【问题标题】:Cutting amplitude of a signal from .wav file从 .wav 文件中切割信号的幅度
【发布时间】:2021-09-06 15:49:16
【问题描述】:

我目前正在开发一个打开 .wav 文件的 C 程序,将 .wav 标头复制到输出文件中,然后在标头之后添加从输入文件中获取的已处理数据。该过程包括将每个样本乘以 0.5,以降低信号的幅度。 这是我的代码:

程序.c

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

struct header_file
{
    char chunk_id[4];
    int chunk_size;
    char format[4];
    char subchunk1_id[4];
    int subchunk1_size;
    short int audio_format;
    short int num_channels;
    int sample_rate;        
    int byte_rate;
    short int block_align;
    short int bits_per_sample;
    char subchunk2_id[4];
    int subchunk2_size;
};

struct header_file header;

int main()

{
    
    FILE * inputfile = fopen("maneskin.wav","rb");      // deschidere fisier .wav, modul de citire
    FILE * outputfile = fopen("Output.wav","wb");       // creeaza fisierul .wav, modul de scriere

    int BUFFSIZE = 10000;                   // lungimea buffer-ului
    int count = 0;                      // numara cate frame-uri sunt in fisier
    short int inputBuffer[BUFFSIZE];
    short int outputBuffer[BUFFSIZE];           
/*  header_p meta = (header_p)malloc(sizeof(header));    */
    int nb;                         // numarul de bytes returnati
    int temp;

    if (inputfile)
    {
        
        fread(&header, sizeof(header),1, inputfile);
        fwrite(&header,sizeof(header),1, outputfile);
        
        short int ch2[BUFFSIZE];
         for(int i=0; i<BUFFSIZE; i++)                                           \
            ch2[i] = 1;  
    
        while (!feof(inputfile))//cat timp se citeste fisierul 
        {
             for(int i=0; i<BUFFSIZE && !feof(inputfile); i++) 
            fread((char*)&inputBuffer[i],sizeof(short int),1, inputfile);       // citirea datelor
            count++;// incrementarea numarului de frame-uri
                 for(int z=0; z<BUFFSIZE; z++){
                    outputBuffer[z]=0.5*inputBuffer[z];
                    }   
             for(int k=0; k<BUFFSIZE; k++)
             {

                fwrite((char*)&outputBuffer[k], sizeof(short int), 1, outputfile);// scriere in fisier
                
                 }
            
            
        }
    printf("Numarul de cadre din fisierul wav:%d\n", count);
    }
return 0;
}

我遇到的问题是,当我尝试使用 VLC 或任何其他媒体播放器打开输出文件时,它无法打开并给我一个错误。我认为在输出文件中写入标头可能有问题,但我不确定。我尝试在 Audacity 中将文件作为原始数据导入并播放音频文件,但如果我尝试将其导入为 wav 文件,它不起作用。可能是什么问题?

【问题讨论】:

  • 请看Why is while ( !feof (file) ) always wrong?请收集并使用fread返回的值来控制循环和fwrite。您根本没有使用它
  • 大概就是这样。给自己找一个十六进制编辑器(比如 HxD),看看标头中的哪些字节不同。
  • 是的,header是我程序的第一个问题。我在原始文件和输出文件的标题上查看了HxD,它们是不同的。
  • 你可以发布不同的标题。

标签: c signal-processing wav audio-processing


【解决方案1】:

我不知道这是否是你唯一的问题,但这绝对是一个问题...... 在 C 中,通常当您定义一个结构时,该结构的成员在内存中不会彼此相邻。编译器将它们安排在处理器舒适的边界上,通常以处理器的字长为增量。所以一个 char 类型的元素被两个 int 包围,并没有坐落在它们之间,但实际上它和下一个元素之间可能有 7 个字节的空间。

这样做是为了提高执行效率,通常是有意义的。

但在这种情况下,您希望将结构元素紧密地打包在一起,为此有一种标准方法可以告诉编译器这就是您想要的:

/* pack in 1 byte increments */
#pragma pack(1)

struct header_file
{
    char chunk_id[4];
    int chunk_size;
    char format[4];
    char subchunk1_id[4];
    int subchunk1_size;
    short int audio_format;
    short int num_channels;
    int sample_rate;        
    int byte_rate;
    short int block_align;
    short int bits_per_sample;
    char subchunk2_id[4];
    int subchunk2_size;
};

/* reset to default */
#pragma pack()

我还建议使用特定于大小的类型,例如 uint16_t 而不是 short int,因为您不知道在您的代码可能被编译的每个平台上 int 的大小。

在您的代码中,尝试打印 sizeof 标头以查看是否符合您的预期,例如:

printf("sizeof(header)=%d\n", sizeof(header));

如果数字与 WAV 标头的数字不匹配,则说明一个或多个元素的大小有问题,或者包装有问题。

【讨论】:

  • 我将其复制到我的代码中,sizeof(header) 的结果是 44,这是我的预期。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-18
相关资源
最近更新 更多