Author Topic: Delay when using BASS_Split_StreamCreate and BASS_Mixer_StreamAddChannel  (Read 357 times)

Fr_bp

  • Posts: 9
Hi,

I have my guitar plugged into an audio interface and a BassAsioHandler to capture the data coming from this interface. I'm trying to split my BassAsioHandler's output channel (a decoding channel) into two signals. Then I use a BASS_BFX_PITCHSHIFT effect to shift the pitch of one of the signals. Next, I use the BASS_Mixer_StreamAddChannel to recombine the two signal together. This emulates an octaver pedal. It all works great and there are no errors, but there is a bit of delay (0.5s) between when I hit the string and the output.

I use the following code:

Code: [Select]
//create the mixer while not using the "no sound" device
Bass.BASS_Init(1, 88200, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero)
Mixer = BassMix.BASS_Mixer_StreamCreate(88200, 2, BASSFlag.BASS_SAMPLE_FLOAT);
Bass.BASS_Init(0, 88200, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero)

...

//initialize the handler and make it a decoding channel
handler = new BassAsioHandler(true, 0, 0, 2, BASSASIOFormat.BASS_ASIO_FORMAT_FLOAT, 88200);
handler.SetFullDuplex(0, BASSFlag.BASS_STREAM_DECODE, false);

//split the decoding channel of the handler
int line1 = BassMix.BASS_Split_StreamCreate(handler.OutputChannel, BASSFlag.BASS_STREAM_DECODE, null);
int line2 = BassMix.BASS_Split_StreamCreate(handler.OutputChannel, BASSFlag.BASS_STREAM_DECODE, null);

//shift the pitch of line2
BASS_BFX_PITCHSHIFT pitchUp = new BASS_BFX_PITCHSHIFT();
int pitchUpHandle = Bass.BASS_ChannelSetFX(line2, BASSFXType.BASS_FX_BFX_PITCHSHIFT, 1);
Bass.BASS_FXGetParameters(pitchUpHandle, pitchUp);
pitchUp.fPitchShift = 2.0f;
Bass.BASS_FXSetParameters(pitchUpHandle, pitchUp);

//recombine line1 and line2
BassMix.BASS_Mixer_StreamAddChannel(Mixer, line1, BASSFlag.BASS_DEFAULT);
BassMix.BASS_Mixer_StreamAddChannel(Mixer, line2, BASSFlag.BASS_DEFAULT);

//play
Bass.BASS_ChannelPlay(Mixer, false);


Is there anything I can do about this delay?


Ian @ un4seen

  • Administrator
  • Posts: 20396
The delay is probably due to the output stream's buffering; you can use BASS_ChannelGetData with BASS_DATA_AVAILABLE (on "Mixer") to check that. As you are already using ASIO input, could you use ASIO output (instead of normal BASS/DirectSound output) too? That will have less buffering/latency.

Fr_bp

  • Posts: 9
Thanks for your reply!

I called the BASS_ChannelGetData method like this, but it writes '0':
Code: [Select]
Console.WriteLine(Bass.BASS_ChannelGetData(Mixer, IntPtr.Zero, (int)BASSData.BASS_DATA_AVAILABLE));
How can I play my Mixer with ASIO? I only know how to do it with BASS.

radio42

  • Posts: 4573
Here you can find an example on using a bass stream with ASIO output using the BassAsioHandler (note, that your mixer stream should be a decoding stream)
http://www.bass.radio42.com/help/html/4a5b6aaf-7c59-0ba8-8ca0-7019303e3879.htm

Code: [Select]
private BassAsioHandler _asio;
...
// not playing anything via BASS, so don't need an update thread
Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_UPDATEPERIOD, 0);
// setup BASS - "no sound" device but 48000 (default for ASIO)
Bass.BASS_Init(0, 48000, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero);
BassAsio.BASS_ASIO_Init(0, BASSASIOInit.BASS_ASIO_THREAD);
...
int stream = Bass.BASS_StreamCreateFile(fileName, 0, 0,
                  BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT);
if (stream != 0)
{
    // assign ASIO output to the first device and channel
    // and assume the ASIO format, samplerate and number of channels from the BASS stream
    _asio = new BassAsioHandler(0, 0, stream);
    // start ASIO
    _asio.Start(0);
}
Instead of the above "stream = BASS_StreamCreateFile..." call you can directly use your mixer stream (just make sure the mixer stream is also a decoding stream).

Fr_bp

  • Posts: 9
I've found a way to playback the guitar input without BASS_ChannelPlay(), using SetMirror() on my handler, but now the FX effects don't work anymore. Is there any way I can use SetMirror() and the DX8/BFX effects at the same time?

Ian @ un4seen

  • Administrator
  • Posts: 20396
No, I'm afraid it won't be possible to set effects on the channel when using SetMirror (which uses BASS_ASIO_ChannelEnableMirror internally), as BASSASIO simply copies the data from one ASIO channel to another then.

Fr_bp

  • Posts: 9
That's too bad!

I still haven't found out what is causing the delay. I currently removed all effects, but the delay is still there... Is there any way I could find out what is causing the delay? Would the playback be faster if I don't use the BassAsioHandler class?

Ian @ un4seen

  • Administrator
  • Posts: 20396
You could try using the BASSASIO functions directly. I'm not a .Net user myself, but in C/C++ it could look something like this:

Code: [Select]
BASS_Init(0, 44100, 0, NULL, NULL); // initialize "no sound" BASS device
BASS_ASIO_Init(device, 0); // initialize ASIO device/driver

BASS_ASIO_ChannelEnable(TRUE, 0, AsioProc, 0); // enable 1st input channel
BASS_ASIO_ChannelSetFormat(TRUE, 0, BASS_ASIO_FORMAT_FLOAT); // set it to floating-point
BASS_ASIO_ChannelEnable(FALSE, 0, AsioProc, 0); // enable 1st output channel
BASS_ASIO_ChannelSetFormat(FALSE, 0, BASS_ASIO_FORMAT_FLOAT); // set it to floating-point

mixer = BASS_Mixer_StreamCreate(BASS_ASIO_GetRate(), 1, BASS_SAMPLE_FLOAT|BASS_STREAM_DECODE); // create output mixer
inputstream = BASS_StreamCreate(BASS_ASIO_GetRate(), 1, BASS_SAMPLE_FLOAT|BASS_STREAM_DECODE, STREAMPROC_PUSH, NULL); // create "push" stream to hold input data
line1 = BASS_Split_StreamCreate(inputstream, BASS_STREAM_DECODE, NULL); // create 1st splitter on it
line2 = BASS_Split_StreamCreate(inputstream, BASS_STREAM_DECODE, NULL); // create 2nd splitter on it
BASS_Mixer_StreamAddChannel(mixer, line1, 0); // plug them into the mixer
BASS_Mixer_StreamAddChannel(mixer, line2, 0); // "
// set FX on line2 here...

BASS_ASIO_Start(0, 1); // start the ASIO device

...

DWORD CALLBACK AsioProc(BOOL isinput, DWORD channel, void *buffer, DWORD length, void *user)
{
if (isinput) { // input channel
BASS_StreamPutData(inputstream, buffer, length); // pass the data to the push stream
return 0;
} else { // output channel
int r = BASS_ChannelGetData(mixer, buffer, length); // get data from the mixer
if (r == -1) r = 0; // an error, no data
return r;
}
}

If you want it to be stereo, you can use BASS_ASIO_ChannelJoin to join the 2nd input channel to the 1st input channel and do the same for the output channels, and change the "chans" parameters accordingly in the BASS_Mixer_StreamCreate and BASS_StreamCreate calls.

The main difference in .Net will be in how you use the ASIOPROC callback function; see the "Callbacks and Delegates" section of the "Interoperating with Unmanaged Code" page in the BASS.Net documentation for information on that. Also see the documentation for details on the mentioned functions.

Fr_bp

  • Posts: 9
I converted the code to C# and surprisingly the delay is gone now! I guess it was just the BassAsioHandler class...

Thanks for your help!