Чтение и обработка данных WAV файлов в C/С++

В настоящее время я занимаюсь очень важным школьным проектом. Мне нужно извлечь информацию из файла WAVE в C/С++ и использовать информацию для получения LPC речевого сигнала. Но для этого мне нужно сделать некоторую предварительную обработку сигнала, например, делать перекрестку нуля и энергетический анализ, между прочим. Это означает, что мне нужен знак и реальная ценность. Проблема в том, что я не знаю, как получить полезную информацию и правильный формат для этого. Я уже прочитал каждое поле в файле, но я не уверен, что делаю все правильно. Предложения, пожалуйста?

Так я читаю файл на данный момент:

readI = fread (& bps, 1, 2, audio);       printf ( "бит на выборку =% d\n", бит/с);

Спасибо заранее.

Ответ 1

Моя первая рекомендация - использовать какую-то библиотеку, чтобы помочь вам. Большинство звуковых решений кажутся излишними, поэтому простая идея (например, рекомендованная в комментарии к вашему вопросу libsndfile) должна сделать трюк.

Если вы просто хотите знать, как читать WAV файлы, чтобы вы могли писать свои собственные (поскольку ваша школа может превратить свой нос в то, что вы используете библиотеку, как любой другой обычный человек), быстрый поиск в Google даст вам все вам нужна информация плюс некоторые люди, которые уже написали много учебников по чтению формата .wav.

Если вы все равно не получите его, вот некоторые из моих собственных кодов, где я читаю заголовок и все остальные фрагменты файла данных WAV/RIFF, пока не доберусь до блока данных. Он основан на исключительно в соответствии со спецификацией формата WAV. Извлечение фактических звуковых данных не очень сложно: вы можете прочитать его raw и использовать его raw или сделать преобразование в формат, который у вас будет больше комфорта с внутренним (32-разрядные несжатые данные PCM или что-то еще).

При взгляде на приведенный ниже код замените reader.Read...( ... ) эквивалентными fread вызовами целочисленных значений и размеров байтов указанного типа. WavChunks - это перечисление, которое является маленькими значениями Endian идентификаторов внутри фрагмента файла WAV, а переменная format является одним из типов типов форматов Wav, которые могут содержаться в формате файла WAV:

enum class WavChunks {
    RiffHeader = 0x46464952,
    WavRiff = 0x54651475,
    Format = 0x020746d66,
    LabeledText = 0x478747C6,
    Instrumentation = 0x478747C6,
    Sample = 0x6C706D73,
    Fact = 0x47361666,
    Data = 0x61746164,
    Junk = 0x4b4e554a,
};

enum class WavFormat {
    PulseCodeModulation = 0x01,
    IEEEFloatingPoint = 0x03,
    ALaw = 0x06,
    MuLaw = 0x07,
    IMAADPCM = 0x11,
    YamahaITUG723ADPCM = 0x16,
    GSM610 = 0x31,
    ITUG721ADPCM = 0x40,
    MPEG = 0x50,
    Extensible = 0xFFFE
};

int32 chunkid = 0;
bool datachunk = false;
while ( !datachunk ) {
    chunkid = reader.ReadInt32( );
    switch ( (WavChunks)chunkid ) {
    case WavChunks::Format:
        formatsize = reader.ReadInt32( );
        format = (WavFormat)reader.ReadInt16( );
        channels = (Channels)reader.ReadInt16( );
        channelcount = (int)channels;
        samplerate = reader.ReadInt32( );
        bitspersecond = reader.ReadInt32( );
        formatblockalign = reader.ReadInt16( );
        bitdepth = reader.ReadInt16( );
        if ( formatsize == 18 ) {
            int32 extradata = reader.ReadInt16( );
            reader.Seek( extradata, SeekOrigin::Current );
        }
        break;
    case WavChunks::RiffHeader:
        headerid = chunkid;
        memsize = reader.ReadInt32( );
        riffstyle = reader.ReadInt32( );
        break;
    case WavChunks::Data:
        datachunk = true;
        datasize = reader.ReadInt32( );
        break;
    default:
        int32 skipsize = reader.ReadInt32( );
        reader.Seek( skipsize, SeekOrigin::Current );
        break;
    }
}