Проблемы с преобразованием файла MP3 в файл WAV с помощью Naudio

Библиотека Naudio: http://naudio.codeplex.com/

Я пытаюсь преобразовать файл MP3 в файл WAV, но столкнулся с небольшой ошибкой. Я знаю, что происходит не так, но я действительно не знаю, как это исправить.

Вот кусок кода, который я запускаю:

private void button1_Click(object sender, EventArgs e) {
    using(Mp3FileReader reader = new Mp3FileReader(@"path\to\MP3")) {
        using(WaveFileWriter writer = new WaveFileWriter(@"C:\test.wav", new WaveFormat())) {
            int counter = 0;
            while(reader.Read(test, counter, test.Length + counter) != 0) {
                writer.WriteData(test, counter, test.Length + counter);
                counter += 512;
            }
        }
    }
}

reader.Read() входит в класс Mp3FileReader, и метод выглядит так:

public override int Read(byte[] sampleBuffer, int offset, int numBytes)
{
    if (numBytes % waveFormat.BlockAlign != 0)
        //throw new ApplicationException("Must read complete blocks");
        numBytes -= (numBytes % waveFormat.BlockAlign);
    return mp3Stream.Read(sampleBuffer, offset, numBytes);
}

mp3Stream — это объект класса Stream.

Проблема в том, что я получаю исключение ArgumentException. MSDN говорит, что это связано с тем, что сумма смещения и numBytes больше, чем длина sampleBuffer.

Документация: http://msdn.microsoft.com/en-us/library/system.io.stream.read.aspx

Это происходит потому, что я каждый раз увеличиваю счетчик, но размер массива байтов test остается прежним.

Меня вот что интересует: нужно ли динамически увеличивать размер массива, или нужно узнать нужный размер в начале и сразу задать?

И еще, вместо 512 метод в Mp3FileReader в первый раз возвращает 365. Это размер целого блока. Но я пишу полный 512. Я в основном просто использую чтение, чтобы проверить, не достиг ли я еще конца файла. Мне нужно поймать возвращаемое значение и что-то с этим сделать, или я хорошо здесь?


person KdgDev    schedule 08.05.2010    source источник


Ответы (2)


Вам нужно будет использовать возвращаемое значение Read(), чтобы определить, сколько байтов вы фактически получили. Это не обязательно должно быть 512, вы это уже выяснили. И имейте в виду, что вы работаете с потоками, а не с массивами. Сделайте это похожим на это:

   using (var reader = new Mp3FileReader(@"path\to\MP3")) {
        using (var writer = new WaveFileWriter(@"C:\test.wav", new WaveFormat())) {
            var buf = new byte[4096];
            for (;;) {
                var cnt = reader.Read(buf, 0, buf.Length);
                if (cnt == 0) break;
                writer.WriteData(buf, 0, cnt);
            }
        }
    }
person Hans Passant    schedule 08.05.2010
comment
Хорошо, я делаю это сейчас, и в результате много статического шума. Все-таки это совсем другая проблема. - person KdgDev; 08.05.2010
comment
попробуйте изменить байт[] buf = новый байт[4096]; вместо байта buf = новый байт[4096]; - person fyasar; 15.06.2011
comment
Это не работает для приложения Магазина Windows 8.1, которое я пытаюсь использовать. Можете ли вы опубликовать обновленный метод или указать мне правильную ссылку? - person Wajahat; 14.02.2014

На самом деле в вашем примере вы не выполняете никакого преобразования из MP3 в WAV. Вам нужен WaveFormatConversionStream. Попробуйте что-то вроде этого:

private void button1_Click(object sender, EventArgs e) {
    using(Mp3FileReader reader = new Mp3FileReader(@"path\to\MP3")) {
        using (WaveStream convertedStream = WaveFormatConversionStream.CreatePcmStream(reader)) {
            WaveFileWriter.CreateWaveFile(outputFileName, convertedStream);
        }
    }
}
person Mark Heath    schedule 09.05.2010
comment
Выглядит хорошо, но не запускается. Я продолжаю получать исключение AcmNotPossible, вызывающее acmStreamOpen. - person KdgDev; 12.05.2010
comment
это, вероятно, потому, что ваш целевой формат не соответствует естественному преобразованному формату MP3. Я обновлю пример кода - person Mark Heath; 13.05.2010