2017-08-09 13 views
0

すべてのサンプルを含むcsvファイルを書き込むために、オーディオファイルを入力として読み込むコードを書いています。これはコードです:gnuplot - 軸上の物理的次元

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軸上に表されるかを示す。

waveform plot 私はy軸上の値がマイクの膜の変形を表していると読んでいます。これらの値から必要な物理的な次元を抽出するために誰かが数学的関係を知っていますか?

+1

[PCMオーディオの振幅値?](https://stackoverflow.com/questions/5890499/pcm-audio-amplitude-values)の複製があります。 – user8153

答えて

4

問題:

  1. CSVファイルではありません、それは単なるテキストファイルです。

  2. あなたのコードはそうではありません。コンパイル可能ではありません。あなたはこの問題に「関連する部分」を間違えてコピーしました。

    特に、ループ変数としてnを使用しましたが、バッファへのアクセスにはcontを使用しました。あなたのコードが実際にそれだったら、出力に重複した値のペアが1つしか見えません。

  3. サンプルレートは定義しません。

は、次の反例を考えてみましょう:

#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; 
} 

それは、それぞれのサンプルを出力し、その後、(あなたが最初のサンプル・レートを見つけるためにffmpegを使用することができます)サンプルレートは毎秒48,000サンプルであると仮定し、1行目に1サンプル、第1列に時間、第2列にサンプル値(-1.0〜直下+1.0)が表示されます。

物理的意味では、最初の列はサンプルの時間次元を反映し、2番目の列はセンサのその瞬間の相対的な圧力変化を反映しますが、圧力変化の符号や直線性は実際にはそれは正確なマイク、増幅、および使用される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にも依存します。)

+0

好奇心が強いのは、#define NO_SAMPLEの '-65536' -65536' vsおそらく '#define NO_SAMPLE INT_MIN'? – chux

+1

@chux:理由はありません。良い提案。適用される。ありがとう! –

関連する問題