【问题标题】:Double wav speed with c programc程序加倍wav速度
【发布时间】:2021-03-15 11:41:27
【问题描述】:

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

我像这样运行程序 ./wavproc

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

我必须像这样运行程序./wavproc 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文件?

【问题讨论】:

  • 你忘了问问题
  • 您使用第一个 while 读取整个输入,因此以下所有 getchar() 调用都将返回 EOF。您可以编写一个函数来回显每个字符以输出并返回它:int mygetc() { int c = getchar(); if (c != EOF) putchar(c); return c; } 现在将代码中对getchar() 的每个调用替换为mygetc()
  • 鉴于char c;if(c == EOF) 无法可靠工作。 EOFint,而不是 char,因此 getchar() 返回 intc必须int
  • 抱歉,while 循环是对我复制 wav 文件的测试。顺便说一句,它写的是纯文本而不是二进制文件。
  • 处理检查 RIFF、WAVE 等的代码真的很奇怪。如果此代码被正确重写,它将大约缩短 5-6 倍。你应该做类似if (strncmp(fmt, "fmt ", 4) {fprintf(stderr, "Error!....

标签: c file file-io wav


【解决方案1】:

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

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

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

如果您想尝试一下,请获取一个十六进制编辑器,然后编辑采样率字段。

但请注意,这种方法“有效”。为了正确执行此操作,您还应该修改 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))

但我没试过。

【讨论】:

  • 感谢您的回答!我知道我必须将采样率加倍,但问题是我无法仅使用 putchar 方法将结果写入新文件。
  • @FalierisIlias 我更新了一个工作示例
猜你喜欢
  • 2016-12-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多