naudio / NAudio

Audio and MIDI library for .NET
MIT License
5.38k stars 1.09k forks source link

AAC file problem: plays too fast, might be issue #1096

Open Darkov3 opened 6 months ago

Darkov3 commented 6 months ago

I have the following code to play/pause/stop an *.aac audio file, that I download from an API and I store as a byte array:

private void LoadAac()
{
    // AudioBytes = is where the file is stored
    AudioStream = new MemoryStream(AudioBytes);
    AccReader = new StreamMediaFoundationReader(AudioStream);

    waveOut = new WaveOut();
    waveOut.Init(AccReader);
}

I play it like this:

public void Play()
{
    if (Loaded)
    {
        Logger.Log($"Playing audio file...", "CustomAudioPlayer.Play", LogLevelCustom.Trace);
        waveOut.Play();
        AudioTimer.Enabled = true;
    }
}

The AudioTimer calls this code to know when to stop the audio file and an UI element updates to show progress:

else if (FileFormat == OpenAICreateSpeechRequestResponseFormat.aac)
{
    AudioProgressBar.Value = (int)AccReader.Position;
    if (AccReader.CurrentTime.Milliseconds == AccReader.TotalTime.Milliseconds)
    {
        Stop(); // this just disposes of streams and whatever else + reloads the file with LoadAac();
    }
}

I have little knowledge about how Audio Files work in general, but I have gotten it to work with an MP3 and Opus (using Concentus too) file. I found this online, but because I do not quite understand how everything works, I am not sure if its related or not and how to fix it: https://stackoverflow.com/questions/37734341/aac-and-naudio-sampling-rate-mismatch

I even tried to change the sample rate like this:

private void LoadAac()
{
    AudioStream = new MemoryStream(AudioBytes);
    var streamMediaFoundationReader = new StreamMediaFoundationReader(AudioStream);
    var newFormat = new WaveFormat(
        streamMediaFoundationReader.WaveFormat.SampleRate / 5, // i tried various values here
        streamMediaFoundationReader.WaveFormat.BitsPerSample,
        streamMediaFoundationReader.WaveFormat.Channels); // Use the desired sample rate and bit depth
    AccReader = new WaveFormatConversionStream(newFormat, streamMediaFoundationReader);

    waveOut = new WaveOut();
    waveOut.Init(AccReader);
}

But it was either too fast or too slow.

markheath commented 6 months ago

To troubleshoot, I'd start by saving the whole thing to an aac file. Then see if Windows Media Player (or similar) can play it succesfully. And then see what using MediaFoundationReader can do.

Also, you shouldn't need the WaveFormatConversion step. StreamMediaFoundationReader should already be outputting PCM decoded audio.

Darkov3 commented 6 months ago

It does play, I have tested it. Here is the file, it is generated by OpenAI's TTS model: https://jmp.sh/s/LN8JSQedvzUrIUEoTskC

I have not tried it with MediaFoundationReader, shouldn't StreamMediaFoundationReader do the same, but from a stream?

edit: seems the file was deleted, will upload it somewhere else