0

I'm trying to get data from WAV file for FIR filter.That's what I have so far. Is this code reading WAV correctly? Also I need to store data into an array of double to be able to pass them to a FIR filter function later. I'm not sure how to do that.

EDIT: After reading some more information about WAV files, I now changed my code now. Does it look better now? How can I convert now an array of short of the data into an array of doubles?

struct wav_header_t
{
    char chunkID[4]; //"RIFF" 
    unsigned long chunkSize; 
    char format[4]; //"WAVE" 
    char subchunk1ID[4]; //"fmt " 
    unsigned long subchunk1Size; //16 
    unsigned short audioFormat;
    unsigned short numChannels;
    unsigned long sampleRate;
    unsigned long byteRate;
    unsigned short blockAlign;
    unsigned short bitsPerSample;
};
//Chunks
struct chunk_t
{
    char ID[4]; //"data" 
    unsigned long size;  //Chunk data bytes
};

void WAV::vRead()
{
    //open file
    cout << sName <<" will be open"<<endl;
    FILE* handle;
    fopen_s(&handle, sName, "rb");


    if (handle == NULL)
    {
        cout << "file opened unsuccessfully" << endl;
        return;
    }
    else
    {
        cout << sName << " is open" << endl;
    }

    //size of file.wav
    fseek(handle, 0, SEEK_END);
    long fileSize = ftell(handle);


    //read wav-Headers
    wav_header_t header;
    fread(&header, sizeof(header), 1, handle);

    //Reading file
    chunk_t chunk;
    //go to data chunk
    while (true)
    {
        fread(&chunk, sizeof(chunk), 1, handle);
        if (*(unsigned int*)&chunk.ID == 0x61746164)
            break;
        //skip chunk data bytes
        fseek(handle, chunk.size, SEEK_CUR);
    }

    //Number of samples
    int sample_size = header.bitsPerSample / 8;
    int samples_count = chunk.size * 8 / header.bitsPerSample;

    short int* value = new short int[samples_count];
    memset(value, 0, sizeof(short int) * samples_count);

    //Reading data
    for (int i = 0; i < samples_count; i++)
    {
        fread(&value[i], sample_size, 1, handle);
    }
    fclose(handle);
    return;
}

Zaidiot
  • 13
  • 3
  • Your program reads 4 bytes from a file. What do you mean by "reading WAV correctly"? What does it mean to have read those 4 bytes _correctly_? – Drew Dormann Jun 20 '23 at 01:47
  • Well, I meant to read WAV file correctly in general because as I said I need it for FIR filter, and as far as I can guess from your reply, I am not doing it correctly apparently. This is the first time i try to read this type of file – Zaidiot Jun 20 '23 at 02:07
  • Check this https://stackoverflow.com/a/13661263/5282154 answer for details of the WAV header format. – doug Jun 20 '23 at 02:26
  • Thanks! I checked it out, it did help me to understand WAV file better. I changed my code. Does it look correct now? and does anyone know how I can convert an array of short int to an array of doubles? Its just as I said I need this data to be in array of double because I have to pass them to FIR filter. – Zaidiot Jun 20 '23 at 13:44

1 Answers1

1

What you're missing and requested in your comment was converting from the 16 bit ints to doubles.

Here's an example of converting the interleaved 16 bit ints to normalized doubles. Assumptions are 2 channel stereo. Adapt as needed.

#include <vector>
#include <algorithm>
#include <array>
#include <iostream>

std::vector<std::array<double,2>> get_normalized_wav_doubles(const std::vector<int16_t> wav)
{
    std::vector<std::array<double, 2>> ret(wav.size() / 2);
    for (size_t i = 0; i < wav.size(); i+=2)
    {
        ret[i / 2][0] = wav[i] / 32768.0;   // normalized doubles to +-1
        ret[i / 2][1] = wav[i+1] / 32768.0;
    }
    return ret;
}

int main()
{
    std::vector<int16_t> wav{10, -20, 30, -40, 50, -60}; // 6 16 bit ints interleaved for stereo
    std::vector<std::array<double, 2>> f_set = get_normalized_wav_doubles(wav);
    for (const auto& x : f_set)
    {
        std::cout << x[0] << "\n";      // first channel
        std::cout << x[1] << "\n\n";    // second channel
    }
}

Output:

0.000305176
-0.000610352

0.000915527
-0.0012207

0.00152588
-0.00183105
doug
  • 3,840
  • 1
  • 14
  • 18