19 May '13 - 17:47 *
Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length
 
   Home   Help Search Login Register  
Pages: [1]
  Reply  |  Print  
Author Topic: How to reduce latency in recorder->mixer  (Read 714 times)
MikeV
Posts: 88


« on: 12 Oct '11 - 14:26 »
Reply with quoteQuote

I have built a simple mixer which, for now, is fed by a recorder channel. Init code

BASS_Init(-1, 44100, 0, Forms::Application->Handle, NULL);
BASS_SetConfig(BASS_CONFIG_UPDATEPERIOD, 50);
BASS_SetConfig(BASS_CONFIG_BUFFER, 100);
hMixer = BASS_Mixer_StreamCreate(44100, 2, BASS_MIXER_NONSTOP);

The latency is random, but never as low as 100 ms. I checked the amount of data in the buffers and it appeared the recorder has quite a lot of bytes, explaining the extra latency. How can I reduce that? Here's how I add the recorder to the mixer

hRecord = BASS_RecordStart(44100, 2, BASS_SAMPLE_FLOAT, NULL, 0);
BASS_ChannelPlay(hMixer, TRUE);
BASS_Mixer_StreamAddChannel(hMixer, hRecord, BASS_MIXER_FILTER|BASS_MIXER_LIMIT|BASS_MIXER_BUFFER);

the only other relevant code is checking of the data buffers

Label1->Caption=BASS_ChannelGetData(hRecord, NULL, BASS_DATA_AVAILABLE);
Label2->Caption=BASS_ChannelGetData(hMixer, NULL, BASS_DATA_AVAILABLE);

and getting the level for a peak meter

level = BASS_ChannelGetLevel(hMixer);
Logged
Ian @ un4seen
Administrator
Posts: 15244


« Reply #1 on: 12 Oct '11 - 15:34 »
Reply with quoteQuote

It could be that the recording and playback devices are actually going at slightly different speeds, ie. not at precisely 44100 Hz. Is the latency increasing over time? If so, to compensate for that, the playback rate could be increased slightly via the mixer's BASS_ATTRIB_FREQ setting.

For another perspective, do you see the same thing happen with the latency in the pre-compiled LIVEFX.EXE example? (in the C\BIN directory)
Logged
MikeV
Posts: 88


« Reply #2 on: 12 Oct '11 - 17:05 »
Reply with quoteQuote

I often see a large (50k) recorder buffer from the start, I have not even listened for more than a minute so do not know what the latency does over time (I thought setting the BASS_MIXER_LIMIT flag synced the mixer to the recorder channel?). The initial latency is the problem. I would have expected some kind of synced starting mechanism that takes care of this, i.e. make sure we start with the minimal buffer size. As this is such a basic principle I was sure I was doing something wrong.

I have tried to find a mixer demo but could not find any.
Logged
MikeV
Posts: 88


« Reply #3 on: 13 Oct '11 - 09:45 »
Reply with quoteQuote

To give some background info: I want to create an audio mixer along an existing video app so bought a license for BASS assuming this would be easy. For this very reason I need to have a predictable (and low) latency, not a random latency based on whatever's available in the recorder's buffer. Is my requirement that unique  Huh
Logged
Ian @ un4seen
Administrator
Posts: 15244


« Reply #4 on: 13 Oct '11 - 14:56 »
Reply with quoteQuote

I often see a large (50k) recorder buffer from the start...

Is that 50k from the recording buffer alone, not including the mixer's output buffer? If so, that translates to around 140ms of data in the buffer, which is strange given that the mixer and recording appear to be started at about the same time in the code above (so no time for excess data to build up in the recording buffer). Perhaps the order of the BASS_ChannelPlay and BASS_Mixer_StreamAddChannel calls is influencing it (see the LIMIT/NONSTOP comments below).

The recorded data will be delivered by Windows in blocks, usually of around 31ms on Vista/7. To confirm how the data is arriving there, you can do something like this...

hRecord = BASS_RecordStart(44100, 2, BASS_SAMPLE_FLOAT, NULL, 0);
printf("%d: start\n", timeGetTime());
DWORD avail=0, c=0;
while (1) {
DWORD a=BASS_ChannelGetData(hRecord, NULL, BASS_DATA_AVAILABLE);
if (a!=avail) {
printf("%d: %d\n", timeGetTime(), a-avail);
avail=a;
if (++c==10) break;
}
}

Please copy'n'paste the output from that.

I thought setting the BASS_MIXER_LIMIT flag synced the mixer to the recorder channel?

The BASS_MIXER_LIMIT flag will just limit the amount of data that the mixer produces to the amount available from the recording channel, eg. if there is nothing in the recording buffer then the mixer won't produce any output.

Note the BASS_MIXER_NONSTOP flag tells the mixer to produce silence (instead of nothing) when there is no data available from its source(s). The BASS_MIXER_LIMIT flag will override that, but the mixer is started (via BASS_ChannelPlay) before the recording is added in the code above, so the BASS_MIXER_NONSTOP flag will have effect initially, ie. the mixer's output buffer will initially be filled with silence.

I need to have a predictable (and low) latency

Is using ASIO a possibility for you, eg. BASSASIO? That is better suited to predictable full duplex latency, as the driver's input and output processing is synchronised.
Logged
MikeV
Posts: 88


« Reply #5 on: 13 Oct '11 - 15:50 »
Reply with quoteQuote

No, this has to work on thousands of different PCs so I cannot assume all of them support ASIO. It's been a while since I read up on this, but assume it still is an option for the more exclusive cards. Would WASAPI give me any additional benefits? I have understood this is standard on Vista+?

I'll try your code.
Logged
saga
Posts: 1362


« Reply #6 on: 13 Oct '11 - 20:53 »
Reply with quoteQuote

It's been a while since I read up on this, but assume it still is an option for the more exclusive cards.
Using the ASIO4All driver, ASIO can be used on any soundcard.
Logged
MikeV
Posts: 88


« Reply #7 on: 14 Oct '11 - 07:21 »
Reply with quoteQuote

Is that so? It used to be almost any sound card or at the very least occasionally required some tweaking, which in my case is a no go.
Logged
MikeV
Posts: 88


« Reply #8 on: 14 Oct '11 - 10:58 »
Reply with quoteQuote

2134908: start
2134942: 11032
2134990: 11032
2135016: 11032
2135049: 11032
2135078: 11032
2135107: 11032
2135129: 11032
2135155: 11032
2135211: 11032
2135226: 11032
Logged
Ian @ un4seen
Administrator
Posts: 15244


« Reply #9 on: 14 Oct '11 - 14:21 »
Reply with quoteQuote

Those numbers look as expected (the data is arriving in ~31ms blocks), although the timing looks a bit off (it isn't arriving at exactly ~31ms intervals). So that doesn't explain the ~140ms of buffered data you're seeing. The next thing to check is how much data the mixer is requesting from the recording and how much is left behind, like this...

hRecord = BASS_RecordStart(44100, 2, BASS_SAMPLE_FLOAT, NULL, 0);
printf("%d: start\n", timeGetTime());
BASS_ChannelSetDSP(hRecord, LogDSP, 0, 0);

...

void CALLBACK LogDSP(HDSP handle, DWORD channel, void *buffer, DWORD length, void *user)
{
printf("%d: %d / %d\n", timeGetTime(), length, BASS_ChannelGetData(channel, 0, BASS_DATA_AVAILABLE));
}

Please copy'n'paste the output from that.
Logged
Pages: [1]
  Reply  |  Print  
 
Jump to:  

Powered by SMF 1.1.18 | SMF © 2013, Simple Machines