Изменение частоты дискретизации и байтов WAV-файла без проблем с открытием файла?

Я пытаюсь записать содержимое wav-файла размером 503 196 байт в другой и удвоить частоту дискретизации / байт, чтобы удвоить скорость. However, I'm having trouble reading in the data from the input file and writing it to the output file. Вот мой код:

#include <stdio.h>

int main() {
    struct WAVE {
           char ChunkID[4];
           unsigned int ChunkSize;
           char Format[4];
           char Subchunk1ID[4];
           unsigned int Subchunk1Size;
           unsigned short int AudioFormat;
           unsigned short int NumChannels;
           unsigned int SampleRate;
           unsigned int ByteRate;
           unsigned short int BlockAlign;
           unsigned short int BitsPerSample;
           char Subchunk2ID[4];
           unsigned int Subchunk2Size;
    } wav;
    FILE *original, *fast;
    original = fopen("Alejandro_project.wav", "rb");
    fast = fopen("Alejandro_fast.wav", "wb");
    if (original == NULL) {
                 printf("File does not exist.\n");
                 return 0;
    }
    fread(&wav, 1, 44, original);
    unsigned short int data[12 * wav.SampleRate]
    int i;
    for (i = 0; i < Subchunk2Size / 2; i++)
        fread(&data[i], 1, 2, original);
    fwrite(&wav, 1, 44, fast);
    unsigned int fastSampleRate = wav.SampleRate * 2;
    unsigned int fastByteRate = 2 * fastSampleRate;
    fseek(fast, 24, SEEK_SET);
    fwrite(&fastSampleRate, 4, 1, fast);
    fseek(fast, 28, SEEK_SET);
    fwrite(&fastByteRate, 4, 1, fast);
    fwrite(data, 1, 2, original);
    fclose(fast);
    fclose(original);
}

3 ответа

Есть несколько проблем... для начала, вам нужно убедиться, что структура вашего заголовка WAVE упакована так, чтобы в структуре не было неожиданного заполнения, которое могло бы выровнять некоторые поля и увеличить размер структуры. В противном случае вы, вероятно, получите два байта дополнительного заполнения после каждого из unsigned short int члены.

#pragma pack(push,1) /* for VC, may also work for GCC */
struct WAVE {
     /* ...struct contents... */
} wav;
#pragma pack(pop)

Во-вторых, похоже, что вы пытаетесь просто перезаписать элементы SampleRate и ByteRate в новом файле, оставив остальные без изменений. Это будет работать только в том случае, если новый файл уже является копией старого. Если это так, вам также нужно изменить режим, в котором вы открываете новый файл, на "r+b" (режим чтения + запись) вместо "wb" (режим записи), чтобы существующее содержимое файла не было отброшено.

Там также ошибка при попытке написать заголовок. Эта строка:

fread(original, 1, 44, fast);

Наверное, должно было быть:

fwrite(&wav, 44, 1, fast);

записать 44 байта из wav в новый файл, а не чтение из нового файла и использование старого файла FILE * в качестве пункта назначения.


Если новый файл уже не является копией старого, вам нужно будет скопировать и остальную часть файла (включая другие части заголовка). В этом случае, вероятно, проще всего (после открытия файлов):

  1. Прочитайте заголовок из старого файла в wav

    fread(&wav, sizeof(wav), 1, original);
    
  2. Изменить SampleRate а также ByteRate поля

    wav.SampleRate *= 2;
    wav.ByteRate *= 2;
    
  3. Напиши весь модифицированный wav заголовок к новому файлу

    fwrite(&wav, sizeof(wav), 1, fast);
    
  4. Скопируйте остаток старого файла в новый файл в цикле

    char buf[1024];
    int count;
    while ((count = fread(buf, 1, sizeof(buf), original)) > 0)
        fwrite(buf, 1, count, fast);
    

..и затем закройте файлы и вернитесь.

Чтобы удвоить скорость, вы не можете просто изменить sample rate или же byte-rate в заголовке WAV. Если вы сделаете это, он будет играть быстро, но будет звучать странно из-за неправильной высоты тона. Вместо этого вам нужно использовать соответствующую библиотеку преобразования частоты дискретизации (SRC) для преобразования входного файла WAV в выходной файл WAV с более высокой частотой дискретизации.

Я понял. Я удалил структуру, чтобы посмотреть, что я делаю. Я собираюсь включить структуру обратно, как только я закончу свой последний проект.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    FILE *original, *fast, *slow, *slowdown;
    unsigned int ChunkSize, Subchunk1Size, Subchunk2Size, RIFFSize, fmtSize, dataSize, SampleRate, ByteRate;
    unsigned short int AudioFormat, NumChannels, BlockAlign, BitsPerSample;
    char ChunkID[5], Format[5], Subchunk1ID[5], Subchunk2ID[5];
    ChunkID[4] = '\0';
    Format[4] = '\0';
    Subchunk1ID[4] = '\0';
    Subchunk2ID[4] = '\0';
    char path[FILENAME_MAX], dfast[FILENAME_MAX], dslow[FILENAME_MAX], dslowdown[FILENAME_MAX];
    printf("Enter path to Alejandro_project.wav file: ");
    scanf("%s", path);
    strcpy(dfast, path);
    dfast[strlen(path) - 21] = '\0';
    strcpy(dslow, dfast);
    strcpy(dslowdown, dslow);
    strcat(dfast, "Alejandro_fast.wav");
    strcat(dslow, "Alejandro_slow.wav");
    strcat(dslowdown, "Alejandro_slowdown.wav");
    original = fopen(path, "rb");
    if (!original) {
        printf("Error: file does not exist.\n");
        return EXIT_FAILURE;
    }
    fread(ChunkID, 4, 1, original);
    fread(&ChunkSize, 4, 1, original);
    fread(Format, 4, 1, original);
    fread(Subchunk1ID, 4, 1, original);
    fread(&Subchunk1Size, 4, 1, original);
    fread(&AudioFormat, 2, 1, original);
    fread(&NumChannels, 2, 1, original);
    fread(&SampleRate, 4, 1, original);
    fread(&ByteRate, 4, 1, original);
    fread(&BlockAlign, 2, 1, original);
    fread(&BitsPerSample, 2, 1, original);
    fread(Subchunk2ID, 4, 1, original);
    fread(&Subchunk2Size, 4, 1, original);
    fmtSize = Subchunk1Size + 8;
    dataSize = Subchunk2Size + 8;
    RIFFSize = ChunkSize + 8 - (fmtSize + dataSize);
    printf("RIFF Size:     %d\n", RIFFSize);
    printf("fmt Size:      %d\n", fmtSize);
    printf("data Size:     %d\n\n", dataSize);
    printf("ChunkID:       %s\n", ChunkID);
    printf("ChunkSize:     %d\n", ChunkSize);
    printf("Format:        %s\n\n", Format);
    printf("Subchunk1ID:   %s\n", Subchunk1ID);
    printf("Subchunk1Size: %d\n", Subchunk1Size);
    printf("AudioFormat:   %d\n", AudioFormat);
    printf("NumChannels:   %d\n", NumChannels);
    printf("SampleRate:    %d\n", SampleRate);
    printf("ByteRate:      %d\n", ByteRate);
    printf("BlockAlign:    %d\n", BlockAlign);
    printf("BitsPerSample: %d\n\n", BitsPerSample);
    printf("Subchunk2ID:   %s\n", Subchunk2ID);
    printf("Subchunk2Size: %d\n", Subchunk2Size);
    fseek(original, 0, SEEK_SET);
    fast = fopen(dfast, "wb");
    unsigned int fastSampleRate = SampleRate * 2;
    unsigned int fastByteRate = 2 * fastSampleRate;
    fwrite(ChunkID, 4, 1, fast);
    fwrite(&ChunkSize, 4, 1, fast);
    fwrite(Format, 4, 1, fast);
    fwrite(Subchunk1ID, 4, 1, fast);
    fwrite(&Subchunk1Size, 4, 1, fast);
    fwrite(&AudioFormat, 2, 1, fast);
    fwrite(&NumChannels, 2, 1, fast);
    fwrite(&fastSampleRate, 4, 1, fast);
    fwrite(&fastByteRate, 4, 1, fast);
    fwrite(&BlockAlign, 2, 1, fast);
    fwrite(&BitsPerSample, 2, 1, fast);
    fwrite(Subchunk2ID, 4, 1, fast);
    fwrite(&Subchunk2Size, 4, 1, fast);
    short int data;
    unsigned int i;
    for (i = 0; i < Subchunk2Size / 2; i++) {
        fread(&data, 2, 1, original);
        fwrite(&data, 2, 1, fast);
    }
    fclose(fast);
    fseek(original, 0, SEEK_SET);
    slow = fopen(dslow, "wb");
    unsigned int slowSampleRate = SampleRate / 2;
    unsigned int slowByteRate = 2 * slowSampleRate;
    fwrite(ChunkID, 4, 1, slow);
    fwrite(&ChunkSize, 4, 1, slow);
    fwrite(Format, 4, 1, slow);
    fwrite(Subchunk1ID, 4, 1, slow);
    fwrite(&Subchunk1Size, 4, 1, slow);
    fwrite(&AudioFormat, 2, 1, slow);
    fwrite(&NumChannels, 2, 1, slow);
    fwrite(&slowSampleRate, 4, 1, slow);
    fwrite(&slowByteRate, 4, 1, slow);
    fwrite(&BlockAlign, 2, 1, slow);
    fwrite(&BitsPerSample, 2, 1, slow);
    fwrite(Subchunk2ID, 4, 1, slow);
    fwrite(&Subchunk2Size, 4, 1, slow);
    for (i = 0; i < Subchunk2Size / 2; i++) {
        fread(&data, 2, 1, original);
        fwrite(&data, 2, 1, slow);
    }
    fclose(slow);    
    fclose(original);
    system("pause");
    return EXIT_SUCCESS;
}
Другие вопросы по тегам