gnuplot - 轴上的物理尺寸

Posted

技术标签:

【中文标题】gnuplot - 轴上的物理尺寸【英文标题】:gnuplot - physical dimension on axis 【发布时间】:2017-08-09 15:46:33 【问题描述】:

我编写了一个代码,它应该读取一个音频文件作为输入,以便编写一个包含每个样本的 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 轴上表示的是哪个物理维度。

我在其他帖子上读到,y 轴上的值代表麦克风中膜的变形。有谁知道数学关系以便从这些值中提取我需要的物理尺寸?

【问题讨论】:

PCM audio amplitude values?的可能重复 【参考方案1】:

问题:

    那不是 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。)

【讨论】:

好奇#define NO_SAMPLE -65536 中的-65536#define NO_SAMPLE INT_MIN 的任何特殊原因? @chux:没有理由。好建议;应用。谢谢!

以上是关于gnuplot - 轴上的物理尺寸的主要内容,如果未能解决你的问题,请参考以下文章

如何让 Gnuplot 不裁剪科学记数法

gnuplot 学习笔记

Raspberry Pi 上的 Gnuplot,绘图到 X11 终端,我怎样才能重用同一个 X 窗口?

使用 gnuplot 绘制获得的权力

sh:gnuplot:在 Gnuplot + Xcode 中找不到命令

在不使用十六进制代码的情况下在 gnuplot 中设置线条不透明度