用c程序实现双波速度

Double wav speed with c program

我已经在 c 中创建了一个程序,它使用 getchar 读取 wav 文件。

我运行程序是这样的./wavproc

我想将声音的速度加倍并用 putchar 创建一个新的 wav 文件。

我必须 运行 这样的程序 ./wavproc < sound.wav > soundX2.wav

因为是练习,所以必须只使用getchar和putchar。

我把我写的代码放上去

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

int main(){

unsigned char buffer4[4];
unsigned char buffer2[2];

unsigned int size_of_file;
unsigned int size_of_format_chunck;
unsigned int wave_type_format;
unsigned int mono_stereo;   
unsigned int sample_rate;
unsigned int bytes_per_second;
unsigned int block_alignment;
unsigned int bits_per_sample;
unsigned int size_of_data_chunck;   
char riff[4];
char wave[4];
char fmt[4];
char data[4];

int i;


char c;

while(1) {
    c = getchar();
    putchar(c);
    if(c == EOF)
        break;
}   




//read bytes 1-4 to check RIFF
for(i=0;i<4;i++){
  riff[i] = getchar();
}

if(riff[0] != 'R') {
    fprintf(stderr, "Error! \"RIFF\" not found\n");
    return 1;
} else if(riff[1] != 'I') {
    fprintf(stderr, "Error! \"RIFF\" not found\n");   
            return 1;
} else if(riff[2] != 'F') {
    fprintf(stderr, "Error! \"RIFF\" not found\n");   
            return 1;
} else if(riff[3] != 'F') {
    fprintf(stderr, "Error! \"RIFF\" not found\n");   
            return 1;
}

//read bytes 5-8 for size of file
for(i=0;i<4;i++) {
    buffer4[i] = getchar();
}
size_of_file = buffer4[0] | (buffer4[1]<<8) | (buffer4[2]<<16) | (buffer4[3]<<24);
fprintf(stderr, "size of file: %d\n",size_of_file);


//read bytes 9-12 to check WAVE 
for(i=0; i<4; i++) {
    wave[i] = getchar();
}

if(wave[0] != 'W') {
            fprintf(stderr, "Error! \"WAVE\" not found\n");
            return 1;
    } else if(wave[1] != 'A') {
            fprintf(stderr, "Error! \"WAVE\" not found\n");
            return 1;
    } else if(wave[2] != 'V') {
            fprintf(stderr, "Error! \"WAVE\" not found\n");
            return 1;
    } else if(wave[3] != 'E') {
            fprintf(stderr, "Error! \"WAVE\" not found\n");
            return 1;
    }

//read bytes 13-16 to check fmt
    for(i=0; i<4; i++) {
            fmt[i] = getchar();
    }

    if(fmt[0] != 'f') {
            fprintf(stderr, "Error! \"fmt \" not found\n");
            return 1;
    } else if(fmt[1] != 'm') {
            fprintf(stderr, "Error! \"fmt \" not found\n");
            return 1;
    } else if(fmt[2] != 't') {
            fprintf(stderr, "Error! \"fmt \" not found\n");
            return 1;
    } else if(fmt[3] != ' ') {
            fprintf(stderr, "Error! \"fmt \" not found\n");
            return 1;
    }

//read bytes 17-20 for size of format chunck
for(i=0; i<4; i++) {
    buffer4[i] = getchar();
}
size_of_format_chunck = buffer4[0] | (buffer4[1]<<8) | (buffer4[2]<<16) | (buffer4[3]<<24);
fprintf(stderr, "size of format chunck: %d\n",size_of_format_chunck);

if(size_of_format_chunck != 16) {
    fprintf(stderr, "Error! size of format chunck should be 16\n");
    return 1;
}

//read bytes 21-22 for wave type format
    for(i=0; i<2; i++) {
            buffer2[i] = getchar();
    }
    wave_type_format = buffer2[0] | (buffer2[1]<<8);
    fprintf(stderr, "WAVE type format: %d\n",wave_type_format);

if(wave_type_format!=1) {
    fprintf(stderr, "Error! WAVE type format should be 1\n");
    return 1;
}

//read bytes 23-24 for mono stereo
    for(i=0; i<2; i++) {
            buffer2[i] = getchar();
    }
    mono_stereo = buffer2[0] | (buffer2[1]<<8);
    fprintf(stderr, "mono/stereo: %d\n",mono_stereo);

if(mono_stereo!=1 && mono_stereo!=2) {
    fprintf(stderr, "Error! mono/stereo should be 1 or 2\n");
    return 1;
}

//read bytes 25-28 for sample rate
    for(i=0; i<4; i++) {
            buffer4[i] = getchar();
    }
    sample_rate = buffer4[0] | (buffer4[1]<<8) | (buffer4[2]<<16) | (buffer4[3]<<24);
    fprintf(stderr, "sample rate: %d\n",sample_rate);

//read bytes 29-32 for bytes per second
    for(i=0; i<4; i++) {
            buffer4[i] = getchar();
    }
    bytes_per_second = buffer4[0] | (buffer4[1]<<8) | (buffer4[2]<<16) | (buffer4[3]<<24);
    fprintf(stderr, "bytes/sec: %d\n",bytes_per_second);

//read bytes 33-34 for block alignment
    for(i=0; i<2; i++) {
            buffer2[i] = getchar();
    }
    block_alignment = buffer2[0] | (buffer2[1]<<8);
    fprintf(stderr, "block alignment: %d\n",block_alignment);

if(bytes_per_second!=sample_rate*block_alignment) {
    fprintf(stderr, "Error! bytes/second should be sample rate x block alignment\n");
    return 1;
}

//read bytes 35-36 for bits per sample
    for(i=0; i<2; i++) {
            buffer2[i] = getchar();
    }
    bits_per_sample = buffer2[0] | (buffer2[1]<<8);
    fprintf(stderr, "bits/sample: %d\n",bits_per_sample);

if(bits_per_sample!=8 && bits_per_sample!=16) {
    fprintf(stderr, "Error! bits/sample should be 8 or 16\n");
    return 0;
}

if(block_alignment!=bits_per_sample/8*mono_stereo) {
    fprintf(stderr, "Error! block alignment should be bits per sample / 8 x mono/stereo\n");
    return 1;
}

//read bytes 37-40 to check data
    for(i=0; i<4; i++) {
            data[i] = getchar();
    }

    if(data[0] != 'd') {
            fprintf(stderr, "Error! \"data\" not found\n");
            return 1; 
    } else if(data[1] != 'a') {
            fprintf(stderr, "Error! \"data\" not found\n");
            return 1; 
    } else if(data[2] != 't') {
            fprintf(stderr, "Error! \"data\" not found\n");
            return 1; 
    } else if(data[3] != 'a') {
            fprintf(stderr, "Error! \"data\" not found\n");
            return 1;
    }

//read bytes 41-44 for bytes per second
    for(i=0; i<4; i++) {
            buffer4[i] = getchar();
    }
    size_of_data_chunck = buffer4[0] | (buffer4[1]<<8) | (buffer4[2]<<16) | (buffer4[3]<<24);
    fprintf(stderr, "size of data chunck: %d\n",size_of_data_chunck);

//check if file size is correct
i=44;
while(getchar()!=EOF)
    i++;

if(i!=size_of_file+8) {
    fprintf(stderr,"Error! bad file size\n");
    return 1;
}

return 0;
}

问题是如何将声音的速度加倍并创建一个新的 wav 文件?

首先。除非您将此作为纯粹的练习,否则您不应该从头开始编写此类内容。你应该使用图书馆。那里有一些。

The question is how to double sound's speed and create a new wav file?

实现这一点的绝对最简单的方法就是简单地将采样率加倍。将其他所有内容都写入一个新文件,但首先将采样率加倍,然后将以双倍速度播放。

如果您想尝试一下,请获取一个 hexeditor,然后只需编辑采样率字段即可。

但请注意,这种方法“有效”。为了正确地做到这一点,您还应该修改 ByteRate 字段,它紧跟在 SampleRate 字段之后。我跳过了那部分。

这是一个非常小的例子,可以完成这项工作:

#include <stdio.h>
#include <stdint.h>

int main(void)
{
    // Copy everything before sample rate
    for(size_t i=0; i<24; i++)
        putchar(getchar());

    // Read the sample rate
    unsigned char b[4];
    for(size_t i=0; i<4; i++)
        b[i] = getchar();

    // Double it
    uint32_t sr = b[0] | (b[1]<<8) | (b[2]<<16) | (b[3]<<24);
    sr *= 2;

    // Write the doubled rate
    for(size_t i=0; i<4; i++)
        putchar((sr >> i*8) & 0xFF);

    // Copy the rest
    int ch;
    while((ch = getchar()) != EOF)
        putchar(ch);
}

请注意,这是非常小的。我已经完全跳过了任何错误检查。如果采样率太高,那么这将不起作用。

以上是无损方法。如果你想保持采样率,那么你需要删除信息。我不确定该怎么做,但我想你可以取两个样本的平均值。或者,也许只是跳过彼此。如果我不得不猜测,我认为最好的方法是做类似的事情:

new_sample = exp(log(sample1) + log(sample2))

不过我没试过