将.wav文件转换为单声道(删除右声道)

时间:2018-11-15 06:18:35

标签: c wav

enter image description here我正在尝试从.wav文件中删除正确的频道,但无济于事。有关原始标题的一些信息:

NumChannels:2,BlockAlign:4,BitsPerSample:16

由此我得到样本大小为4个字节(2Left + 2Right),因此我正在创建一个新文件,向其写入原始标头,然后一次从原始文件向该新文件写入4个字节使用AND掩码0xffff0000将右通道清零。尽管似乎正确通道的音量似乎减少了90%,但我正在寻找一些改进。下面的代码部分:

int convertToMono(char *original) {
    Header *header = malloc(sizeof(Header));
    getHeader(header, original);

    FILE *fp = fopen(original, "rb");
    fseek(fp, HEADER_SIZE, 0);// Advance HEADER_SIZE bytes to data section

    // Create new file name
    char *name = malloc((5 + strlen(original)) * sizeof(char));
    strcpy(name, "new-");
    strcat(name, original);

    // Open new file and write the header to it
    FILE *new = fopen(name, "wb");
    fwrite(header, HEADER_SIZE, 1, new);

    u_int sample = 0;// unsigned int, size in bytes == 4
    for (int i = 0; i < header->chunkSize - HEADER_SIZE + 8; i += sizeof(u_int)) {
        fread(&sample, sizeof(u_int), 1, fp);
        sample = (sample & 0xffff0000);
        fwrite(&sample, sizeof(u_int), 1, new);
    }

    fclose(fp);
    fclose(new);
    free(name);
    return 0;
}

编辑:从音频中添加了Audacity显示的图片。

1 个答案:

答案 0 :(得分:0)

要转换为单声道,首先必须更改与numChannels字段关联的标题信息:

header->numChannels = 1;
header->subchunk2Size /= 2;
header->chunkSize = header->subchunk2Size + 36;
header->byteRate /= 2;
header->blockAlign /= 2;

然后打开新文件,并将修改后的标头写入其中:

FILE *fp2 = fopen("new.wav", "wb");
fwrite(header, HEADER_SIZE, 1, fp2);

创建一个可以容纳一半样本的缓冲区:

size_t channel_size = (size_t) (header->bitsPerSample / 8);
char sample[channel_size];

读写所有样本的左通道,而忽略右通道。

for (int i = 0; i < header->subchunk2Size; i += channel_size) {
    fread(sample, channel_size, 1, fp1);
    fwrite(sample, channel_size, 1, fp2);

    fread(sample, channel_size, 1, fp1);
}

这将创建一个原始大小一半的文件,并且只会听到左声道。注意:这并不意味着声音只会来自左耳机。