Читать левый и правый канал wav файла в C? - PullRequest
0 голосов
/ 05 мая 2020

Я создал код, который считывает wav-форму wav-файла и распечатывает его. (Прочтите мой комментарий в коде)

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

Хотя он может читать моно wav-файл (один канал). Он не может читать 2 канала (левый и правый канал).

Мне известно: 1 отсчет из файла wav моноканала содержит 2 байта, а 1 отсчет из файла wav стереоканала содержит 4 байта (2 байта слева канал и 2 байта от правого канала).

Пример: из образца, например: 24 17 1E F3

Если это был моно файл WAV, он будет рассматриваться как два образца и будет напечатан , 5924 и -3298 (примечание: это прямой порядок байтов, а F3 1E - это дополнение до 2, как описано в http://soundfile.sapp.org/doc/WaveFormat/)

Если это был файл 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[]

1 Ответ

0 голосов
/ 07 мая 2020

После того, как я пару раз ломал голову, я думаю, что наконец понял (Прочтите мои комментарии).

#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, потому что не каждый тег данных wav-файла начинается со смещения 36. (Возможно, мне стоит добавить функцию, которая проверяет, является ли файл wav-файлом, потому что без него это будет l oop навсегда и может вызвать сегментацию ошибка.)

Поделитесь своими мыслями.

...