BASS.NET API for the Un4seen BASS Audio LibraryBassBASS_ChannelSetDSP Method BASS.NET API for the Un4seen BASS Audio Library
Sets up a user DSP function on a stream, MOD music, or recording channel.

Namespace: Un4seen.Bass
Assembly: Bass.Net (in Bass.Net.dll) Version: 2.4.12.0
Syntax

[DllImportAttribute("bass.dll", CharSet = CharSet.Unicode)]
public static int BASS_ChannelSetDSP(
	int handle,
	DSPPROC proc,
	IntPtr user,
	int priority
)

Parameters

handle
Type: SystemInt32
The channel handle... a HSTREAM, HMUSIC, or HRECORD.
proc
Type: Un4seen.BassDSPPROC
The callback function (see DSPPROC).
user
Type: SystemIntPtr
User instance data to pass to the callback function.
priority
Type: SystemInt32
The priority of the new DSP, which determines it's position in the DSP chain - DSPs with higher priority are called before those with lower.

Return Value

Type: Int32
If succesful, then the new DSP's handle is returned, else 0 is returned. Use BASS_ErrorGetCode to get the error code.
Remarks

The channel does not have to be playing to set a DSP function, they can be set before and while playing.

Equally, you can also remove them at any time. Use BASS_ChannelRemoveDSP(Int32, Int32) to remove a DSP function.

Multiple DSP functions may be used per channel, in which case the order that the functions are called is determined by their priorities. Any DSPs that have the same priority are called in the order that they were added.

DSP functions can be applied to MOD musics and streams, but not samples. If you want to apply a DSP function to a sample, then you should stream the sample.

ERROR CODEDescription
BASS_ERROR_HANDLEhandle is not a valid channel.

Examples

The following example shows a little gain amplifier, assuming you are processing 32-bit BASS_SAMPLE_FLOAT!
VB
Private _gainDB As Single = 0F
Private _stream As Integer = 0
Private _myDSPProc As DSPPROC ' make it global, so that the GC can not remove it
...
_gainDB = 6f; // amplify by +6dB
_stream = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, 
               BASSFlag.BASS_STREAM_AUTOFREE Or BASSFlag.BASS_SAMPLE_FLOAT)
' set a DSP user callback method
_myDSPProc = New DSPPROC(AddressOf MyDSPGain)
' set the user DSP callback
Bass.BASS_ChannelSetDSP(_stream, _myDSPProc, IntPtr.Zero, 0)
...
' this is the actual processing method
Private Sub MyDSPGain(handle As Integer, channel As Integer, 
                      buffer As IntPtr, length As Integer, user As IntPtr)
  ' the global variable _gainDB contains the amplification value in dB!
  If _gainDB = 0F OrElse length = 0 OrElse buffer = IntPtr.Zero Then
    Return
  End If 
  ' convert the _gainDB value to a float
  Dim _gainAmplification As Single = CSng(Math.Pow(10.0, _gainDB / 20.0))
  ' number of bytes in 32-bit floats, since length is in bytes
  Dim l4 As Integer = length / 4
  Dim data(l4 - 1) As Single
  ' copy from managed to unmanaged memory
  Marshal.Copy(buffer, data, 0, l4)
  ' apply gain, assumeing using 32-bit floats (no clipping here ;-)
  Dim a As Integer
  For a = 0 To l4 - 1
    data(a) = data(a) * _gainAmplification
  Next a
  ' copy back from unmanaged to managed memory
  Marshal.Copy(data, 0, buffer, l4)
End Sub
private float _gainDB = 0f;
private int _stream = 0;
private DSPPROC _myDSPProc; // make it global, so that the GC can not remove it
...
_gainDB = 6f; // amplify by +6dB
_stream = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, 
               BASSFlag.BASS_STREAM_AUTOFREE | BASSFlag.BASS_SAMPLE_FLOAT);
// set a DSP user callback method
_myDSPProc = new DSPPROC(MyDSPGain);
// set the user DSP callback
Bass.BASS_ChannelSetDSP(_stream, _myDSPProc, IntPtr.Zero, 0);
...
// this is the actual processing method
private void MyDSPGain(int handle, int channel, IntPtr buffer, int length, IntPtr user)
{
  // the global variable _gainDB contains the amplification value in dB!
  if (_gainDB == 0f || length == 0 || buffer == IntPtr.Zero)
    return;

  // convert the _gainDB value to a float
  float _gainAmplification = (float)Math.Pow(10d, _gainDB / 20d);
  // number of bytes in 32-bit floats, since length is in bytes
  int l4 = length/4;
  float[] data = new float[l4];
  // copy from managed to unmanaged memory
  Marshal.Copy(buffer, data, 0, l4);
  // apply gain, assumeing using 32-bit floats (no clipping here ;-)
  for (int a=0; a<l4; a++)
    data[a] = data[a] * _gainAmplification;
  // copy back from unmanaged to managed memory
  Marshal.Copy(data, 0, buffer, l4);
}
This example is type safe but 'slow', since two copy operations are involved. One from unmanaged BASS to managed .NET and when processing has been done locally from .NET back to BASS. However, for VB.Net users this is almost the only way to do it.

C# user can be a little more lucky, since C# supports unsafe code blocks and native pointer access - which will be shown in the following example:

private unsafe void MyDSPGain(int handle, int channel, IntPtr buffer, int length, IntPtr user)
{
  if (_gainDB == 1f || length == 0 || buffer == IntPtr.Zero)
    return;

  // convert the _gainDB value to a float
  float _gainAmplification = (float)Math.Pow(10d, _gainDB / 20d);
  // length is in bytes, so the number of floats to process is length/4 
  int l4 = length / 4;
  // cast the given buffer IntPtr to a native pointer to float values
  float *data = (float*)buffer;
  for (int a=0; a<l4; a++)
  {
    data[a] = data[a] * _gainAmplification;
    // alternatively you can also use:
    // *data = *data * _gainAmplification;
    // data++;
  }
}
See Also

Reference