Преобразование WAV-файла в моно (удалить правый канал) - PullRequest
0 голосов
/ 15 ноября 2018

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 голосов
/ 17 ноября 2018

Для преобразования в моно сначала необходимо изменить информацию заголовка, связанную с полем 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);
}

При этом будет создан файл, размер которого наполовину меньше исходного, и будет слышен только левый канал. Примечание. Это не означает, что звук будет исходить только от левого наушника.

...