2014-01-25 88 views
0

我想读取一个.wav文件,我认为它给了我正确的结果,但是,当我在Matlab或Python中绘制相同的音频文件时,结果是不同。C++ - 在16位.wav文件中读取

这是结果,我得到:

enter image description here

这是结果的Python(与matplotlib绘制)给出:

enter image description here

结果似乎并没有什么不同,但是,当谈到分析时,这就搞乱了我的结果。

下面是转换代码:

for (int i = 0; i < size; i += 2) 
{ 
    int c = (data[i + 1] << 8) | data[i]; 
    double t = c/32768.0; 
       //cout << t << endl; 
    rawSignal.push_back(t); 
} 

我要去哪里错了?因为,这种转换看起来很好,并且产生了类似的结果。

感谢

编辑:

码读取头/数据:

voidreadHeader(ifstream& file) { 



s_riff_hdr riff_hdr; 
    s_chunk_hdr chunk_hdr; 

    long padded_size; // Size of extra bits 

    vector<uint8_t> fmt_data; // Vector to store the FMT data. 

    s_wavefmt *fmt = NULL; 

    file.read(reinterpret_cast<char*>(&riff_hdr), sizeof(riff_hdr)); 
    if (!file) return false; 

    if (memcmp(riff_hdr.id, "RIFF", 4) != 0) return false; 

    //cout << "size=" << riff_hdr.size << endl; 
    //cout << "type=" << string(riff_hdr.type, 4) << endl; 

    if (memcmp(riff_hdr.type, "WAVE", 4) != 0) return false; 
    { 
     do 
     { 
      file.read(reinterpret_cast<char*>(&chunk_hdr), sizeof(chunk_hdr)); 
      if (!file) return false; 
      padded_size = ((chunk_hdr.size + 1) & ~1); 

      if (memcmp(chunk_hdr.id, "fmt ", 4) == 0) 
      { 
       if (chunk_hdr.size < sizeof(s_wavefmt)) return false; 

       fmt_data.resize(padded_size); 
       file.read(reinterpret_cast<char*>(&fmt_data[0]), padded_size); 
       if (!file) return false; 

       fmt = reinterpret_cast<s_wavefmt*>(&fmt_data[0]); 

       sample_rate2 = fmt->sample_rate; 

       if (fmt->format_tag == 1) // PCM 
       { 
        if (chunk_hdr.size < sizeof(s_pcmwavefmt)) return false; 

        s_pcmwavefmt *pcm_fmt = reinterpret_cast<s_pcmwavefmt*>(fmt); 


        bits_per_sample = pcm_fmt->bits_per_sample; 
       } 
       else 
       { 
        if (chunk_hdr.size < sizeof(s_wavefmtex)) return false; 

        s_wavefmtex *fmt_ex = reinterpret_cast<s_wavefmtex*>(fmt); 


        if (fmt_ex->extra_size != 0) 
        { 
         if (chunk_hdr.size < (sizeof(s_wavefmtex) + fmt_ex->extra_size)) return false; 

         uint8_t *extra_data = reinterpret_cast<uint8_t*>(fmt_ex + 1); 
         // use extra_data, up to extra_size bytes, as needed... 
        } 

       } 
       //cout << "extra_size=" << fmt_ex->extra_size << endl; 
      } 

      else if (memcmp(chunk_hdr.id, "data", 4) == 0) 
      { 
       // process chunk data, according to fmt, as needed... 
       size = padded_size; 

       if(bits_per_sample == 16) 
       { 
        //size = padded_size/2; 
       } 

       data = new unsigned char[size]; 

       file.read(data,  size); 

       file.ignore(padded_size); 
       if (!file) return false; 
      } 
      { 
       // process other chunks as needed... 

       file.ignore(padded_size); 
       if (!file) return false; 
      } 

     }while (!file.eof()); 
     return true; 
    } 

} 

这就是 “转换为双” 发生了:

if(bits_per_sample == 8) 
     { 
      uint8_t c; 
      //cout << size; 
      for(unsigned i=0; (i < size); i++) 
      { 
       c = (unsigned)(unsigned char)(data[i]); 
       double t = (c-128)/128.0; 
       rawSignal.push_back(t); 
      } 
     } 
     else if(bits_per_sample == 16) 
     { 

      for (int i = 0; i < size; i += 2) 
      { 
       int c; 
       c = (unsigned) (unsigned char) (data[i + 2] << 8) | data[i]; 
       double t = c/32768.0; 
       rawSignal.push_back(t); 
     } 

注意如何“8位”文件正常工作?

+0

将_what_?那里有什么“大小”和“数据”?什么是你想要复制的相应的Python代码? – abarnert

+0

那个'rawSignal'中的“原始”格式是什么?通常,浮动音频的范围从-1到1或0到1,但看起来你会从0到2(因为你从0-65535取int),假设'data'是一个'unsigned char * ',然后除以32768.0)。 – abarnert

+0

@abarnert我想将原始数据转换为“double”,因此“/ 32768.0”为 – Phorce

回答

3

我怀疑你的问题可能是data的数组签名char值。所以,当你这样做时:

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

......它实际上并没有做你想做的。我们来看一些简单的例子。

如果data[i+1] == 64data[i] == 64,这将是0x4000 | 0x40或0x4040,都很好。

如果data[i+1] == -64data[i] == -64,那将是0xffffc000 | 0xffffffc0或0xffffffc0,这显然是错误的。

如果您使用unsigned char值,这会工作,因为代替-64这些数字将是192,你会最终0xC000时| 0xc0或0xc0c0,就像你想要的一样。 (但是你的/32768.0会给你的数字范围在0.0到2.0之间,当你大概想要-1.0到1.0时。)

如果不知道你想要做什么,建议“修复”是很困难的。很明显,你想将某种16位小尾数整数格式转换成某种浮点格式,但很多都依赖于这些格式的确切细节,而且你还没有提供任何这样的细节。默认的.wav格式是16位无符号的小尾数整数,因此只需使用unsigned char *就可以修复等式的这一部分。但我不知道任何使用从0.0到2.0的64位浮点数的音频格式,而且我不知道您实际上想要的是什么音频格式,所以我不能说那实际上应该是什么样的音频格式是的,只是这可能是错误的。

+0

请参阅我更新的问题,我已包含代码。 – Phorce

+0

正如你所看到的,我没有无符号或有符号的“数据”字符,那怎么会是这个问题呢? – Phorce

+0

@ user1326876你说'data'是'char *',在大多数系统上这意味着它是一个有符号数据类型。数值范围从-128到127,而不是0到255. –