2014年1月10日金曜日

ArduinoでFFT : 音声を入力してみた

ほぼ昨日のソースと同様、違うのは主に関数でデータを取り込む代わりに

data[i] = (analogRead(mic) >> 2) - 128;
としているところ。

マイクは秋月の「高感度マイクアンプキット 500円」。まずこれを組み立てたのですが…ハンダがランドに乗ってくれなくてまたしても苦戦。「こんだけ熱が回っちゃうとマイク壊れているかもしれないなぁ…」と思いつつ、オシロにつないでみると一応声を拾っている。良かった良かった。


FFTは昨日も使った8bit fft。で、結果なのですが…ピークtoピークのアナログ波形でも出力は0-50程度、どうも今ひとつダイナミックレンジが狭い感じ。また、人間の声についてはそれなりに拾っていますが、ビープ音についてはレンジを越えてしまう様子。128点のサンプリングに約15mSかかっているので約8500回/秒、その半分として4.2Khzは拾っているはずなのですが。うーん。

さて、今回は芸無くSerialへの出力でしたが、次回は何かもっと見やすく表示してみます。
#include <fix_fft.h>
#include <Time.h>
#define N_SAMPLES 128
char im[N_SAMPLES];      // 虚数部
char data[N_SAMPLES];    // 入力/実数部
char buf[20];            // 文字出力バッファ
int mic = 0;      // マイク接続ポート
int cnt = 0;      // ループカウンタ
int prevSec = 0;  // 秒カウント

void setup() {
  Serial.begin(115200);
  analogReference(DEFAULT);
 
  prevSec = -1;
}

void loop(){
  int  i;
  unsigned long mil;
 
  cnt ++;
 
  mil = millis();
  for (i = 0; i < N_SAMPLES; i++) {
    // 音声を読み込み
    data[i] = (analogRead(mic) >> 2) - 128;
   
    // 虚数部をクリア
    im[i]   = 0;
  }
  // 128個の読み込み時間を計測
  mil = millis() - mil;
  // FFT
  fix_fft(data, im, 7, 0);  // full scale 2^7=128, FFT mode
  for (i = 0; i < N_SAMPLES / 2; i++) {
    data[i] = sqrt(data[i] * data[i] + im[i] * im[i]);
  }
 
  // 1秒ごとのループ回数と128個の読み込み時間(mSec)を表示
  int s = second();
  if (prevSec != s) {
    prevSec = s;
    data[0] = cnt;  // 0をcnt出力に流用
    data[1] = mil;  // 1をmil出力に流用
    dispData("Results : ", data, N_SAMPLES / 2);  //  結果出力
    Serial.println("");
   
    cnt = 0;  //  カウンタをクリア
  }
}

void dispData(char *inMsg, char *inData, int inN) {
  Serial.print(inMsg);
  for (int i = 0; i < inN; i++) {
    sprintf(buf, "%5d", inData[i]);
    Serial.print(buf);
  }
}

0 件のコメント:

コメントを投稿