逐渐将音频文件从正常速度减慢到半速?

时间:2015-07-14 02:10:36

标签: c audio interpolation wav slowdown

我试图从音频文件中获取内容并将其写入另一个音频文件 - 除了输出应以正常速度开始,然后随着时间的推移减速并以原始速度的一半结束。我尝试拉格朗日插值方法,但似乎无法使其正确。我暂时停止结构只是为了看看我在做什么。这是我的代码:

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

int main() {
    FILE *original, *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], dslowdown[FILENAME_MAX];
    printf("Enter path to Alejandro_project.wav file:\n");
    scanf("%s", path);
    strcpy(dslowdown, path);
    dslowdown[strlen(path) - 21] = '\0';
    strcat(dslowdown, "Alejandro_fast.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);
    fseek(original, 0, SEEK_SET);
    slowdown = fopen(dslowdown, "wb");
    fwrite(ChunkID, 4, 1, slowdown);
    fwrite(&ChunkSize, 4, 1, slowdown);
    fwrite(Format, 4, 1, slowdown);
    fwrite(Subchunk1ID, 4, 1, slowdown);
    fwrite(&Subchunk1Size, 4, 1, slowdown);
    fwrite(&AudioFormat, 2, 1, slowdown);
    fwrite(&NumChannels, 2, 1, slowdown);
    fwrite(&SampleRate, 4, 1, slowdown);
    fwrite(&ByteRate, 4, 1, slowdown);
    fwrite(&BlockAlign, 2, 1, slowdown);
    fwrite(&BitsPerSample, 2, 1, slowdown);
    fwrite(Subchunk2ID, 4, 1, slowdown);
    fwrite(&Subchunk2Size, 4, 1, slowdown);
    short int t[4], audio[Subchunk2Size / 2], f[4];
    for (i = 0; i < Subchunk2Size / 2; i++) {
        fread(&data, 2, 1, original);
        audio[i] = data;
    }
    for (i = 0; i < sizeof(t) / 2; i++)
        t[i + 1] = t[i] + (11.41 - t[i]) / 11.41 * (1.0 / 22050.0) + t[i] / 11.41 * (0.4 / 22050.0);
    for (i = 0; i < sizeof(f) / 2; i++) {
        f[i + 1] = ((t[i] - t[i - 1]) * (t[i] - t[i + 1]) * (t[i] - t[i + 2])) / ((t[i - 2] - t[i - 1]) * (t[i - 2] - t[i + 1]) * (t[i - 2] - t[i + 2])) * f[i - 2] + ((t[i] - t[i - 2]) * (t[i] - t[i + 1]) * (t[i] - t[i + 2])) / ((t[i - 1] - t[i - 2]) * (t[i - 1] - t[i + 1]) * (t[i - 1] - t[i + 2])) * f[i - 1] + ((t[i] - t[i - 2]) * (t[i] - t[i - 1]) * (t[i] - t[i + 2])) / ((t[i + 1] - t[i - 2]) * (t[i + 1] - t[i - 1]) * (t[i + 1] - t[i + 2])) * f[i + 1] + ((t[i] - t[i - 2]) * (t[i] - t[i - 1]) * (t[i] - t[i + 2])) / ((t[i + 1] - t[i - 2]) * (t[i + 1] - t[i - 1]) * (t[i + 1] - t[i + 2])) * f[i + 2];
    }
    for (i = 0; i < Subchunk2Size; i++) {
        audio[i] = audio[f[i]];
    }
    fwrite(audio, sizeof(audio), 1, slowdown);
    fseek(slowdown, 40, SEEK_SET);
    fwrite(&Subchunk2Size, 4, 1, slowdown);
    fseek(slowdown, 40, SEEK_SET);
    fwrite(audio, sizeof(audio), 1, slowdown);
    fseek(slowdown, 4, SEEK_SET);
    fwrite(&ChunkSize, 4, 1, slowdown);
    fclose(slowdown);
    fclose(original);
    return EXIT_SUCCESS;
}

1 个答案:

答案 0 :(得分:0)

我明白了。我回到struct并重新编写数学。

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

int main() {
    FILE *original, *fast, *slow, *slowdown;
    unsigned int RIFFSize, fmtSize, dataSize;
    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;
        int SampleRate;
        int ByteRate;
        unsigned short int BlockAlign;
        unsigned short int BitsPerSample;
        char Subchunk2ID[4];
        unsigned int Subchunk2Size;
    } o, f, s, sd;
    char path[FILENAME_MAX], dfast[FILENAME_MAX], dslow[FILENAME_MAX], dslowdown[FILENAME_MAX];
    printf("Enter the path to an input WAVE (.wav) file:\n");
    gets(path);
    strcpy(dfast, path);
    dfast[strlen(path) - 4] = '\0';
    strcpy(dslow, dfast);
    strcpy(dslowdown, dslow);
    strcat(dfast, "_fast.wav");
    strcat(dslow, "_slow.wav");
    strcat(dslowdown, "_slowdown.wav");
    original = fopen(path, "rb");
    if (!original) {
        printf("Error: file does not exist.\n");
        return EXIT_FAILURE;
    }
    fread(&o, 44, 1, original);
    fseek(original, 0, SEEK_SET);
    fread(&f, 44, 1, original);
    fseek(original, 0, SEEK_SET);
    fread(&s, 44, 1, original);
    fseek(original, 0, SEEK_SET);
    fread(&sd, 44, 1, original);
    fmtSize = o.Subchunk1Size + 8;
    dataSize = o.Subchunk2Size + 8;
    RIFFSize = o.ChunkSize + 8 - (fmtSize + dataSize);
    printf("Characteristics of %s:\n", path);
    printf("RIFF Size:     %d\n", RIFFSize);
    printf("fmt Size:      %d\n", fmtSize);
    printf("data Size:     %d\n\n", dataSize);
    printf("ChunkID:       %.4s\n", o.ChunkID);
    printf("ChunkSize:     %d\n", o.ChunkSize);
    printf("Format:        %.4s\n\n", o.Format);
    printf("Subchunk1ID:   %.4s\n", o.Subchunk1ID);
    printf("Subchunk1Size: %d\n", o.Subchunk1Size);
    printf("AudioFormat:   %d\n", o.AudioFormat);
    printf("NumChannels:   %d\n", o.NumChannels);
    printf("SampleRate:    %d\n", o.SampleRate);
    printf("ByteRate:      %d\n", o.ByteRate);
    printf("BlockAlign:    %d\n", o.BlockAlign);
    printf("BitsPerSample: %d\n\n", o.BitsPerSample);
    printf("Subchunk2ID:   %.4s\n", o.Subchunk2ID);
    printf("Subchunk2Size: %d\n\n", o.Subchunk2Size);
    fseek(original, 0, SEEK_SET);
    fast = fopen(dfast, "wb");
    f.SampleRate = o.SampleRate * 2;
    f.ByteRate = 2 * f.SampleRate;
    fseek(fast, 0, SEEK_SET);
    fwrite(&f, 44, 1, fast);
    fmtSize = f.Subchunk1Size + 8;
    dataSize = f.Subchunk2Size + 8;
    RIFFSize = f.ChunkSize + 8 - (fmtSize + dataSize);
    printf("\nCharacteristics of %s:\n", dfast);
    printf("RIFF Size:     %d\n", RIFFSize);
    printf("fmt Size:      %d\n", fmtSize);
    printf("data Size:     %d\n\n", dataSize);
    printf("ChunkID:       %.4s\n", f.ChunkID);
    printf("ChunkSize:     %d\n", f.ChunkSize);
    printf("Format:        %.4s\n\n", f.Format);
    printf("Subchunk1ID:   %.4s\n", f.Subchunk1ID);
    printf("Subchunk1Size: %d\n", f.Subchunk1Size);
    printf("AudioFormat:   %d\n", f.AudioFormat);
    printf("NumChannels:   %d\n", f.NumChannels);
    printf("SampleRate:    %d\n", f.SampleRate);
    printf("ByteRate:      %d\n", f.ByteRate);
    printf("BlockAlign:    %d\n", f.BlockAlign);
    printf("BitsPerSample: %d\n\n", f.BitsPerSample);
    printf("Subchunk2ID:   %.4s\n", f.Subchunk2ID);
    printf("Subchunk2Size: %d\n\n", f.Subchunk2Size);
    short int data;
    unsigned int i;
    for (i = 0; i < f.Subchunk2Size / 2; i++) {
        fread(&data, 2, 1, original);
        fwrite(&data, 2, 1, fast);
    }
    fclose(fast);
    fseek(original, 0, SEEK_SET);
    slow = fopen(dslow, "wb");
    s.SampleRate = o.SampleRate / 2;
    s.ByteRate = 2 * s.SampleRate;
    fseek(slow, 0, SEEK_SET);
    fwrite(&s, 44, 1, slow);
    printf("\nCharacteristics of %s:\n", dslow);
    printf("RIFF Size:     %d\n", RIFFSize);
    printf("fmt Size:      %d\n", fmtSize);
    printf("data Size:     %d\n\n", dataSize);
    printf("ChunkID:       %.4s\n", s.ChunkID);
    printf("ChunkSize:     %d\n", s.ChunkSize);
    printf("Format:        %.4s\n\n", s.Format);
    printf("Subchunk1ID:   %.4s\n", s.Subchunk1ID);
    printf("Subchunk1Size: %d\n", s.Subchunk1Size);
    printf("AudioFormat:   %d\n", s.AudioFormat);
    printf("NumChannels:   %d\n", s.NumChannels);
    printf("SampleRate:    %d\n", s.SampleRate);
    printf("ByteRate:      %d\n", s.ByteRate);
    printf("BlockAlign:    %d\n", s.BlockAlign);
    printf("BitsPerSample: %d\n\n", s.BitsPerSample);
    printf("Subchunk2ID:   %.4s\n", s.Subchunk2ID);
    printf("Subchunk2Size: %d\n\n", s.Subchunk2Size);
    for (i = 0; i < s.Subchunk2Size / 2; i++) {
        fread(&data, 2, 1, original);
        fwrite(&data, 2, 1, slow);
    }
    fclose(slow);
    fseek(original, 0, SEEK_SET);
    slowdown = fopen(dslowdown, "wb");
    unsigned int samples;
    fseek(original, 44, SEEK_SET);
    fseek(slowdown, 44, SEEK_SET);
    samples = o.Subchunk2Size / 2;
    double dt = 1/22050.0, out, space, t;
    double point[4], ta, tb, tc, td;
    unsigned int stamp;
    unsigned int count = 0;
    short int fd[4], audio;
    t = dt;
    space = dt;
    point[0] = (-1.0) * (-2.0) * (-3.0) * dt;
    point[1] = (1.0) * (-1.0) * (-2.0) * dt;
    point[2] = (2.0) * (1.0) * (-1.0) * dt;
    point[3] = (3.0) * (2.0) * (1.0) * dt;

    while (t < (samples - 2) * dt) {
        stamp = (int)(t / dt - 1);
        fseek(original, 44 + stamp * 2, SEEK_SET);
        for(i = 0; i < 4; i++) {
            fread(&fd[i], 2, 1, original);
    }
        ta = stamp * dt;
        tb = (stamp + 1) * dt;
        tc = (stamp + 2) * dt;
        td = (stamp + 3);
        out = (((t - tb) * (t - tc) * (t - td)) / (point[0])) * fd[0] + (((t - ta) * (t - tc) * (t - td)) / (point[1])) * fd[1] + (((t - ta) * (t - tb) * (t - td)) / (point[2])) * fd[2] + (((t - ta) * (t - tb) * (t - tc)) / (point[3])) * fd[3];
        audio = (short int)(out);
        fwrite(&audio, 2, 1, slowdown);
        space = (((samples - 1) * dt - t) / ((samples - 1) * dt)) * dt + (t / ((samples - 1) * dt)) * .4 * dt;
        t += space;
        count++;
    }
    sd.Subchunk2Size = count * 2;
    sd.ChunkSize = 36 + sd.Subchunk2Size;
    fseek(slowdown, 0, SEEK_SET);
    fwrite(&sd, 44, 1, slowdown);
    fmtSize = sd.Subchunk1Size + 8;
    dataSize = sd.Subchunk2Size + 8;
    RIFFSize = sd.ChunkSize + 8 - (fmtSize + dataSize);
    printf("\nCharacteristics of %s:\n", dslowdown);
    printf("RIFF Size:     %d\n", RIFFSize);
    printf("fmt Size:      %d\n", fmtSize);
    printf("data Size:     %d\n\n", dataSize);
    printf("ChunkID:       %.4s\n", sd.ChunkID);
    printf("ChunkSize:     %d\n", sd.ChunkSize);
    printf("Format:        %.4s\n\n", sd.Format);
    printf("Subchunk1ID:   %.4s\n", sd.Subchunk1ID);
    printf("Subchunk1Size: %d\n", sd.Subchunk1Size);
    printf("AudioFormat:   %d\n", sd.AudioFormat);
    printf("NumChannels:   %d\n", sd.NumChannels);
    printf("SampleRate:    %d\n", sd.SampleRate);
    printf("ByteRate:      %d\n", sd.ByteRate);
    printf("BlockAlign:    %d\n", sd.BlockAlign);
    printf("BitsPerSample: %d\n\n", sd.BitsPerSample);
    printf("Subchunk2ID:   %.4s\n", sd.Subchunk2ID);
    printf("Subchunk2Size: %d\n\n", sd.Subchunk2Size);
    printf("\nAs you can see, the only differences between the fast/slow output files and the original input file are the sample rate and byte rate. However, the slowdown output file differs from the original input file not only in its sample rate and byte rate, but also in its data size, Chunk size, and Subchunk2 size.\n");
    fclose(slowdown);
    fclose(original);
    return EXIT_SUCCESS;
}