我写了一个代码,据说应该读取一个音频文件作为输入,以便编写包含每个样本的csv文件。这是代码:
FILE *pipein;
pipein = popen("ffmpeg -i test1.wav -f s16le -ac 1 -", "r");
fread(buf, 2, sample_number, pipein);
pclose(pipein);
// Print the sample values in the buffer to a CSV file
FILE *csvfile;
csvfile = fopen("samples.csv", "w");
while (n<=sample_number) {
//if (buf[n]!=0) {
fprintf(csvfile, "%d %f\n", buf[cont], Sam_freq*cont);
cont++;
// }
n++;
}
fclose(csvfile);
这是运行代码后csv文件的样子:
10 43.150544
-36 43.150567
11 43.150590
30 43.150612
-29 43.150635
61 43.150658
13 43.150680
46 43.150703
121 43.150726
61 43.150748
144 43.150771
128 43.150794
130 43.150816
131 43.150839
我尝试使用gnuplot绘制samples.csv的数据,但我不明白在y轴上表示了哪个物理尺寸。
答案 0 :(得分:4)
的问题:
这不是CSV文件,只是一个文本文件。
您的代码看起来不像那样。它远非可编辑,你犯了错误,将“相关部分”复制到这个问题上。
特别是,您使用n
作为循环变量,但cont
访问缓冲区。如果您的代码实际上是这样,那么您只会在输出中看到一对重复的值。
您没有定义采样率。
考虑以下反例:
#include <stdlib.h>
#include <stdint.h>
#include <limits.h>
#include <string.h>
#include <endian.h>
#include <stdio.h>
#ifndef SAMPLE_RATE
#define SAMPLE_RATE 48000
#endif
#define NO_SAMPLE INT_MIN
#if (__BYTE_ORDER-0 == __BIG_ENDIAN-0)
/* Use big-endian samples */
#define SAMPLE_FORMAT "s16be"
static inline int read_sample(FILE *source)
{
int16_t sample;
if (fread(&sample, sizeof sample, 1, source) == 1)
return (int)sample;
else
return NO_SAMPLE;
}
#elif (__BYTE_ORDER-0 == __LITTLE_ENDIAN-0) || (__BYTE_ORDER-0 == __PDP_ENDIAN-0)
/* Use little-endian samples */
#define SAMPLE_FORMAT "s16le"
static inline int read_sample(FILE *source)
{
int16_t sample;
if (fread(&sample, sizeof sample, 1, source) == 1)
return (int)sample;
else
return NO_SAMPLE;
}
#else
/* Use little-endian (two's complement) samples, but
read them byte-by-byte. */
#define SAMPLE_FORMAT "s16le"
static inline int16_t read_sample(FILE *source)
{
unsigned char bytes[2];
int sample;
if (fread(bytes, 2, 1, source) != 2)
return NO_SAMPLE;
sample = bytes[0] + 256*bytes[1];
if (sample > 32767)
return sample - 65536;
else
return sample;
}
#endif
int main(void)
{
const double sample_rate = SAMPLE_RATE;
FILE *in;
unsigned long i;
int sample;
in = popen("ffmpeg -i test1.wav -v -8 -nostats -f " SAMPLE_FORMAT " -ac 1 -", "r");
if (!in)
return EXIT_FAILURE;
i = 0u;
while ((sample = read_sample(in)) != NO_SAMPLE) {
printf("%.6f %9.6f\n", (double)i / sample_rate, (double)sample / 32768.0);
i++;
}
pclose(in);
return EXIT_SUCCESS;
}
假设采样率为每秒48,000个样本(您可以先使用ffmpeg
查找采样率),然后打印出每个样本,每行一个样本,第一列中的时间,以及第二列中的样本值(-1.0到恰好低于+1.0)。
在物理意义上,第一列反映了样本的时间维度,第二列反映了传感器当时的相对压力变化 - 但是,压力变化的符号或线性都不是真正已知的当然,这取决于所使用的麦克风,放大器和ADC。
假设您编译并运行上述内容,将输出重定向到test1.out
:
gcc -Wall -O2 example.c -o example
./example > test1.out
您可以轻松地在Gnuplot中绘制它。开始gnuplot
,并告诉它
set xlabel "Time [seconds]"
set ylabel "Relative pressure change [f((P-P0)/Pmax)]"
plot "test1.out" u 1:2 notitle w lines
对于垂直轴,P
是水平轴上指示的压力,P0
是环境压力,Pmax
是麦克风可以检测到的最大压力变化, f()
与使用的麦克风,麦克风放大器和模数转换器电路的非线性相反。 (f()
和Pmax
都可能取决于环境压力P0
。)