BASS.NET API for the Un4seen BASS Audio LibraryBassEncBASS_Encode_StartACM Method (Int32, IntPtr, BASSEncode, ENCODEPROC, IntPtr)BASS.NET API for the Un4seen BASS Audio Library
Sets up an encoder on a channel, using an ACM codec and sending the output to a user defined function.

Namespace: Un4seen.Bass.AddOn.Enc
Assembly: Bass.Net (in Bass.Net.dll) Version:

[DllImportAttribute("bassenc.dll", CharSet = CharSet.Auto)]
public static int BASS_Encode_StartACM(
	int handle,
	IntPtr form,
	BASSEncode flags,
	IntPtr user


Type: SystemInt32
The channel handle... a HSTREAM, HMUSIC, or HRECORD.
Type: SystemIntPtr
ACM codec output format (buffer as returned by BASS_Encode_GetACMFormat(Int32, IntPtr, Int32, String, BASSACMFormat)).
Type: Un4seen.Bass.AddOn.EncBASSEncode
A combination of these flags BASSEncode:
BASS_ENCODE_PAUSEStart the encoder paused.
BASS_ENCODE_AUTOFREEAutomatically free the encoder when the source channel is freed.
BASS_ENCODE_QUEUEQueue data to feed the encoder asynchronously. This prevents the data source (DSP system or BASS_Encode_Write(Int32, IntPtr, Int32) call) getting blocked by the encoder, but if data is queud more quickly than the encoder can process it, that could result in lost data.
BASS_ENCODE_CAST_NOLIMITDon't limit the data rate (to real-time speed) when sending to a Shoutcast or Icecast server.
BASS_ENCODE_LIMITLimit the data rate to real-time speed, by introducing a delay when the rate is too high. With BASS 2.4.6 or above, this flag is ignored when the encoder is fed in a playback buffer update cycle (including BASS_Update(Int32) and BASS_ChannelUpdate(Int32, Int32) calls), to avoid possibly causing playback buffer underruns. Except for in those instances, this flag is applied automatically when the encoder is feeding a Shoutcast or Icecast server.
Type: Un4seen.Bass.AddOn.EncENCODEPROC
Callback function to receive the encoded data.
Type: SystemIntPtr
User instance data to pass to the callback function.

Return Value

Type: Int32
The encoder handle is returned if the encoder is successfully started, else 0 is returned. Use BASS_ErrorGetCode to get the error code.

The ACM encoder allows installed ACM (Audio Compression Manager) codecs to be used for encoding. The codec used is determined by the contents of the form parameter. The BASS_Encode_GetACMFormat(Int32, IntPtr, Int32, String, BASSACMFormat) function can be used to initialize that.

Internally, the sending of sample data to the encoder is implemented via a DSP callback on the channel. That means when you play the channel (or call BASS_ChannelGetData(Int32, IntPtr, Int32) if it's a decoding channel), the sample data will be sent to the encoder at the same time. The encoding is performed in the DSP callback. There isn't a separate process doing the encoding, as when using an external encoder via BASS_Encode_Start(Int32, String, BASSEncode, ENCODEPROC, IntPtr).

By default, the encoder DSP has a priority setting of -1000, which determines where in the DSP chain the encoding is performed. That can be changed using the BASS_CONFIG_ENCODE_PRIORITY config option (see BASS_SetConfig(BASSConfig, Int32)).

Besides the automatic DSP system, data can also be manually fed to the encoder via the BASS_Encode_Write(Int32, IntPtr, Int32) function. Both methods can be used together, but in general, the "automatic" system ought be paused when using the "manual" system, by use of the BASS_ENCODE_PAUSE flag or the BASS_Encode_SetPaused(Int32, Boolean) function.

When done encoding, use BASS_Encode_Stop(Int32) to close the encoder.

Multiple encoders can be set on a channel. For simplicity, the encoder functions will accept either an encoder handle or a channel handle. When using a channel handle, the function is applied to all encoders that are set on that channel.

ERROR CODEDescription
BASS_ERROR_HANDLEhandle is not valid.
BASS_ERROR_NOTAVAILThe codec specified in form couldn't be initialized.
BASS_ERROR_UNKNOWNSome other mystery problem!


Setup an ACM encoder with a callback to process the encoded data:
' get suggested (maximum) format buffer size
Dim formlen As Integer = BassEnc.BASS_Encode_GetACMFormat(0, IntPtr.Zero, 0, Nothing, BASSACMFormat.BASS_ACM_NONE)
' create a buffer for the codec
Dim buffer(formlen - 1) As Byte
' now create a pinned handle, so that the Garbage Collector will not move this object
Dim hGC As GCHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned)
' get the pointer to that pinned object
Dim codec As IntPtr = hGC.AddrOfPinnedObject()
' let the user choose a codec...
If BassEnc.BASS_Encode_GetACMFormat(channel, codec, formlen, "Choose your format", 
           BASSACMFormat.BASS_ACM_DEFAULT) > 0 Then
  ' create the delegate
  _myEncProc = New ENCODEPROC(AddressOf MyEncoderProc)
  ' begin encoding using the codec with the delegate callback
  Dim encHandle As Integer = BassEnc.BASS_Encode_StartACMFile(channel, codec, 
                                     BASSEncode.BASS_ENCODE_DEFAULT, _myEncProc, IntPtr.Zero)
End If
' free the codec format buffer (you might free it even if encoding is still running)
Private _myEncProc As ENCODEPROC
Private Function MyEncodingWriter(handle As Integer, channel As Integer, 
                                  buffer As IntPtr, length As Integer, user As IntPtr) As Boolean
End Function
// get suggested (maximum) format buffer size
int formlen = BassEnc.BASS_Encode_GetACMFormat(0, IntPtr.Zero, 0, null, BASSACMFormat.BASS_ACM_NONE);
// create a buffer for the codec
byte[] buffer = new byte[formlen];
  fixed (byte* p = buffer)
    // let the user choose a codec...
    if ( BassEnc.BASS_Encode_GetACMFormat( channel, (IntPtr)p, formlen, "Choose your format", 
                 BASSACMFormat.BASS_ACM_DEFAULT) > 0 )
      // create the delegate
      _myEncProc = new ENCODEPROC(MyEncoderProc);
      // begin encoding using the codec with the delegate callback
      int encHandle = BassEnc.BASS_Encode_StartACMFile(channel, (IntPtr)p, BASSEncode.BASS_ENCODE_DEFAULT, _myEncProc, IntPtr.Zero);
// the encoding callback
private ENCODEPROC _myEncProc;  // keep the callback delegate in a global member
private bool MyEncodingWriter(int handle, int channel, IntPtr buffer, int length, IntPtr user)
If you are into C# using native pointers in an unsafe codeblock would be even faster:
See Also