读取原始音频文件,如Matlab在C中所做的那样

时间:2014-07-08 10:47:27

标签: c matlab

我想用C编写以下小脚本:

`%% getting the spectgrum 
clear, clc ;

 fileName ='M0.raw'
   [x,fs] = audioread(fileName);
   [xPSD,f] = pwelch(x,hanning(8192),0,8192*4 ,fs);
   plot(f,10*log10(abs(xPSD)));
   xlim([0 22e3]);
   absxPSD = abs(xPSD);
   save('absXPSD.txt','absxPSD','-ascii');
   save('xPSD.txt','xPSD','-ascii');
   save('xValues.txt','x','-ascii');
   save('frequency.txt','f','-ascii');`

没有详细说明,我在获取正确结果时遇到了问题,当我检查时,我发现我读到的数据是错误的,这里读取原始文件的样本与Matalb读取的内容进行比较:

#include <stdio.h>
#include <stdlib.h>
int main (){

FILE* inp =NULL;
FILE* oup =NULL;
double value =0;

inp = fopen("M0.raw","r");
oup = fopen("checks.txt","w+");

更新 在LoPiTaL的回答之后,我试图使用fseek

跳过长度为44By的RIFF标题
fseek (inp,352,SEEK_SET);// that didn't help getting the right result !! 

if( inp == NULL || oup==NULL){
    printf(" error at file opning \n");
    return -1;
}

while (!(feof(inp))){

    fread(&value,sizeof(double),1,inp);
    printf(" %f \n ",value);
    fprintf(oup,"%f\n",value);
}
fclose(inp);
fclose(oup);
return 0;

}

我得到的结果是:

    -28083683309813134333858080554409220100578902032859386180468433149049781495379346137536863936326139303879846829175766826833343673613788446579155215033623707200818670767132304934425064429529496303287641688697019947073799877821581901737052884168025721481955133510652655692037990001524306465271815108431928360960.000000
0.000000
0.000000
0.000000
0.000000
0.000000
-20701636078248669570005757343846586744027511881225108933223144646890577802102653022204406730988428912367583701134782419138464527797567258583836429190479797597328678189654150340845........................................................................

我的目标是获得这些价值:

  -1.0162354e-02
  -9.3688965e-03
  -7.5073242e-03
  -1.9531250e-03
   3.7231445e-03
   1.3549805e-02
   2.3223877e-02
   3.2867432e-02
   4.4830322e-02
   5.5114746e-02
   6.7291260e-02
   7.7636719e-02
   8.8562012e-02
   9.5794678e-02
   1.0055542e-01
   1.0415649e-01
   1.0351563e-01
   1.0235596e-01
   9.8785400e-02
   9.1796875e-02
   8.3648682e-02
   7.1594238e-02

音频文件是单声道是16位分辨率,任何想法怎么解决这个?谢谢你的帮助

2 个答案:

答案 0 :(得分:2)

对于初学者,您必须以二进制模式打开文件。否则,您将获得文本模式,例如,可以进行行结尾的翻译。二进制数据不太好。

二进制模式:

inp = fopen("M0.raw", "rb");
                        ^
                        |
                       muy
                   importante

答案 1 :(得分:1)

当然,您无法按原样读取音频文件,并希望数据符合您的预期。

忽略任何编码的音频文件,当然在阅读之前你必须解码它,让我们专注于RAW音频文件:

RAW音频文件通常是WAV文件。 WAV文件在文件开头有一个.RIFF标题,显然你在阅读音频数据之前必须忽略它。

http://en.wikipedia.org/wiki/Resource_Interchange_File_Format

删除RIFF标题后,数据就会启动。 如您所述,数据编码为16位分辨率。 16位分辨率意味着0x0000是0.0而0xFFFF是1.0,并且数据的大小只有两个字节! 所以你必须一次读取两个字节(即带有符号的短路),然后转换到0到1的范围:

signed short ss;
double value;
FILE* inp =NULL;
inp = fopen("M0.raw","rb");  //As stated in other answer, use binary mode!
fseek (inp,44,SEEK_SET);     // Only 44 bytes!!
//We already have discarded the header here....

while (fread(&ss, sizeof(signed short) ,1 , inp) == 1){
    //Now we have to convert from signed short to double:
    value=((double)ss)/(unsigned)0xFFFF;

    //Print the results:
    printf(" %f \n ",value);
    fprintf(oup,"%f\n",value);
}

当然,功能&#34; audioread&#34;来自Matlab已经为你做了所有这些,所以你不必关心编码,如你的例子中,你的特定数据是16位,但如果你使用任何其他文件,它可能是8, 16,24或32,即使是WAV文件,也可以是差分或编码(有关更多信息,请参阅RIFF标题)。