将编码的音频文件转换为具有信号值的文本

时间:2017-08-08 19:33:26

标签: c audio ffmpeg

我第一次使用音频文件在c编程。我发现这个代码应该读取一个音频文件,然后写一个包含几个信息的csv文件,以便分析音频波,以防万一将是一个简单的声音:我对波的振幅,音色感兴趣声音及其高度和延伸。

           main () {   
           // Create a 20 ms audio buffer (assuming Fs = 44.1 kHz)
           int16_t buf[N] = {0}; // buffer
           int n;                // buffer index

          // Open WAV file with FFmpeg and read raw samples via the pipe.
          FILE *pipein;
          pipein = popen("ffmpeg -i whistle.wav -f s16le -ac 1 -", "r");
          fread(buf, 2, N, pipein);
          pclose(pipein);

          // Print the sample values in the buffer to a CSV file
          FILE *csvfile;
          csvfile = fopen("samples.csv", "w");
          for (n=0 ; n<N ; ++n) fprintf(csvfile, "%d\n", buf[n]);
          fclose(csvfile);

       }

有人可以详细解释我如何阅读音频文件,以便从中提取我需要的信息?参考这段代码,有人可以解释一下第8行管道的含义

pipein = popen("ffmpeg -i whistle.wav -f s16le -ac 1 -", "r");

P.S。我已经知道如何读取音频文件的标题,其中包含许多有用的信息,但我也想分析整个音频文件,逐个样本。

1 个答案:

答案 0 :(得分:4)

我刚刚编译然后运行你的代码...输出文件samples.csv是一个带符号16位整数的垂直列,代表输入音频曲线的每个样本......如:YMMV

-20724
-19681
-18556
-17359
-16096
-14766
-13383
-11940
-10460
-8928
-7371
-5778
-4165
-2536
-897
749
2385
4019
5633
7224
8793
10318
11811
13251
14644
15977
17247

...所以虽然原始音频在变量buf中,但您可以添加上面的代码来回答您的问题

音量 - 音频是一条曲线,所以当曲线无法摆动它的静音时......在计算音量时理解位深的意义至关重要...我建议你打开输出文件一个文本编辑器,用于注视每个值...知道你有16位的深度值告诉你可能的整数值的数量......在空白的凝视read up on PCM raw audio ...到第一个近似值下面的变化你的代码会告诉你音量

int min_value = 9999;
int max_value = -9999;

for (n=0 ; n < N ; ++n) {

    if (buf[n] < min_value)  min_value = buf[n];
    if (buf[n] > max_value)  max_value = buf[n];

    fprintf(csvfile, "%d\n", buf[n]);
}

fclose(csvfile);

printf("min_value %d\n", min_value);
printf("max_value %d\n", max_value);

知道你的音频的位深度,让我们说它的16位,然后你有2 ^ 16个可能的不同整数...从0到(65536 - 1)表示原始音频的曲线...如果你的数据是无符号的...如果它的有符号整数(在WAV文件头中定义)然后移动该范围使其零居中...那么范围将从-32768变为(+32768-1)或 - 32768到+32767 ...所以如果您的音频buf[n]值从最小值到最大值遍历整个可能的范围,那么您的音频样本范围可以说是全音量...现在我们处于一个位置解释上述测量:min_value和max_value ...如果min_value在-16384附近,如果max_value在+16384左右,那么音量大约是最大值的一半,因为它只消耗了可能整数值范围的一半

因此可以使用此公式计算(通过过度简化)0到1(最小到最大体积)范围内的体积

num_possible_ints = 2^bit_depth  // == 65536 for bit depth of 16 bits 
volume = 1 - ( num_possible_ints - ( max_value - min_value )) / num_possible_ints

为什么这会过于简单化?因为没有预处理你的音频缓冲区[通过丢弃极少刺激到最大或最小的外围音频样本,如果需要]这种方法很容易提供过高的音量测量

有更好的音量测量值,但请记住它容易产生感知偏差...... lookup Root Mean Square to calculate volume with better accuracy ... to quote :

  

RMS平均信号所取代的区域,即波形与线性零线之间的区域(不是0dB,而是轴)。

     

当波形在中心线上方(+)和下方( - )摆动时,必须忽略摆动的极性。幸运的是,在数学中,任何乘以其自身(平方)的东西都会变成正数。然后可以对信号进行平均(在时间线/窗口ED提及的算术平均值或其积分时间),因为正和负半部现在相互抵消 - 并且最终执行平方反转 - 平方根。

     

RMS只表示均方根或信号平方算术平均值的平方根。

     

实际上,这意味着高振幅,spikey,瞬态内容的信号可以具有与较低振幅但较胖的波形相同的RMS值 - 因为它们都具有相同的能量含量。如果你把它们放在扬声器中,它们都应该产生相同的声能输出。

     

典型的spikey波形就像鼓瞬态,而较胖的波形可能是正弦波甚至是方波(尽可能胖),其中需要更低的峰值才能获得相同的功率(正弦波) 1.4Vp具有与1.0Vp的方波相同的RMS水平。

......这应该让你开始

PS popen is doing a stream read from the input file