0
votes

Matlab has a function called audioread that I'm trying to reproduce in C++ but just for wav files. I can read a wav file and get double type values from it but these values seem to differ from the values returned by the Matlab function. My situation is very similar to this guy. My code for reading the file:

    vector<double> rawAudioSignal;

    std::basic_ifstream<uint8_t> inputStream(path.c_str(), std::ifstream::binary);
    if (inputStream) {
        // get length of file:
        inputStream.seekg(0, inputStream.end);
        int fileLength = inputStream.tellg();
        // go back to start of stream
        inputStream.seekg(0, inputStream.beg);

        uint8_t *buffer = new uint8_t[fileLength];
        inputStream.read((uint8_t *)buffer, fileLength);
        inputStream.close();

        const int wavHeaderSize = 44;
        for (size_t i = wavHeaderSize; i < fileLength; i += 2)
        {
            // removes those huge 65000+ value spikes
            int c = ((char)buffer[i + 1]) << 8 | 
                ((unsigned char)buffer[i]);

            // failed attempts
            //int c = (buffer[i + 1] << 8 | buffer[i]); // little endian
            //int c = (buffer[i] << 8 | buffer[i + 1]); // big endian

            // failed normalizations
            //rawAudioSignal.push_back((c / 32768.0) - 1);
            //rawAudioSignal.push_back(((c - 32768.0) / 32768.0));
            rawAudioSignal.push_back(c);
        }
        delete[] buffer;
    }

All of the values in rawAudioSignal are whole number from about -5 to 5 but in Matlab, the numbers are from -1 to 1, where the lowest Matlab value for this particular file is -0.2511 and the highest is 0.3846. I don't know what numbers the Matlab function is normalizing against or how it's normalizing. Any help is appreciated.

1

1 Answers

3
votes

The samples are 16-bit in the range of -32768 to 32767 and you want them scaled to -1.0 to 1.0. The way to do this is to divide by 32768.0 (-32768/32768.0 == -1, 32767/32768.0 is slightly less than 1).

You have the right basic idea in the conversion from bytes to int so I suspect some casting might solve your problem. Try casting the individual byte to int before left shifting to prevent possible overflow. Break it into multiple statements and watch it in the debugger.

int c = ((int)buffer[i+1]) << 8 | buffer[i];