LoginSignup
3
5

More than 5 years have passed since last update.

oF のアドオン ofxFft が正常に動かなかった話

Posted at

使用環境

背景

最近触り始めた openFrameworks で、音を視覚化するアプリを作ってみようと思い立った。折角なので、周波数空間(フーリエ空間)を表現してみたい。でも、ぶっちゃけ FFT を自力で組むのが面倒...。
で、ググってみたら、案の定作っている先人がいらっしゃった(kylemcdonald/ofxFFT)。どうやら oF で簡単かつ基本的な周波数解析(FFT)が計算できるアドオンらしい。特に細かいカスタマイズする気もなかったから、今回はありがたく拝借することに。

だが、実際動かしてみたらおかしなことが。なぜか、特定の処理を draw() で実行しないと正常な値が得られない様子。
最終的には”初歩的なミス”というオチだったが、原因の特定やら対処やらで手こずったので、備忘録を残しておく。

注意:
本稿は、アドオンの詳細についての説明を省略しております。あらかじめご了承ください。
使い方自体は GitHub に記載されておりますので、そちらをご参照ください。

症状

今回行った処理は下記の通り。マイク入力に対して FFT を行い、値を標準出力する。
なおfft.drawDebug()は、計測した値を画面にビットマップ出力する。fft.drawBars()は、計測した値をグラフで描画する。

ofApp.h
#include "ofxProcessFFT.h"

class ofApp : public ofBaseApp{

    public:
        ...
        ProcessFFT fft;
};
ofApp.cpp
#include "ofApp.h"

void ofApp::setup() {
    ...

    // FFT setting
    fft.setup();
    fft.setNumFFTBins(16);
    fft.setNormalize(true);

    ...
}

void ofApp::update() {
    fft.update();

    // Output values
    float lowVal = fft.getLowValue();
    float midVal = fft.getMidValue();
    float highVal = fft.getHighValue();

    std::cout << "ofApp : " << "Low value : " << lowVal << endl;
    std::cout << "ofApp : " << "Middle value : " << midVal << endl;
    std::cout << "ofApp : " << "High value : " << highVal << endl;
}

void ofApp::draw() {
    fft.drawDebug();
    fft.drawBars();
}

主な症状は下記の通り。

  • 上記のプログラムでは、正常な計測値が得られる。
  • fft.drawDebug()をコメントアウトすると、急に正常な値が得られなくなる。
  • fft.drawDebug()の内部でも各行をコメントアウトしてみたが、特定の処理が影響している様子ではない(むしろ、"処理の数"が影響しているような...?)
  • ProcessFFTの内部パラメータを全て観察してみたところ、パラメータの1つであるavgMaxSoundOverTimeの値が増加し続けてしまうことに原因があるっぽい(正常時には増え続けていなかった)。
  • さらに細かくみると、avgMaxSoundOverTimeを求めるときに使う値accumMaxSoundsが増え続けていることが根本的な原因である様子。

原因

下記のように、ofxProcessFFT.cppaccumMaxSoundsが初期化されていなかった。

ofxProcess.cpp
...

void ofxProcessFFT::calculateFFT( ... ) {
    ...

    float accumMaxSounds;  /* It is not initialized! */
    for (int i = 0; i < graphMaxSound.size(); i++) {
        accumMaxSounds = accumMaxSounds+graphMaxSound[i]; // ...
    }

    avgMaxSoundOverTime = accumMaxSounds/graphMaxSound.size(); // ...

    ...
}

対処

accumMaxSoundsを初期化してやれば良い。

ofxProcessFFT.cpp
...

void ofxProcessFFT::calculateFFT( ... ) {
    ...

-   float accumMaxSounds;  /* It is not initialized! */
+   float accumMaxSounds = 0;
    for (int i = 0; i < graphMaxSound.size(); i++) {
        accumMaxSounds = accumMaxSounds+graphMaxSound[i]; // ...
    }

    avgMaxSoundOverTime = accumMaxSounds/graphMaxSound.size(); // ...

    ...
}

まとめ

うーん、しょーもない(失礼)。
ただ、結果的に見ると単純な話、初歩的なミスで良かった。おそらく「処理の数が影響してる様子」だったのも、変数のアドレスが関係していたと思われる(偶然ゼロになっていた、またはその逆)。
今回の件を GitHub で直接 issue に出そうかは検討中。

この手のエラーは意外と忘れがちかも...。

Reference

None

3
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
5