3

I am trying to get OpenAL to play a simple audio clip for a game engine. I have not been able to find a good library to process to WAV files, so I have decided to try and decode them myself. I have been having some issues with this, and am rewriting my question to get a more targeted response.

Here is my code that is processing the WAV file. This code specifically skips over an extra header metadata that I found that has been causing me some issues. I then save the data into a buffer that gets returned to the call, which then sends the sound into OpenAL.

in.read(buffer, 4);//"data" chunk. 

        while(strncmp(buffer, "data", 4) != 0)
        {
            if(strncmp(buffer, "LIST", 4) == 0)
            {
                in.read(buffer, 2);
                in.ignore(ConvertToInt(buffer, 2) - 1);
            }
            in.read(buffer, 4);
        }

        std::cout << "current place: " << buffer[0] << buffer[1] << buffer[2] << buffer[3] << std::endl;

        in.read(buffer, 4); //Get size of the data

        size = ConvertToInt(buffer, 4);

        std::cout << "size: " << size << std::endl;

        if(size < 0)
        {
            std::cout << "Error here, not a valid WAV file, size of file reports 0.\n This was found instead: "
                      << size << std::endl;
        }

        char* data = new char[size];

        in.read(data, size);//Read audio data into buffer, return.

        in.close();

        return data;    

Here is my problem. No music plays. All that I get is a very brief squeek, then when I kill the program, I hear my speakers pop. When I print out the data, I see something very interesting that makes me thinking something is broken:

Print out data from caller -------------------------------------------------------

8   *   É   k   F   <   t   Å     C  ═   )  ç   ⌠   <  º  é  σ  J   α   6   *      2   » ² B   ë ·  ² 7 ≈ ≥ · É ⌠ F ∙ ` ≤ t ° y ⌠ 3 ∙ t ÷ i · ≈ ° ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ 

I installed a program called riffpad, and used that to take a look at the WAV file, and the first little bit of data matches up, but then it all turns into equal signs, which seems wrong. I am not sure why this is happening. I thought maybe it was because of how it was being returned, but this print out is from where the data is created, not where it's used, and it looks the same in both places. Any one have any idea what I'm doing wrong here?

Update:

Printing out the whole file produces this output:

Print out data from caller -------------------------------------------------------

R I F F ~ 4 ü   W A V E f m t                D ¼      ▒          L I S T R      I N F O I A R T        K o m i k u     I C M T í       U R L :   h t t p : / / f r e e m u s i c a r c h i v e . o r g / m u s i c / K o m i k u / C a p t a i n _ G l o u g l o u s _ I n c r e d i b l e _ W e e k _ S o u n d t r a c k / S k a t e
 C o m m e n t s :   h t t p : / / f r e e m u s i c a r c h i v e . o r g /
 C u r a t o r :
 C o p y r i g h t :       I C R D        2 0 1 8 - 0 7 - 1 4 T 0 4 : 3 7 : 0 5   I G N R        E l e c t r o n i c     I N A M        S k a t e   I P R D .       C a p t a i n   G l o u g l o u ' s   I n c r e d i b l e   W e e k   S o u n d t r a c k   I P R T        4   I S F T        L a v f 5 8 . 2 7 . 1 0 3   d a t a   3 ü   8   *   É   k   F   <   t   Å     C  ═   )  ç   ⌠   <  º  é  σ  J   α   6   *      2   » ² B   ë ·  ² 7 ≈ ≥ · É ⌠ F ∙ ` ≤ t ° y ⌠ 3 ∙ t ÷ i · ≈ ° · ≈ °  ⁿ ╜ ⁿ    ▐   ú    H  :  Ü  ┴  _  1 l  ß  ∩   ≈  / 2  r  ó  ≡  U  ¥  C  W  4       :  ¬  r  G ƒ  å Γ   ─  1  ∞  π  ╓   z  ▒    ò  ∞  é  >    ╣  ô  J 
 ┌  ]  i

which looks to me like the right kind of data... I am at a complete loss here. Something about trying to read the data from my data marker to my size corrupts the data.

1 Answers1

0

Turns out there was something wrong with the ifstream.read() function I was using. Here is my solution that works, sans error checking, which I will add in as I refactor it to an interface.

static int ConvertToInt(char* buffer, int len)
    {
        int a = 0;

        if(!IsBigEndian())
        {
            for(int i = 0; i < len; ++i)
            {
                ((char*)&a)[i] = buffer[i];
            }
        }
        else
        {
            for(int i = 0; i < len; ++i)
            {
                ((char*)&a)[3-i] = buffer[i];
            }
        }

        return a;
    }

//Header values for WAV file. Values are in bytes. 
    const U32 WAV_CHANNELS_OFFSET = 22;
    const U32 WAV_CHANNELS_SIZE = 2;

    const U32 WAV_SAMPLE_RATE_OFFSET = 24;
    const U32 WAV_SAMPLE_RATE_SIZE = 4;

    const U32 WAV_BYTE_RATE_OFFSET = 34;
    const U32 WAV_BYTE_RATE_SIZE = 2;

    const U32 WAV_DATA_OFFSET = 36;
    const U32 WAV_DATA_HEADER_SIZE = 4;
    const U32 WAV_DATA_SIZE_INFO_SIZE = 2;

    static void GetIndexRange(char* source, char* dest, int offset, int len)
    {
        for(int i = 0; i < len; ++i)
        {
            dest[i] = source[offset + i];
        }
    }

    //Location and size of data is found here: http://www.topherlee.com/software/pcm-tut-wavformat.html
    static char* LoadWAV(string filename, int& channels, int& sampleRate, int& bps, int& size)
    {
        std::ifstream in(filename.c_str());

        //Get the total size of the file
        in.seekg(0, in.end);

        int totalSize = (int)in.tellg();

        in.seekg(0, in.beg);

        //Save the whole file to a buffer using read
        char* buffer = new char[totalSize];

        in.read(buffer, totalSize);

        //Extract info about the audio file.
        char info[4];

        GetIndexRange(buffer, info, WAV_CHANNELS_OFFSET, WAV_CHANNELS_SIZE);

        channels = ConvertToInt(info, WAV_CHANNELS_SIZE);

        GetIndexRange(buffer, info, WAV_SAMPLE_RATE_OFFSET, WAV_SAMPLE_RATE_SIZE);

        sampleRate = ConvertToInt(info, WAV_SAMPLE_RATE_SIZE);

        GetIndexRange(buffer, info, WAV_BYTE_RATE_OFFSET, WAV_BYTE_RATE_SIZE);

        bps = ConvertToInt(info, WAV_BYTE_RATE_SIZE);

        //Extract the data itself.
        GetIndexRange(buffer, info, WAV_DATA_OFFSET, WAV_DATA_HEADER_SIZE);

        U32 POSITION = WAV_DATA_OFFSET + WAV_DATA_HEADER_SIZE;
        U32 moveTo = 0;

        while(strncmp(info, "data", 4) != 0)
        {
            if(strncmp(info, "LIST", 4) == 0)
            {
                GetIndexRange(buffer, info, POSITION, WAV_DATA_SIZE_INFO_SIZE);

                moveTo = ConvertToInt(info, WAV_DATA_SIZE_INFO_SIZE);           
            }
            //Set new position, move foreward one for rough check
            GetIndexRange(buffer, info, moveTo, WAV_DATA_HEADER_SIZE);
            POSITION = moveTo;
            moveTo = ++POSITION;
        }

        U32 DATA_SIZE_POSITION = POSITION - 1 + WAV_DATA_HEADER_SIZE;

        GetIndexRange(buffer, info, DATA_SIZE_POSITION, 4);

        size = ConvertToInt(info, 4);

        return buffer;
    }