从二进制文件中读取一个整数

3
我一直在尝试从.Wav文件中读取int类型的数据,但遇到了麻烦。我正在根据这里列出的.wav规范进行操作。我想要从头部读取一个int类型(Subchunk2Size),并将数据存入一个short数组中。无论是使用fread()还是ifstream.read()函数,我都遇到了障碍。我会列出两种读取技术的问题,但其实只需要回答其中一种即可。
    sprintf(filename, "C:\\Users\\MacbookWin7\\wavs\\%s.wav", word);
FILE * infile = fopen(filename, "rb");
if (infile != NULL)
{
    int f = ferror(infile);
    int d = fseek(infile, 40, SEEK_SET);
    int * subChunk2Size = new int[1];
    int i = fread(subChunk2Size, sizeof(int), 1, infile);
    int g = ferror(infile);
问题: fread函数无法读取任何内容,i始终初始化为0。
我尝试了许多不同的组合来声明subChunk2Size,包括尝试声明指针、数组(单个和多个元素)、声明nullptr以及声明int并传递其引用。 ifstream.read()
    sprintf(filename, "C:\\Users\\MacbookWin7\\wavs\\%s.wav", word);
ifstream sampleStream(filename,ios::binary);
char * samplesStr;

if (sampleStream.is_open())
{
    sampleStream.seekg(40);
    char * subChunk2SizeStr = new char[4];
    sampleStream.read(subChunk2SizeStr, 4);
    int subChunk2Size = 0;
    for (int i = 3; i >= 0; i--)
    {
        subChunk2Size = (subChunk2Size << 8) + subChunk2SizeStr[i];
    }
    int numBytes = subChunk2Size + *nsamples * 2;
    char * samplesStr = new char[numBytes];
    sampleStream.read(samplesStr, numBytes);
    sampleStream.close();
    short * samples = new short[numBytes / 2];
    for (int i = 0; i < numBytes / 2; i++)
    {
        int b = i * 2;
        samples[i] = samplesStr[b+1];
        samples[i] = (samples[i] << 8) + samplesStr[b];
    }
问题: 我的第一个读取和位移操作得出了正确答案约为22,000,但我无法通过第二个循环读取short类型的数据。

感谢任何人对我的问题给予关注。


我不知道这些中的任何一个是否导致了你的问题(实际上,你没有说明你的问题是什么):1. 使用有符号值进行移位可能会产生未定义的行为;2. char 可以是有符号的,并且在转换时会被符号扩展,从而在移位时引起更多麻烦;3. 你似乎没有释放你分配的内存。 - Dietmar Kühl
你使用的是PowerPC Mac吗?如果不是,为什么要进行字节顺序操作呢? - Mats Petersson
Dietmar,我不知道如何更清楚地解释这些问题,所以我认为我们现在就是卡住了。感谢你给我的其他提示。Mats,我只是试图读取SubChunk2Size和wav数据 - 我正在尝试一切可能的方法来使它工作。 - DCKlingensmith
1个回答

3
我拿了你的代码,稍微改动了一下,当我使用每个样本16位、立体声输入(如此文件)时,似乎显示出合理的结果。
#include <fstream>
#include <cstdio>
#include <iostream>
#include <climits>

using namespace std;

int main()
{
    const char *filename = "audio/M1F1-int16-AFsp.wav";
    ifstream sampleStream(filename,ios::binary);
    int nsamples = 10000;
    short * samples;
    if (sampleStream.is_open())
    {
        sampleStream.seekg(44);  // Skip all of the header. 
        samples = new short[nsamples];
        sampleStream.read(reinterpret_cast<char *>(samples), sizeof(short)*nsamples);
        sampleStream.close();
    }
    short max = 0; 
    short min = 32767;
    int min_at = 0; 
    int max_at = 0;
    for(int i = 0; i < nsamples; i++)
    {
        if (samples[i] > max) 
        {
            max = samples[i];
            max_at = i;
        }
        if (samples[i] < min)
        {
            min = samples[i];
            min_at = i;
        }
    }
    cout << "Max=" << max << " at " << max_at << endl;
    cout << "Min=" << min << " at " << min_at << endl;
}

在样本990 [立体声中的样本495]处,它显示了一个峰值14325和一个最低水平-7125,与在Audacity软件中的值进行比较时两者都匹配。请注意,我依赖于我的机器上的x86处理器是小端序。如果您正在运行Mac,则情况也是如此,除非它是一个非常老的PowerPC Mac。


你能否请在读取头文件中的SubChunk2Size时做同样的事情?它是位于第40个字节的int类型。 sampleStream.seekg(40); sampleStream.read(reinterpret_cast<char *>(subChunk2Size), sizeof(int)); - DCKlingensmith
是的,只要机器是小端序的。 - Mats Petersson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接