openFrameworksとArduinoで音量メーター

 前回、ようやくArduinoを繋ぐ事ができたので、LEDを光らせて何か作ってみようと思います。せっかくopenFrameworksからコントロールしているのでPC側の機能を使った物ということで、マイクで拾った音量をLEDで表示してみます。

■サンプルの内容
 まず、firmataExampleを見てLEDのon/offの方法を調べます。

□ testApp.h
 ofArduino というのがArduinoを管理してくれるクラスですね。

□testApp.cpp - setup
 ard.connectで接続開始しています。前回ハマったのはこのドライバ名(?)でした。

□testApp.cpp - update
 接続チェックかな。

□testApp.cpp - setupArduino
 ピンのモード設定。ARD_OUTPUT=デジタル出力用、ARD_ANALOG=アナログ入力用、ARD_PWM=PWM出力用。PWMというのは、デジタル出力を細かくOn/Offする事で階調を表現する事。たとえば、LEDを1秒間に0.1秒点灯、0.1秒消灯を5回繰り返せば、常につけている場合と比べて、半分の明るさになる。

□testApp.cpp - updateArduino
 Arduinoオブジェクトをアップデートしています。ard.sendPwm()で、Pin11に50%〜100%の明るさになるようにPWMを送っています。

□testApp.cpp - draw
 ard.getAnalog(0)で、pin0(半固定抵抗)のアナログ入力の値を取得しています。


 という事で、以下の命令でコントロールする事ができます。簡単!便利!
     : 送る : 受け取る
 デジタル:sendDigital:getDigital
 アナログ:sendPwm:getAnalog
(sendPwmはアナログを出力するわけではありません)




■音量を扱ったサンプル
 LEDのコントロールが分かったところで、今度は音量を取得する方法を探します。examplesにaudioInputExampleというのがあるので、開いてみます。PCのマイクの音を周波数別に表示しているみたいです。

□ testApp.h
 float * left、float * right、左右の音量が格納されます。周波数ごとの配列として使われます。

□testApp.cpp - setup
 ofSoundStreamSetup(0,2,this, 44100, 256, 4);
 left = new float[256];
 right = new float[256];
 音の入出力のセットアップですね。周波数を256段階に分けて取り込みます。

□testApp.cpp - draw
 left[]とright[]に入っている値を使って、波形を描画しています。

□testApp.cpp - audioReceived
 引数として渡されるinputに左右の値が交互に入っているみたいですね。それを分けて、left,rightに入れています。


 音量を直接取り出す命令が分からなかったのですが、left,rightに入っている全ての値を合算すれば、全体の音量になるはず。多分。



■組み合わせる
 以上でそれぞれ必要な準備と使い方が分かったので、新しいプロジェクトを作って、各要素をコピーしてきます。

testApp.h

#ifndef _TEST_APP
#define _TEST_APP


#include "ofMain.h"

class testApp : public ofBaseApp{

public:
void setup();
void update();
void draw();

void keyPressed (int key);
void keyReleased(int key);
void mouseMoved(int x, int y );
void mouseDragged(int x, int y, int button);
void mousePressed(int x, int y, int button);
void mouseReleased(int x, int y, int button);
void windowResized(int w, int h);

void setupArduino();
void updateArduino();

// Arduino
ofArduino ard;
bool bSetupArduino; // flag variable for setting up arduino once

// Sound
void audioReceived (float * input, int bufferSize, int nChannels);
float * left;
float * right;
};

#endif


testApp.cpp

#include "testApp.h"

//--------------------------------------------------------------
void testApp::setup(){
ofSetVerticalSync(true);
ofSetFrameRate(60);
ofBackground(255,255,255);

// Arduino setup
ard.connect("/dev/tty.usbserial-A7005OBP", 57600);
bSetupArduino = false;

// Sound setup
ofSoundStreamSetup(0,2,this, 44100, 256, 4);
left = new float[256];
right = new float[256];
}

//--------------------------------------------------------------
void testApp::setupArduino(){
// 全てのPinをデジタル出力モードに設定
for (int i = 0; i < 13; i++){
ard.sendDigitalPinMode(i, ARD_OUTPUT);
}
}

//--------------------------------------------------------------
void testApp::update(){

if ( ard.isArduinoReady()){

// 1st: setup the arduino if haven't already:
if (bSetupArduino == false){
setupArduino();
bSetupArduino = true; // only do this once
}
// 2nd do the update of the arduino
updateArduino();
}
}

//--------------------------------------------------------------
void testApp::updateArduino(){
ard.update();
}

//--------------------------------------------------------------
void testApp::draw(){
// draw the left:
ofSetColor(0x333333);
ofRect(0, 0, ofGetWidth(), ofGetHeight() );
ofSetColor(0xFFFFFF);

for (int i = 0; i < 256; i++){
ofSetLineWidth(4);
ofLine(i*4, ofGetHeight()/2, i*4, ofGetHeight()/2+left[i]*100.0f);
}

if (!ard.isArduinoReady()){
cout << "arduino not read" << endl;
} else {
float volume = 0;
for (int i = 0; i < 256; i++){
volume += left[i];
}

volume *= 100;

for (int j = 1; j<6; j++) {
if (volume > j * 30) {
ard.sendDigital(j+1, 1);
}else {
ard.sendDigital(j+1, 0);
}
}
}
}

//--------------------------------------------------------------
void testApp::audioReceived (float * input, int bufferSize, int nChannels){
for (int i = 0; i < bufferSize; i++){
left[i] = input[i*2];
right[i] = input[i*2+1];
}
}


■Arduino側の配線
 テストでLEDを1つ点けましたが、ほぼ一緒です。2〜6Pinの5個になっただけです。0と1Pinは書き込みのために使われているので空けています。(ん?今回は書き込みしないから使ってもいいのかな・・?)




■動画

Comments