Звуковой проигрыватель не может прочитать WAV-файл, созданный моей программой, говорит отсутствующий заголовок - PullRequest
0 голосов
/ 12 октября 2019

Я кодирую программу, которая отображает тип волны (синус, квадрат, волна и т. Д.) И записывает ее в файл. Проблема в том, что звуковой плеер говорит, что заголовок отсутствует, хотя я его написал. Предполагается, что типы данных должны быть написаны с прямым порядком байтов.

Я пытался переписывать функции ввода-вывода несколько раз по-разному, но безрезультатно. Я попытался заполнить массив данными, которые будут записаны с тестовыми данными, и даже это не работает. Что-то не так при записи файла.

Основная функция:

int main (int argc, char** argv){
  if (argc != 6){
    printf("Error: expecting more arguments\n");
    return -1;
  }

  //First argument: voice
  int voice = atof(argv[1]);


  //Second argument: frequency
  float frequency = atof(argv[2]);


  //Third argument: amplitude
  float amplitude = atof(argv[3]);


  //Fourth argument: numsample
  int numsamples = atof(argv[4]); 

  //Fifth argument: output file name
  char* filename = argv[5];

  int16_t buffer[numsamples*2];
  memset(buffer, 0.1, numsamples*2);

  if (check_args(voice, frequency,  amplitude) != 0) {  


    //Sine wave
    if (voice == 0) {
      //render_sine_wave_stero(buffer, numsamples, frequency, amplitude);
    }

    //If square wave
    else if (voice == 1){
      //render_square_wave_stereo(buffer, numsamples, frequency, amplitude);
    }

    //Sawtooth
    else if (voice == 2) {
      //render_sawtooth_wave_stero(buffer, numsamples, frequency, amplitude);
    }





    FILE *outputfile = fopen(filename, "wb+");
    if (outputfile == NULL){
      printf("Error: file failed to open");
      return 1;
    }

    write_wave_header(outputfile, numsamples);

    write_s16_buf(outputfile, buffer, numsamples*2);

    fclose(outputfile);

    printf("Finished\n");

Функция записи заголовка:

#define PI                 3.14159265358979323846
#define SAMPLES_PER_SECOND 44100u
#define NUM_CHANNELS       2u
#define BITS_PER_SAMPLE    16u

void write_wave_header(FILE *out, unsigned num_samples) {
  /*
   * See: http://soundfile.sapp.org/doc/WaveFormat/
   */
  uint32_t ChunkSize, Subchunk1Size, Subchunk2Size;
  uint16_t NumChannels = NUM_CHANNELS;
  uint32_t ByteRate = SAMPLES_PER_SECOND * NumChannels * (BITS_PER_SAMPLE/8u);
  uint16_t BlockAlign = NumChannels * (BITS_PER_SAMPLE/8u);

  /* Subchunk2Size is the total amount of sample data */
  Subchunk2Size = num_samples * NumChannels * (BITS_PER_SAMPLE/8u);
  Subchunk1Size = 16u;
  ChunkSize = 4u + (8u + Subchunk1Size) + (8u + Subchunk2Size);

  /* Write the RIFF chunk descriptor */
  write_bytes(out, "RIFF", 4u);
  write_u32(out, ChunkSize);
  write_bytes(out, "WAVE", 4u);

  /* Write the "fmt " sub-chunk */
  write_bytes(out, "fmt ", 4u);       /* Subchunk1ID */
  write_u32(out, Subchunk1Size);
  write_u16(out, 1u);                 /* PCM format */
  write_u16(out, NumChannels);
  write_u32(out, SAMPLES_PER_SECOND); /* SampleRate */
  write_u32(out, ByteRate);
  write_u16(out, BlockAlign);
  write_u16(out, BITS_PER_SAMPLE);

  /* Write the beginning of the "data" sub-chunk, but not the actual data */
  write_bytes(out, "data", 4);        /* Subchunk2ID */
  write_u32(out, Subchunk2Size);
}

Функции ввода-вывода:

void write_byte(FILE* out, char val){

  fwrite(&val, sizeof(char), 1, out);
}

void write_bytes(FILE* out, const char data[], unsigned n){

  for (unsigned i=0; i<n; i++){
    write_byte(out, data[n]);
  }
}

void write_u16(FILE* out, uint16_t value){

  char bytes[] = {0, 0};
  //Lowest byte
  bytes[0] = value & 0xFF;
  //Biggest byte
  bytes[1] = value>>8;
  write_bytes(out, bytes, 2u);


  //fwrite(&value, sizeof(uint16_t), 1, out);
}

void write_u32(FILE* out, uint32_t value){

  uint16_t first = value & 0x0000FFFF;
  uint16_t second = value >> 16;;

  write_u16(out, first);
  write_u16(out, second);

    //fwrite(&value, sizeof(uint32_t), 1, out);
}

void write_s16(FILE* out, int16_t  value){

  uint16_t newV = (uint16_t)value;

  write_u16(out, newV);

  //fwrite(&value, sizeof(int16_t), 1, out);
}

void write_s16_buf(FILE* out, const int16_t  buf[], unsigned n){
  for (unsigned i=0; i<n; i++){
    write_s16(out, buf[n]);
  }
}

Я ожидал, что файл, созданный с помощью вызова ./render_tone 1 100 0,1 44100 out.wav, будет доступен для чтения звуковому проигрывателю, но out.wav приведет к ошибке, сообщающей, что при чтении заголовок отсутствует.

1 Ответ

0 голосов
/ 13 октября 2019

У вас есть опечатка (я полагаю) в вашей функции write_bytes():

void write_bytes(FILE* out, const char data[], unsigned n){

  for (unsigned i=0; i<n; i++){
    write_byte(out, data[n]);
  }
}

вы должны использовать data[i] вместо data[n]. Прямо сейчас, если вы позвоните:

write_bytes(out, "RIFF", 4u);

, он напишет \0 символ (NUL завершает строку c) 4 раза.

...