C++写wav文件到磁盘,为什么声音这么大?
C++ write wav file to disk, why is it so loud?
我已经编写了一些代码,以 .wav 格式将堆分配的浮点数组写入磁盘。
它工作得很好,除了输出非常响亮和失真。
这是我目前编写wav文件的代码:
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;
}
我在使用此代码之前所做的是使用 SDL2 加载 2 个 wav 文件,
然后将它们的数据“粘合”在一起以生成 1 个单一的 wav 文件。
我正在使用 SDL_QueueAudio 播放“粘合”数据,听起来很完美,没有问题!
唯一的问题是当我使用我编写的这个函数导出数据时。
输出非常响亮且失真。
我什至在 Bitwig (DAW) 中打开导出的 .wav 文件来查看波形,它看起来很奇怪:
正如我所说,
当我使用 SDL2 播放粘合数据时,它听起来很完美......所以我猜我的 wav_write
函数有问题。
我是这样称呼它的:
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);
如有任何帮助,我们将不胜感激。
干杯!
您在 header 中使用了错误的格式类型。
如您所见,here 您使用 format_type 1
作为 PCM 数据,但您使用的是浮点数据。
您应该改用 3
。
我已经编写了一些代码,以 .wav 格式将堆分配的浮点数组写入磁盘。 它工作得很好,除了输出非常响亮和失真。
这是我目前编写wav文件的代码:
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;
}
我在使用此代码之前所做的是使用 SDL2 加载 2 个 wav 文件, 然后将它们的数据“粘合”在一起以生成 1 个单一的 wav 文件。 我正在使用 SDL_QueueAudio 播放“粘合”数据,听起来很完美,没有问题!
唯一的问题是当我使用我编写的这个函数导出数据时。 输出非常响亮且失真。
我什至在 Bitwig (DAW) 中打开导出的 .wav 文件来查看波形,它看起来很奇怪:
正如我所说,
当我使用 SDL2 播放粘合数据时,它听起来很完美......所以我猜我的 wav_write
函数有问题。
我是这样称呼它的:
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);
如有任何帮助,我们将不胜感激。 干杯!
您在 header 中使用了错误的格式类型。
如您所见,here 您使用 format_type 1
作为 PCM 数据,但您使用的是浮点数据。
您应该改用 3
。