I am streaming audio in C# via naudio running in a separate thread fed via a threadsafe queue. Input into naudio is a stream consisting of 16 bit PCM data, AAC decoded by libfaad2 with PInvoke, as I did not find a native C# AAC decoder. The data consists of a continuous stream originating from live "dab plus" broadcasting sources.
This works all very nice and smooth, with one little exception. The data rates reported by the AAC decoder and naudio do not match. As an example, the libfaad2 decoder reports 48000 Hz sampling rate, having been initialized with the metadata of the broadcast station. NAudio - initialized with this sampling rate - generates a "Buffer full" exception after a short time (30 sec with 512000bytes naudio buffer, the timeout scaling linearly with the buffer size).
The "DiscardOnBufferOverflow" option of naudio is not a viable solution of the problem, as it causes - of course - audible artifacts after that event. When I increase for naudio the reported 48000 Hz by 3000, i.e. initialize the naudio with 51000 Hz, it runs for almost an hour before the buffer overflow exception.
I also recorded a three minutes file with naudio left at 48kHz, sounding perfect.
My question: What might be the reason of the bitrate mismatch between naudio and the AAC decoder when streaming? I really would like to know the reason for this, as I do not want to leave the current hack implemented.
Although almost 2 years old, the reason for the behaviour had not been resolved, until I found a solution today.
The reason is the behaviour of the libfaad2.dll, which converts the AAC coded buffers to pcm16 buffers. Initialized by its "NeAACDecInit" API call (DTS headers), it assumes frame lengths of 1024 bytes, whereas the DAB+ data are coded with 960 bytes. Nevertheless, the libfaad decodes it, leading to the mentioned mismatch. The normal solution is to use the "Audio Specific Coding (ASC)" and the "NeAACDecInit2" API call, as is usually applied in DAB+ decoding software. The "Init2" using ASC coding has an option to select the frame length, in contrast to the "Init", using DTS headers, silently assuming the 1024 byte frame length.
However, it is well possible to modify the libfaad "NeAACDecInit" API call with an additional parameter and using it to command libfaad to use the short frame length. Probably the right place to do this in the libfaad2 library would be the file "decoder.c", around line 321, and insert hDecoder->frameLength = 960;
.
NAudio won't complain any more.