在C中读取wav文件的左右声道?

问题描述 投票:0回答:1

我已经创建了一个读取wavfile的wavform并将其打印出来的代码。 (阅读我在代码中的注释)

#include <stdio.h>
#include <stdlib.h>


int main(){

   FILE *fp = fopen("file.wav","rb");
   fseek(fp,40,SEEK_SET); // moves pointer to Subchunk2Size. Read http://soundfile.sapp.org/doc/WaveFormat/
   int length;
   fread(&length,sizeof(int),1,fp); // stores the length of the waveform to "length"
   printf("%d\n", length); 

   short *data;
   data = malloc(length*sizeof(short)); // allocate a memory with the size length*sizeof(short)
   fseek(fp,44,SEEK_SET); // moves pointer to byte 44 where data begins. again http://soundfile.sapp.org/doc/WaveFormat/
   fread(data,sizeof(short),length,fp);
   for (int k=0; k<length; k++){
      printf("data at %d is %d\n", k, data[k]);
   }
   free(data);
   return 0;
}

尽管它可以读取单声道wavfile(单通道)。它无法读取2个通道(左右通道。)

[我的知识:单声道wav文件中的1个样本包含2个字节,立体声声道wavfile中的1个样本包含4个字节(左声道2个字节,右声道2个字节。

示例:例如:24 17 1E F3

[如果这是一个单声道wav文件,它将被视为两个样本并打印出5924-3298(注意:这是小尾数,F3 1E是http://soundfile.sapp.org/doc/WaveFormat/中所述的2的补码)

如果这是立体声通道wav文件,它将被视为1个样本,打印为:

Sample 1 Left channel: 5924
Sample 1 Right channel: -3298

因此24 17是左边的样本,右边的1E F3是样本。这是我对http://soundfile.sapp.org/doc/WaveFormat/]的解释

我正在寻找一个答案,该答案将把左声道置于short Left[],将右声道置于short Right[]

我已经创建了一个读取wavfile的wavform并将其打印出来的代码。 (请阅读代码中的注释)#include #include int main(){FILE * fp = fopen(“ file.wav” ...

c wav
1个回答
0
投票

几次折腾后,我认为我终于对了(阅读我的评论)。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

short * stereoChannel;

short * leftChannel;
short * rightChannel;

char    Subchunk2[4];
int     move    =    0;
short   channel =    1;
int     val     =    50000;

int main(){

   FILE *fp = fopen("bin.wav","rb");
   if (!fp){
      printf("Couldn't open file!\n");
      return 0;
   }
   while (1){
     fseek(fp,36+move,SEEK_SET);
     fread(Subchunk2,4*sizeof(char),1,fp);
     if (!strcmp(Subchunk2,"data")){
        break;
     }
     move++;
   }
   fseek(fp,22,SEEK_SET);
   fread(&channel,sizeof(short),1,fp);
   fseek(fp,36+move+4,SEEK_SET);
   int num;
   fread(&num,sizeof(int),1,fp);
   stereoChannel = malloc(num*sizeof(short));
   fseek(fp,4,SEEK_CUR);
   fread(stereoChannel,sizeof(short),num,fp);
   if (channel == 2){
      val=0;
      printf("wavfile in stereo\n");
      leftChannel = malloc(num*sizeof(short)/2);
      rightChannel = malloc(num*sizeof(short)/2);
      int channelpoint = 0;
      for (int inc=0;inc<num/2;inc++){
         leftChannel[channelpoint] = stereoChannel[inc*2];
         rightChannel[channelpoint] = stereoChannel[(inc*2)+1];
         channelpoint++;
      }



      for (int k=0; k<50000; k++){
         printf("stereo sample %d L: %d R: %d \n",k,leftChannel[k],rightChannel[k]);
      }

      free(rightChannel);
      free(leftChannel);
   }
   for (int k=0; k<val; k++){  // If this is stereo, it would print nothing because val was set to 0
      printf("mono sample %d is %d\n", k, stereoChannel[k]);
}
   free(stereoChannel);
   return 0;
}

打印:

...
stereo sample 49981 L: 8039 R: 6943
stereo sample 49982 L: 9277 R: 10518
stereo sample 49983 L: 13398 R: 16936
stereo sample 49984 L: 13305 R: 15692
stereo sample 49985 L: 2715 R: 9778
stereo sample 49986 L: -5680 R: 5595
stereo sample 49987 L: -3632 R: 3921
...

while loop的说明。此代码检查data标记,因为并非每个wavfile数据标记都从偏移量36开始。(也许我应该添加一个函数来检查文件是否为wavfile,因为如果没有它,它将永远循环并可能导致分段错误。)

给我您的想法。

© www.soinside.com 2019 - 2024. All rights reserved.