读取16位wav文件并将其归一化,如Matlab所做的

Reading a 16 bit wav file and normalizing it as Matlab does

本文关键字:Matlab wav 16位 文件 读取      更新时间:2023-10-16

Matlab有一个名为audioread的函数,我试图在c++中重现,但只是用于wav文件。我可以读取wav文件并从中获得双类型值,但这些值似乎与Matlab函数返回的值不同。我的情况和这个人很相似。我读取文件的代码:

    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;
    }

rawAudioSignal中的所有值都是大约从-5到5的整数,但在Matlab中,这些数字是从-1到1,其中该特定文件的最低Matlab值为-0.2511,最高为0.3846。我不知道Matlab函数是对什么数进行归一化的也不知道它是如何归一化的。

样本是在-32768到32767范围内的16位,您希望它们缩放到-1.0到1.0。方法是除以32768.0(-32768/32768.0 == - 1,32767/32768.0略小于1)。

在从字节到整型的转换中,你有正确的基本想法,所以我怀疑一些类型转换可能会解决你的问题。尝试在左移之前将单个字节转换为int,以防止可能的溢出。将它分解成多个语句,并在调试器中观察它。

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