简体   繁体   中英

Endianness in wav files

I have tried to make a simple wav writer. I wanted to do this so that I could read in a wav file (using a pre-existing wav reader), resample the audio data then write the resampled data to another wav file. Input files could be 16 bitsPerSample or 32 bitsPerSample and I wanted to save the resampled audio with the same number of bitsPerSample.

The writer is working but there a couple of things I don't understand to do with endianness and I was hoping someone may be able to help me?

I previously had no experience of reading or writing binary files. I began by looking up the wav file format online and tried to write the data following the correct format. At first the writing wasn't working but I then found out that wav files are little-endian and it was trying to make my file writer consistent with this that brought up the majority of my problems. I have got the wav writer to work now (by way of a test whereby I read in a wav file and checked I could write the unsampled audio and reproduce the exact same file) however there are a couple of points I am still unsure on to do with endianness and I was hoping someone may be able to help me?

Assuming the relevant variables have already been set here is my code for the wav writer:

// Write RIFF header
out_stream.write(chunkID.c_str(),4);
out_stream.write((char*)&chunkSize,4);
out_stream.write(format.c_str());

// Write format chunk
out_stream.write(subchunk1ID.c_str(),4);
out_stream.write((char*)&subchunk1Size,4);
out_stream.write((char*)&audioFormat,2);
out_stream.write((char*)&numOfChannels,2);
out_stream.write((char*)&sampleRate,4);
out_stream.write((char*)&byteRate,4);
out_stream.write((char*)&blockAlign,2);
out_stream.write((char*)&bitsPerSample,2);

// Write data chunk
out_stream.write(subchunk2ID.c_str(),4);
out_stream.write((char*)&subchunk2Size,4);

// Variables for writing 16 bitsPerSample data
std::vector<short> soundDataShort;
soundDataShort.resize(numSamples);
char theSoundDataBytes [2];

// soundData samples are written as shorts if bitsPerSample=16 and floats if bitsPerSample=32
switch( bitsPerSample )
{ 
    case (16):
        // cast each of the soundData samples from floats to shorts
        // then save the samples in little-endian form (requires reversal of byte-order of the short variable)
        for (int sample=0; sample < numSamples; sample++)
    {
        soundDataShort[sample] = static_cast<short>(soundData[sample]);
            theSoundDataBytes[0] = (soundDataShort[sample]) & 0xFF;
            theSoundDataBytes[1] = (soundDataShort[sample] >> 8) & 0xFF;
            out_stream.write(theSoundDataBytes,2);          
    }   
    break;

    case (32):
        // save the soundData samples in binary form (does not require change to byte order for floats)
        out_stream.write((char*)&soundData[0],numSamples);
}

The questions that I have are:

  1. In the soundData vector why does the endianness of a vector of shorts matter but the vector of floats doesn't? In my code I have reversed the byte order of the shorts but not the floats.

  2. Originally I tried to write the shorts without reversing the byte order. When I wrote the file it ended up being half the size it should have been (ie half the audio data was missing, but the half that was there sounded correct), why would this be?

  3. I have not reversed the byte order of the shorts and longs in the other single variables which are essentially all the other fields that make up the wav file eg sampleRate, numOfChannels etc but this does not seem to affect the playing of the wav file. Is this just because media players do not use these fields (and hence I can't tell that I have got them wrong) or is it because the byte order of these variables does not matter?

In the soundData vector why does the endianness of a vector of shorts matter but the vector of floats doesn't? In my code I have reversed the byte order of the shorts but not the floats.

Actually, if you take a closer look at your code, you will see that you are not reversing the endianness of your shorts at all. Nor do you need to, on Intel CPUs (or on any other low-endian CPU).

Originally I tried to write the shorts without reversing the byte order. When I wrote the file it ended up being half the size it should have been (ie half the audio data was missing, but the half that was there sounded correct), why would this be?

I have no idea without seeing the code but I suspect that some other factor was in play.

I have not reversed the byte order of the shorts and longs in the other single variables which are essentially all the other fields that make up the wav file eg sampleRate, numOfChannels etc but this does not seem to affect the playing of the wav file. Is this just because media players do not use these fields (and hence I can't tell that I have got them wrong) or is it because the byte order of these variables does not matter?

These fields are in fact very important and must also be little-endian, but, as we have seen, you don't need to swap those either.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM