Author Topic: AoIP delay in audio after a period.  (Read 685 times)

Chris Oakley

  • Posts: 304
AoIP delay in audio after a period.
« on: 26 Oct '23 - 18:29 »
We've got a weird issue with a particular user using Dante audio https://www.audinate.com/meet-dante

Our application seems to get an audible delay when sending audio via one of Dante's virtual audio devices. It starts off okay, but then we come back to it after a period of time and there is a delay. If we pause the playback we can see in the Sound Control panel in Windows the level meter takes a few seconds to drop. Unpausing, the same happens, it's a few seconds to start again. The levels in the application which are from a DSP Peak, are absolutely fine.

It's just a device in Windows, nothing unusual from that side. We just choose the device index in BASS and open audio in the regular way. The only difference perhaps is we use Mixers which we set to 2 channel, 44100 Khz. Could having a device which is set to 2 channel 24bit 48000Khz cause issues like this?

This is a totally new thing that we've not seen before, and it would be easy to blame a config issue with Dante, but I don't understand what it could be. Regular sound cards don't display this problem.

Anyone else had any issues with BASS using AoIP like Dante?

Chris Oakley

  • Posts: 304
Re: AoIP delay in audio after a period.
« Reply #1 on: 1 Feb '24 - 16:47 »
I'd like to circle back on this because I've a little more info which raises a question. We've got the same issue with this delay on another AoIP system but this one is Wheatnet, as opposed to Dante.

I've narrowed the problem down to a situation where you have a mixer setup going to No Sound and then you do a DSP_StreamCopy which is set to just output to a specific device. In this case one of the Wheatnet audio outputs.

I've got a DSP_PeakLevelMeter on the No Sound mixer and I can see that there is no delay here when I open a file as DECODE and add it into the No Sound mixer.

However, after a period of a few hours there is a noticeable delay between what's playing on the No Sound mixer and what's coming out of the Wheatnet device. The longer you leave it the bigger the delay is. The meter is always spot on, but audibly the sound is delayed.

We are only seeing this on AoIP currently. Regualr USB sound devices or built in sound devices are absolutely fine. Even VB Cables from VB Audio are fine. No build up.

Now obviously I don't know what's happening with regard to the stream copy and it sending it to the output device, but my understanding is that it's supposed to be a synchronized copy of the source buffer - but something timing wise is clearly off.

I did try altering the ATTRIB_FREQ for the No Sound mixer, increasing it, but that just creates glitches in the audio, even upping it by just 1 from 48000 to 48001.
« Last Edit: 1 Feb '24 - 17:29 by Chris Oakley »

Chris Oakley

  • Posts: 304
Re: AoIP delay in audio after a period.
« Reply #2 on: 2 Feb '24 - 18:30 »
I believe I have located the problem. It seems that a mixer set to No Sound and a mixer set to an actual device output must be clocking at different rates.

The reason I've drawn this conclusion is because the only way I've been able to stop the delay is do a DSP_StreamCopy of the No Sound mixer and then plug that into the TargetMixer which is assigned to the physical WNIP Output and created at 48000, but with the freq attrib set to 48010 like this:
Code: [Select]
Bass.BASS_ChannelSetAttribute(_TargetMixer, BASSAttribute.BASS_ATTRIB_FREQ, 48010)

Now, whilst this works, it oddly does create ever so slight glitches on the audio. I assume this is because I've plucked an arbitary value of 48010 which is 10 more above what the mixer is set as.

So my question is, how on earth am I, as a developer, supposed to handle this properly?

Ian @ un4seen

  • Administrator
  • Posts: 25725
Re: AoIP delay in audio after a period.
« Reply #3 on: 5 Feb '24 - 16:59 »
Yes, when feeding the input from one device to the output of another, there is unfortunately a chance that they'll be going at slightly different rates, ie. one or both may not be exactly at the specified rate. You can detect that by monitoring buffer levels, and correct it by adjusting the playback rate via BASS_ATTRIB_FREQ (as you did). Basically, if the buffer levels are rising then increase the playback rate, and if they're falling then reduce it. An example of doing this can be found in the LIVEFX.C example included in the BASS package.

Chris Oakley

  • Posts: 304
Re: AoIP delay in audio after a period.
« Reply #4 on: 5 Feb '24 - 18:39 »
Oh wow. Is this not something BASS should be handling itself?

Chris Oakley

  • Posts: 304
Re: AoIP delay in audio after a period.
« Reply #5 on: 5 Feb '24 - 20:27 »
I've had a look at the example but I cannot figure out how I'm supposed to implement this practise. I'm not taking a recording channel, I'm taking a No Sound mixer, making a StreamCopy and passing that into a mixer which is on the device I want it to go out to.

How can I monitor the buffer on the output mixer? I did try by using:
Code: [Select]
Dim _buf As Integer = Bass.BASS_ChannelGetData(_PhysicalId, IntPtr.Zero, BASSData.BASS_DATA_AVAILABLE)

but I had no way of knowing how to use the numbers to my advantage.

Chris Oakley

  • Posts: 304
Re: AoIP delay in audio after a period.
« Reply #6 on: 6 Feb '24 - 09:22 »
Some example numbers from the above code are these. I log them every 10 seconds. This is from when the app started and there was no delay:
Code: [Select]
2024-02-05 20:50:12.003 (2024-02-05 14:50:12.003) : Physical Device Buffer 10224
2024-02-05 20:50:22.005 (2024-02-05 14:50:22.005) : Physical Device Buffer 9968
2024-02-05 20:50:32.009 (2024-02-05 14:50:32.009) : Physical Device Buffer 11128
2024-02-05 20:50:42.020 (2024-02-05 14:50:42.020) : Physical Device Buffer 10936
2024-02-05 20:50:52.025 (2024-02-05 14:50:52.025) : Physical Device Buffer 9784
2024-02-05 20:51:02.026 (2024-02-05 14:51:02.026) : Physical Device Buffer 9588
2024-02-05 20:51:12.026 (2024-02-05 14:51:12.026) : Physical Device Buffer 11508
2024-02-05 20:51:22.035 (2024-02-05 14:51:22.035) : Physical Device Buffer 9784
2024-02-05 20:51:32.041 (2024-02-05 14:51:32.041) : Physical Device Buffer 10744
2024-02-05 20:51:42.052 (2024-02-05 14:51:42.052) : Physical Device Buffer 10552
2024-02-05 20:51:52.052 (2024-02-05 14:51:52.052) : Physical Device Buffer 10552

This is from the app now there is a delay of about 1 second:
Code: [Select]
2024-02-06 09:18:59.370 (2024-02-06 03:18:59.370) : Physical Device Buffer 10756
2024-02-06 09:19:09.377 (2024-02-06 03:19:09.377) : Physical Device Buffer 11328
2024-02-06 09:19:19.377 (2024-02-06 03:19:19.377) : Physical Device Buffer 11332
2024-02-06 09:19:29.381 (2024-02-06 03:19:29.381) : Physical Device Buffer 10556
2024-02-06 09:19:39.394 (2024-02-06 03:19:39.394) : Physical Device Buffer 9992
2024-02-06 09:19:49.398 (2024-02-06 03:19:49.398) : Physical Device Buffer 11116
2024-02-06 09:19:59.407 (2024-02-06 03:19:59.407) : Physical Device Buffer 11372
2024-02-06 09:20:09.408 (2024-02-06 03:20:09.408) : Physical Device Buffer 11128
2024-02-06 09:20:19.416 (2024-02-06 03:20:19.416) : Physical Device Buffer 9596
2024-02-06 09:20:29.424 (2024-02-06 03:20:29.424) : Physical Device Buffer 9984
2024-02-06 09:20:39.424 (2024-02-06 03:20:39.424) : Physical Device Buffer 9784
2024-02-06 09:20:49.438 (2024-02-06 03:20:49.438) : Physical Device Buffer 11120
2024-02-06 09:20:59.443 (2024-02-06 03:20:59.443) : Physical Device Buffer 10952
2024-02-06 09:21:09.445 (2024-02-06 03:21:09.445) : Physical Device Buffer 10756

I can't see anything there that's going to be any use to me.

Ian @ un4seen

  • Administrator
  • Posts: 25725
Re: AoIP delay in audio after a period.
« Reply #7 on: 6 Feb '24 - 16:40 »
Oh wow. Is this not something BASS should be handling itself?

I'll try to think of something, but the problem is BASS doesn't know where the stream's data is ultimately coming from in this case, so it can't automatically monitor that. For example, taking the LIVEFX.C example, BASS just sees a STREAMPROC - it has no knowledge of the fact that it's being fed by a recording channel. One case where some automatic monitoring/adjusting could perhaps be implemented is a recording channel (or a push stream) plugged into a mixer, as the mixer can check how much data the source has buffered then.

I've had a look at the example but I cannot figure out how I'm supposed to implement this practise. I'm not taking a recording channel, I'm taking a No Sound mixer, making a StreamCopy and passing that into a mixer which is on the device I want it to go out to.

How can I monitor the buffer on the output mixer? I did try by using:
Code: [Select]
Dim _buf As Integer = Bass.BASS_ChannelGetData(_PhysicalId, IntPtr.Zero, BASSData.BASS_DATA_AVAILABLE)

You would generally want to monitor the input buffer rather than the output buffer, as that's where the build-up of data (increasing latency) is likely to be. For example, the LIVEFX.C example monitors the recording channel's buffer. DSP_StreamCopy creates a "push" stream, so it should be possible to monitor its buffer level with BASS_StreamPutData (with length=0) - BASS_ChannelGetData with BASS_DATA_AVAILABLE won't work because it doesn't have a playback or recording buffer.

Chris Oakley

  • Posts: 304
Re: AoIP delay in audio after a period.
« Reply #8 on: 6 Feb '24 - 17:18 »
I see. So this?
Code: [Select]
Dim _bufsize As Integer = Bass.BASS_StreamPutData(_SplitChannel.StreamId, IntPtr.Zero, 0)

When I do this it returns 5760 on my system. Does that sound about right for 2 chan 48000 Hz?

Ian @ un4seen

  • Administrator
  • Posts: 25725
Re: AoIP delay in audio after a period.
« Reply #9 on: 6 Feb '24 - 17:42 »
That's equivalent to either 30ms or 15ms, depending on whether it's 16-bit or floating-point (you can use BASS_ChannelBytes2Seconds to convert a byte count to seconds without needing to know what the sample format is). Can't really say whether it looks right, but it's not a lot, so won't be causing a big delay. I guess this reading is at the start, not when the problem is happening?

Chris Oakley

  • Posts: 304
Re: AoIP delay in audio after a period.
« Reply #10 on: 6 Feb '24 - 17:44 »
Yes this is right at the start. I've now got this monitoring on the offending system and will track its change. Hopefully it will eventually get larger so I've got something to work with.

Will report back when it's had a few hours.

Chris Oakley

  • Posts: 304
Re: AoIP delay in audio after a period.
« Reply #11 on: 6 Feb '24 - 19:07 »
So it started off with this as its buffer:
Code: [Select]
2024-02-06 17:28:01.273 (2024-02-06 11:28:01.273) : Physical Device Buffer 3840

and now it's crept up to:
Code: [Select]
2024-02-06 19:01:44.798 (2024-02-06 13:01:44.798) : Physical Device Buffer 26880

Based on your suggestions and the example LiveFX project if I check this size every 10 seconds and do this:

Code: [Select]
Dim _bufphysical As Int64 = Bass.BASS_StreamPutData(_SplitChannel.StreamId, IntPtr.Zero, 0) 'The actual buffer size of the DSP_StreamCopy in bytes
Dim _bufsec As Double = Bass.BASS_ChannelBytes2Seconds(_SplitChannel.StreamId, _bufphysical) 'The actual buffer size of the DSP_StreamCopy in seconds
If _bufsec > 0.1 Then 'The  buffer has wandered a bit too far beyond 100ms
    m_AdjustedRate = CInt(m_AdjustedRate * 1.001) 'Speed up rate a touch
    Bass.BASS_ChannelSetAttribute(_PhysicalId, BASSAttribute.BASS_ATTRIB_FREQ, m_AdjustedRate) 'Set the frequency on the mixer
End If
If _bufsec < 0.03 Then 'The buffer has wandered a bit too far under 30ms
    m_AdjustedRate = CInt(m_AdjustedRate * 0.999) 'Slow down rate a touch
    Bass.BASS_ChannelSetAttribute(_PhysicalId, BASSAttribute.BASS_ATTRIB_FREQ, m_AdjustedRate) 'Set the frequency on the mixer
End If

Would this do the job? Also am I being a bit too excessive with my thresholds of 30ms and 100ms?

Ian @ un4seen

  • Administrator
  • Posts: 25725
Re: AoIP delay in audio after a period.
« Reply #12 on: 7 Feb '24 - 14:20 »
You could start with 30/100ms thresholds and see how it goes. I would check it more frequently than every 10s though, eg. the LIVEFX.C example checks it every update cycle. I would also suggest doing it in a DSP function set (via BASS_ChannelSetDSP) on the same channel (StreamId), so that it's in sync with the processing. Note in that case the BASS_StreamPutData value won't include the data received by the DSP function (because it's already left the push stream's buffer), so you may want to add that (the DSPPROC "length" parameter).

Chris Oakley

  • Posts: 304
Re: AoIP delay in audio after a period.
« Reply #13 on: 7 Feb '24 - 14:55 »
I see, so what you're saying regarding the correct value to monitor is this?
Code: [Select]
    Private Sub CheckDspProc(handle As Integer, channel As Integer, buffer As IntPtr, length As Integer, user As IntPtr)

            Dim _bufphysical As Int64 = Bass.BASS_StreamPutData(channel, IntPtr.Zero, 0) 'The actual buffer size of the DSP_StreamCopy in bytes
            Dim _buflength As Int64 = _bufphysical + length

    End Sub

_buflength would then contain the magic number I need to check?

Ian @ un4seen

  • Administrator
  • Posts: 25725
Re: AoIP delay in audio after a period.
« Reply #14 on: 7 Feb '24 - 15:29 »
Yes, that will tell you how much data was in the buffer at the start of the current cycle. Note that if the stream isn't floating-point (BASS_SAMPLE_FLOAT) and you have BASS_CONFIG_FLOATDSP enabled then you will need to account for that, eg. divide "length" by 2.

Chris Oakley

  • Posts: 304
Re: AoIP delay in audio after a period.
« Reply #15 on: 28 Feb '24 - 16:02 »
I just wanted to circle back on this. I have for now managed to solve the issue by implementing my own buffer monitoring. It's an invisible dance but the process I've implemented is working great. If anyone else is having the same problem, what I've done is get the buffer size in the DSPProc in bytes. I then convert that to milliseconds and I monitor this value.

If the buffer size goes over 100ms I then check to see if the buffer size is larger than the last buffer size check then if it's been more than 1 second since the last adjustment I up the sample rate on the physical mixer by .01% Giving it a second before making another adjustment gives the updated sample rate a chance to have an effect on the buffer. If after a second it's still not coming down then it will up it again.

I also check the buffer size to see if it's lower than 40ms. If it is, I then check to see if the sample rate isn't at the proper rate i.e 48000. If it isn't then I set it to this on the physical mixer. This then prevents the buffer becoming too empty.

This seems to have done the trick. No more delay build up. I'm also logging out the changes so I can see how often it's having to adjust and it seems to have to do it every 10 or so minutes on the system I'm testing it on.

It is a bit of a ball ache having to handle this though because you immediately don't think there is an issue in BASS that isn't being dealt with, so you're burning up your evenings and weekends trying to find what you've done wrong, or if there is a misconfig on the system your software is on.

It eventually transpires that you haven't done anything wrong.

Ian @ un4seen

  • Administrator
  • Posts: 25725
Re: AoIP delay in audio after a period.
« Reply #16 on: 29 Feb '24 - 15:19 »
Great to hear that you've got it working well now.