Author Topic: [SOLVED] Weird AAC streaming issue with reported bitrate  (Read 216 times)

Chris Oakley

  • Posts: 206
I'm seeing something weird when streaming to AAC with the reported bit rate. If I use the below code:

Code: [Select]
        Bass.BASS_Init(0, 44100, BASSFlag.BASS_DEFAULT, IntPtr.Zero) 'Set to no sound device
        Dim _Mixer As Integer = BassMix.BASS_Mixer_StreamCreate(44100, 2, BASSFlag.BASS_DEFAULT Or BASSFlag.BASS_MIXER_NONSTOP) 'Create a mixer
        Bass.BASS_ChannelPlay(_Mixer, False) 'Play mixer

        'Dim _Stream As Integer = Bass.BASS_StreamCreateFile("SOUND FILE", 0, 0, BASSFlag.BASS_STREAM_DECODE Or BASSFlag.BASS_STREAM_PRESCAN) 'Load a sound
        'BassMix.BASS_Mixer_StreamAddChannel(_Mixer, _Stream, BASSFlag.BASS_DEFAULT) 'Add to mixer

        Dim _EncoderString As String = "ffmpeg.exe -loglevel -8 -f s16le -ac 2 -ar 44100 -i - -f adts -b:a 128k  -c:a aac -"
        Dim _EncoderContent As String = BassEnc.BASS_ENCODE_TYPE_AAC
        Dim _Encoder As Integer = BassEnc.BASS_Encode_Start(_Mixer, _EncoderString, BASSEncode.BASS_ENCODE_NOHEAD Or BASSEncode.BASS_ENCODE_FP_16BIT Or BASSEncode.BASS_ENCODE_LIMIT, Nothing, IntPtr.Zero)
        BassEnc.BASS_Encode_CastInit(_Encoder, "URL", "PASSWORD", _EncoderContent, "", "", "", "", Nothing, 128, False)

This reports:

Stream is up (HE-AAC @ 2 kbps, 44.1 kHz)

However, if you uncomment the Dim _Stream... bit so you end up with:

Code: [Select]
        Bass.BASS_Init(0, 44100, BASSFlag.BASS_DEFAULT, IntPtr.Zero) 'Set to no sound device
        Dim _Mixer As Integer = BassMix.BASS_Mixer_StreamCreate(44100, 2, BASSFlag.BASS_DEFAULT Or BASSFlag.BASS_MIXER_NONSTOP) 'Create a mixer
        Bass.BASS_ChannelPlay(_Mixer, False) 'Play mixer

        Dim _Stream As Integer = Bass.BASS_StreamCreateFile("SOUND FILE", 0, 0, BASSFlag.BASS_STREAM_DECODE Or BASSFlag.BASS_STREAM_PRESCAN) 'Load a sound
        BassMix.BASS_Mixer_StreamAddChannel(_Mixer, _Stream, BASSFlag.BASS_DEFAULT) 'Add to mixer

        Dim _EncoderString As String = "ffmpeg.exe -loglevel -8 -f s16le -ac 2 -ar 44100 -i - -f adts -b:a 128k  -c:a aac -"
        Dim _EncoderContent As String = BassEnc.BASS_ENCODE_TYPE_AAC
        Dim _Encoder As Integer = BassEnc.BASS_Encode_Start(_Mixer, _EncoderString, BASSEncode.BASS_ENCODE_NOHEAD Or BASSEncode.BASS_ENCODE_FP_16BIT Or BASSEncode.BASS_ENCODE_LIMIT, Nothing, IntPtr.Zero)
        BassEnc.BASS_Encode_CastInit(_Encoder, "URL", "PASSWORD", _EncoderContent, "", "", "", "", Nothing, 128, False)

It then reports:

Stream is up (HE-AAC @ 128 kbps (VBR), 44.1 kHz)

Which is almost what I would expect, I'm not sure why it thinks it's VBR, because I'm not telling the encoder string to use VBR.

However, what is going on with the bit rate and why do I need to add a channel to the mixer in order for this to correct itself? Surely if I have mixer outputting to the no sound device on its own it should be okay.
« Last Edit: 10 Oct '22 - 20:15 by Chris Oakley »

Ian @ un4seen

  • Administrator
  • Posts: 24732
Re: Weird AAC streaming issue with reported bitrate
« Reply #1 on: 7 Oct '22 - 14:24 »
I believe AAC encoding is always VBR, but perhaps ffmpeg has a "constrained" VBR mode? In normal VBR, silence can often be reduced to almost nothing, resulting in a very low bitrate. A constrained VBR mode should keep the bitrate at a more consistent level regardless of the sound.

Chris Oakley

  • Posts: 206
Re: Weird AAC streaming issue with reported bitrate
« Reply #2 on: 7 Oct '22 - 15:07 »
Thanks Ian, so it should be CBR as that's what the command line is configured for. So that's a puzzle on it's own.

So is the code okay? I'm not missing anything?

Ian @ un4seen

  • Administrator
  • Posts: 24732
Re: Weird AAC streaming issue with reported bitrate
« Reply #3 on: 7 Oct '22 - 16:08 »
Yes, your code looks fine. It is generally best to start the encoder in a paused state (via BASS_ENCODE_PAUSE flag) though, so that you can setup the casting before any data is encoded, which ensures that the casting doesn't miss anything, eg. headers. Alternatively, you can achieve the same by delaying starting the mixer until after the encoding/casting is setup on it.

Regarding possibly constraining the bitrate with ffmpeg, I found this:

   https://trac.ffmpeg.org/wiki/Limiting%20the%20output%20bitrate

Chris Oakley

  • Posts: 206
Re: Weird AAC streaming issue with reported bitrate
« Reply #4 on: 8 Oct '22 - 19:03 »
Thanks Ian. I couldn't find a way to make ffmpeg report the correct bitrate, but discovered it is reported at the time of cast init so, it's a bit hacky, but I now just generate 1 second of inaudible audio, add this into the mixer on loop and then when connection is made simply remove it and free it then it connects with the proper details.

Code: [Select]
        Bass.BASS_Init(0, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero) 'Set to no sound device
        Dim _Mixer As Integer = BassMix.BASS_Mixer_StreamCreate(44100, 2, BASSFlag.BASS_DEFAULT Or BASSFlag.BASS_MIXER_NONSTOP) 'Create a mixer
        Bass.BASS_ChannelPlay(_Mixer, False) 'Play mixer
        Dim _EncoderString As String = "ffmpeg.exe -loglevel -8 -f s16le -ac 2 -ar 44100 -i - -f adts -b:a 128k  -c:a aac -"
        Dim _EncoderContent As String = BassEnc.BASS_ENCODE_TYPE_AAC
        Dim _Encoder As Integer = BassEnc.BASS_Encode_Start(_Mixer, _EncoderString, BASSEncode.BASS_ENCODE_NOHEAD Or BASSEncode.BASS_ENCODE_FP_16BIT Or BASSEncode.BASS_ENCODE_LIMIT, Nothing, IntPtr.Zero)
        Dim _len As Integer = CInt(Bass.BASS_ChannelSeconds2Bytes(_Mixer, 1)) + 44
        Dim _buf() As Byte = {82, 73, 70, 70, 54, 177, 2, 0, 87, 65, 86, 69, 102, 109, 116, 32, 18, 0, 0, 0, 1, 0, 2, 0, 68, 172, 0, 0, 16, 177, 2, 0, 4, 0, 16, 0, 0, 0, 100, 97, 116, 97, 16, 177, 2}
        Array.Resize(_buf, _len)
        For i As Integer = 45 To _len - 1
            _buf(i) = 20 'Alter the buffer data to 20 as anything less doesn't have the desired effect
        Next
        Dim _hGCFile As GCHandle = GCHandle.Alloc(_buf, GCHandleType.Pinned)
        Dim _Stream As Integer = Bass.BASS_StreamCreateFile(_hGCFile.AddrOfPinnedObject(), 0, _buf.Length, BASSFlag.BASS_STREAM_DECODE Or BASSFlag.BASS_SAMPLE_LOOP Or BASSFlag.BASS_SAMPLE_FLOAT)
        BassMix.BASS_Mixer_StreamAddChannel(_Mixer, _Stream, BASSFlag.BASS_DEFAULT) 'Add to mixer
        BassEnc.BASS_Encode_CastInit(_Encoder, "URL", "PASSWORD", _EncoderContent, "", "", "", "", Nothing, 128, False)
        Bass.BASS_StreamFree(_Stream)

I'm sure there is a more elegant way of doing this, but hopefully this may help anyone else who is stuck in the same puzzle, or perhaps someone can shed some extra light on this situation.