Sebastian Karlsson
Sebastian Karlsson

Reputation: 745

C++ write wav file to disk, why is it so loud?

I have written some code that writes a heap allocated float array to disk in the .wav format. It works great except that the output is really loud and distorted.

Here is the code that I currently have to write the wav file:

typedef struct WAV_HEADER {
  uint8_t riff[4] = {'R', 'I', 'F', 'F'};
  uint32_t overall_size;
  uint8_t wave[4] = {'W', 'A', 'V', 'E'};
  uint8_t fmt_chunk_marker[4] = {'f', 'm', 't', ' '};
  uint32_t length_of_fmt;
  uint16_t format_type;
  uint16_t channels;
  uint32_t sample_rate;
  uint32_t byterate;
  uint16_t block_align;
  uint16_t bits_per_sample;
  uint8_t data_chunk_header[4] = {'d', 'a', 't', 'a'};
  uint32_t data_size;
} WavHeader;


int wav_write(const char* path, float* data, uint32_t size, float sample_freq,
              uint16_t bits_per_sample, uint16_t nr_channels) {



  WavHeader header = {};
  header.length_of_fmt = 16;
  header.format_type = 1;
  header.channels = nr_channels;
  header.sample_rate = sample_freq;
  header.bits_per_sample = bits_per_sample;
  header.byterate = header.sample_rate * header.channels * (header.bits_per_sample / 8);
  header.block_align = (header.bits_per_sample / 8) * header.channels;
  header.data_size = sizeof(&data[0]) * (size >> 3);
  header.overall_size = (header.data_size);

  FILE* out = fopen(path, "wb");
  if (out == NULL) {
    printf("Could not write to %s\n", path);
    return 0;
  }

  fwrite(&header, sizeof(header), 1, out);
  fseek(out,0,SEEK_END);

  fwrite(&data[0], sizeof(&data[0]), size, out);

  fclose(out);

  return 1;
}

What I am doing before I use this code is that I load 2 wav files using SDL2, and then "glue" their data together to produce 1 single wav file. I am playing the "glued" data using SDL_QueueAudio, and it sounds perfect, no issues there!

The only issue is when I export that data using this function that I wrote. The output is extremely loud and distorted.

I even opened up the exported .wav file in Bitwig (DAW) to see the waveform, and it looks pretty weird:

enter image description here

And as I said, when I play the glued data using SDL2, it sounds perfect... So I'm guessing there's something wrong with my wav_write function.

I am calling it like this:

  char buff[256];
  sprintf(buff, "%s.wav", this->project_name.c_str());
  wav_write(buff, this->playback_buffer, this->playback_buffer_size_bytes, PLAYBACK_FREQ, 32, 2);

Any help would be very appreciated. Cheers!

Upvotes: 1

Views: 332

Answers (1)

super
super

Reputation: 12928

You are using the wrong format type in your header.

As you can see here you use format_type 1 for PCM data, but you have float data.

You should be using 3 instead.

Upvotes: 3

Related Questions