openframeworks、サウンド機能・音響合成、ofxmaxim, ofxosc, ofxpd, ofxsupercollider

81
Media Art II 2011 第7回:openFrameworks サウンド、音響合成 ofxMaxim, ofxOsc, ofxSuperCollider, ofxPd 2011年11月15日 多摩美術大学 情報デザイン学科 情報芸術コース 田所 淳

Upload: atsushi-tadokoro

Post on 24-Jan-2015

7.482 views

Category:

Technology


0 download

DESCRIPTION

 

TRANSCRIPT

Page 1: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

Media Art II 2011 第7回:openFrameworksサウンド、音響合成ofxMaxim, ofxOsc, ofxSuperCollider, ofxPd

2011年11月15日多摩美術大学 情報デザイン学科 情報芸術コース田所 淳

Page 2: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

今日の内容‣ openFrameworks音に関する機能いろいろ

‣ openFrameworksの標準機能‣ サウンドファイルの再生 (ofSoundPlayer)‣ サウンド入出力 (audioIn(), audioOut())

‣ 音響合成のためのAddonを利用 (ofxMaxim)

‣ 外部プログラムとの連携‣ OSCとは?‣ Pdとの連携 (ofxPd)‣ SuperColliderとの連携 (ofxSuperCollider)

Page 3: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

サウンドファイルの再生ofSoundPlayer

Page 4: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

サウンドファイルの再生 - ofSoundPlayer‣ ofSoundPlayer‣ サウンドファイルをよみこんで、再生する‣ おそらく、一番楽なサウンドを鳴らすための方法

‣ 画像ファイルの読込と同様、ファイルはプロジェクトのdataフォルダに格納する

‣ 《projectのフォルダ》/bin/data/

Page 5: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

サウンドファイルの再生 - ofSoundPlayer‣ ofSoundPlayer‣ サウンドファイルをよみこんで、再生する‣ おそらく、一番楽なサウンドを鳴らすための方法

‣ 様々な機能を内蔵‣ ボリュームの設定‣ 左右の定位(pan)‣ 周波数解析(FFT) ...etc.

‣ 音声ファイルはプロジェクトのdataフォルダに格納する‣ 《projectのフォルダ》/bin/data/

Page 6: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

サウンドファイルの再生 - ofSoundPlayer‣ サウンドファイルを読み込んで再生するサンプル

‣ 再生されたサンプルをリアルタイムにFFT解析し、視覚化‣ 画面の中心から両端に向かって、周波数帯域ごとのパワーの値で円を描いてみる

Page 7: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

サウンドファイルの再生 - ofSoundPlayer‣ testApp.h#pragma once#include "ofMain.h"

class testApp : public ofBaseApp{ public: void setup(); void update(); void draw(); ofSoundPlayer mySound;

float * fft;

int nBandsToGet;};

Page 8: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

サウンドファイルの再生 - ofSoundPlayer‣ testApp.h#pragma once#include "ofMain.h"

class testApp : public ofBaseApp{ public: void setup(); void update(); void draw(); ofSoundPlayer mySound;

float * fft;

int nBandsToGet;};

※サウンドプレーヤー

※FFT解析結果を格納する配列(ポインタ)

※FFT解析の分解精度(2の累乗)

Page 9: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

サウンドファイルの再生 - ofSoundPlayer‣ testApp.cpp - 1 of 2‣#include "testApp.h"void testApp::setup(){! ofSetFrameRate(60); ofSetVerticalSync(true); ofSetCircleResolution(32); ofEnableBlendMode(OF_BLENDMODE_ADD); ofBackground(0, 0, 0); nBandsToGet = 1024; mySound.loadSound("sounds/drumLoop.aif"); mySound.setLoop(true); mySound.play();}

void testApp::update(){ ofSoundUpdate(); fft = ofSoundGetSpectrum(nBandsToGet);}

Page 10: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

サウンドファイルの再生 - ofSoundPlayer‣ testApp.cpp - 1 of 2‣#include "testApp.h"void testApp::setup(){! ofSetFrameRate(60); ofSetVerticalSync(true); ofSetCircleResolution(32); ofEnableBlendMode(OF_BLENDMODE_ADD); ofBackground(0, 0, 0); nBandsToGet = 1024; mySound.loadSound("sounds/drumLoop.aif"); mySound.setLoop(true); mySound.play();}

void testApp::update(){ ofSoundUpdate(); fft = ofSoundGetSpectrum(nBandsToGet);}

※画面初期設定

Page 11: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

サウンドファイルの再生 - ofSoundPlayer‣ testApp.cpp - 1 of 2‣#include "testApp.h"void testApp::setup(){! ofSetFrameRate(60); ofSetVerticalSync(true); ofSetCircleResolution(32); ofEnableBlendMode(OF_BLENDMODE_ADD); ofBackground(0, 0, 0); nBandsToGet = 1024; mySound.loadSound("sounds/drumLoop.aif"); mySound.setLoop(true); mySound.play();}

void testApp::update(){ ofSoundUpdate(); fft = ofSoundGetSpectrum(nBandsToGet);}

※FFTの周波数成分の解像度を設定 (2の累乗)

Page 12: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

サウンドファイルの再生 - ofSoundPlayer‣ testApp.cpp - 1 of 2‣#include "testApp.h"void testApp::setup(){! ofSetFrameRate(60); ofSetVerticalSync(true); ofSetCircleResolution(32); ofEnableBlendMode(OF_BLENDMODE_ADD); ofBackground(0, 0, 0); nBandsToGet = 1024; mySound.loadSound("sounds/drumLoop.aif"); mySound.setLoop(true); mySound.play();}

void testApp::update(){ ofSoundUpdate(); fft = ofSoundGetSpectrum(nBandsToGet);}

※サウンドファイルを読み込んでループ再生

Page 13: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

サウンドファイルの再生 - ofSoundPlayer‣ testApp.cpp - 1 of 2‣#include "testApp.h"void testApp::setup(){! ofSetFrameRate(60); ofSetVerticalSync(true); ofSetCircleResolution(32); ofEnableBlendMode(OF_BLENDMODE_ADD); ofBackground(0, 0, 0); nBandsToGet = 1024; mySound.loadSound("sounds/drumLoop.aif"); mySound.setLoop(true); mySound.play();}

void testApp::update(){ ofSoundUpdate(); fft = ofSoundGetSpectrum(nBandsToGet);}

※サウンドプレーヤーを更新して、FFT解析

Page 14: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

サウンドファイルの再生 - ofSoundPlayer‣ testApp.cpp - 2 of 2void testApp::draw(){ float width = float(ofGetWidth()) / float(nBandsToGet) / 2.0f;

for (int i = 0;i < nBandsToGet; i++){ int b = float(255) / float(nBandsToGet) * i; int g = 31; int r = 255 - b; ofSetColor(r, g, b);

ofCircle(ofGetWidth()/2 + width * i, ofGetHeight()/2, fft[i] * 800);

ofCircle(ofGetWidth()/2 - width * i, ofGetHeight()/2, fft[i] * 800); }}

Page 15: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

サウンドファイルの再生 - ofSoundPlayer‣ testApp.cpp - 2 of 2void testApp::draw(){ float width = float(ofGetWidth()) / float(nBandsToGet) / 2.0f;

for (int i = 0;i < nBandsToGet; i++){ int b = float(255) / float(nBandsToGet) * i; int g = 31; int r = 255 - b; ofSetColor(r, g, b);

ofCircle(ofGetWidth()/2 + width * i, ofGetHeight()/2, fft[i] * 800);

ofCircle(ofGetWidth()/2 - width * i, ofGetHeight()/2, fft[i] * 800); }}

※円の配置間隔を計算

Page 16: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

サウンドファイルの再生 - ofSoundPlayer‣ testApp.cpp - 2 of 2void testApp::draw(){ float width = float(ofGetWidth()) / float(nBandsToGet) / 2.0f;

for (int i = 0;i < nBandsToGet; i++){ int b = float(255) / float(nBandsToGet) * i; int g = 31; int r = 255 - b; ofSetColor(r, g, b);

ofCircle(ofGetWidth()/2 + width * i, ofGetHeight()/2, fft[i] * 800);

ofCircle(ofGetWidth()/2 - width * i, ofGetHeight()/2, fft[i] * 800); }}

※色のグラデーションを生成

Page 17: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

サウンドファイルの再生 - ofSoundPlayer‣ testApp.cpp - 2 of 2void testApp::draw(){ float width = float(ofGetWidth()) / float(nBandsToGet) / 2.0f;

for (int i = 0;i < nBandsToGet; i++){ int b = float(255) / float(nBandsToGet) * i; int g = 31; int r = 255 - b; ofSetColor(r, g, b);

ofCircle(ofGetWidth()/2 + width * i, ofGetHeight()/2, fft[i] * 800);

ofCircle(ofGetWidth()/2 - width * i, ofGetHeight()/2, fft[i] * 800); }}

※円の描画

Page 18: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

サウンドファイルの再生 - ofSoundPlayer‣ 実行結果:サウンドのループ再生と、FFT解析

Page 19: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

サウンド入出力audioIn(), audioOut()

Page 20: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

サウンド入出力‣ openFrameworksには、サウンド入出力のためのイベントが用意されている

‣ サウンド入力‣ void audioIn(float * input, int bufferSize, int nChannels);

‣ サウンド出力‣ void audioOut(float * input, int bufferSize, int nChannels);

‣ input - 入出力される信号のデータ‣ bufferSize - バッファサイズ‣ nChannels - チャンネル数

Page 21: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

サウンド入出力‣ Exampleにあるサンプルプログラムを参考にしてみる

‣ サウンド入力‣ apps/examples/audioInputExample

‣ サウンド出力‣ apps/examples/audioOutputExample

Page 22: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

サウンド入力 - audioInputExample‣ testApp.h#ifndef _TEST_APP#define _TEST_APP#include "ofMain.h"

class testApp : public ofBaseApp{public: void setup(); void update(); void draw(); 《中略》 void audioIn(float * input, int bufferSize, int nChannels); ! vector <float> left; vector <float> right; vector <float> volHistory;

《後略》

Page 23: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

サウンド入力 - audioInputExample‣ testApp.h#ifndef _TEST_APP#define _TEST_APP#include "ofMain.h"

class testApp : public ofBaseApp{public: void setup(); void update(); void draw(); 《中略》 void audioIn(float * input, int bufferSize, int nChannels); ! vector <float> left; vector <float> right; vector <float> volHistory;

《後略》

※サウンド入力のためのイベント

Page 24: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

サウンド入力 - audioInputExample‣ testApp.cpp audioIn()関数void testApp::audioIn(float * input, int bufferSize, int nChannels){!! float curVol = 0.0;! int numCounted = 0;!

! for (int i = 0; i < bufferSize; i++){! ! left[i]!! = input[i*2]*0.5;! ! right[i]! = input[i*2+1]*0.5;! ! curVol += left[i] * left[i];! ! curVol += right[i] * right[i];! ! numCounted+=2;! }

! curVol /= (float)numCounted;! curVol = sqrt( curVol );!! smoothedVol *= 0.93;! smoothedVol += 0.07 * curVol;! bufferCounter++;!}

Page 25: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

サウンド入力 - audioInputExample‣ testApp.cpp audioIn()関数void testApp::audioIn(float * input, int bufferSize, int nChannels){!! float curVol = 0.0;! int numCounted = 0;!

! for (int i = 0; i < bufferSize; i++){! ! left[i]!! = input[i*2]*0.5;! ! right[i]! = input[i*2+1]*0.5;! ! curVol += left[i] * left[i];! ! curVol += right[i] * right[i];! ! numCounted+=2;! }

! curVol /= (float)numCounted;! curVol = sqrt( curVol );!! smoothedVol *= 0.93;! smoothedVol += 0.07 * curVol;! bufferCounter++;!}

左右の入力の波形を取得取得した波形から音量を算出音量の表示の変化をスムーズに加工

Page 26: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

サウンド入力 - audioInputExample‣ 実行結果:波形と音量の平均が表示される

Page 27: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

サウンド出力 - audioOutputExample‣ testApp.h#ifndef _TEST_APP#define _TEST_APP#include "ofMain.h"

class testApp : public ofBaseApp{public: void setup(); void update(); void draw();

《中略》 void audioOut(float * input, int bufferSize, int nChannels); ofSoundStream soundStream; float ! pan; int! ! sampleRate; bool ! bNoise; float ! volume; vector <float> lAudio; vector <float> rAudio;};

#endif

Page 28: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

サウンド出力 - audioOutputExample‣ testApp.h#ifndef _TEST_APP#define _TEST_APP#include "ofMain.h"

class testApp : public ofBaseApp{public: void setup(); void update(); void draw();

《中略》 void audioOut(float * input, int bufferSize, int nChannels); ofSoundStream soundStream; float ! pan; int! ! sampleRate; bool ! bNoise; float ! volume; vector <float> lAudio; vector <float> rAudio;};

#endif

※サウンド出力のためのイベント

Page 29: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

サウンド出力 - audioOutputExample‣ testApp.cpp audioOutイベントvoid testApp::audioOut(float * output, int bufferSize, int nChannels){ float leftScale = 1 - pan; float rightScale = pan;

while (phase > TWO_PI){ phase -= TWO_PI; } if ( bNoise == true){ for (int i = 0; i < bufferSize; i++){ lAudio[i] = output[i*nChannels ] = ofRandom(0, 1) * volume * leftScale; rAudio[i] = output[i*nChannels + 1] = ofRandom(0, 1) * volume * rightScale; } } else { phaseAdder = 0.95f * phaseAdder + 0.05f * phaseAdderTarget; for (int i = 0; i < bufferSize; i++){ phase += phaseAdder; float sample = sin(phase); lAudio[i] = output[i*nChannels ] = sample * volume * leftScale; rAudio[i] = output[i*nChannels + 1] = sample * volume * rightScale; } }}

Page 30: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

サウンド出力 - audioOutputExample‣ testApp.cpp audioOutイベントvoid testApp::audioOut(float * output, int bufferSize, int nChannels){ float leftScale = 1 - pan; float rightScale = pan;

while (phase > TWO_PI){ phase -= TWO_PI; } if ( bNoise == true){ for (int i = 0; i < bufferSize; i++){ lAudio[i] = output[i*nChannels ] = ofRandom(0, 1) * volume * leftScale; rAudio[i] = output[i*nChannels + 1] = ofRandom(0, 1) * volume * rightScale; } } else { phaseAdder = 0.95f * phaseAdder + 0.05f * phaseAdderTarget; for (int i = 0; i < bufferSize; i++){ phase += phaseAdder; float sample = sin(phase); lAudio[i] = output[i*nChannels ] = sample * volume * leftScale; rAudio[i] = output[i*nChannels + 1] = sample * volume * rightScale; } }}

※左右の定位(パン)の設定

Page 31: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

サウンド出力 - audioOutputExample‣ testApp.cpp audioOutイベントvoid testApp::audioOut(float * output, int bufferSize, int nChannels){ float leftScale = 1 - pan; float rightScale = pan;

while (phase > TWO_PI){ phase -= TWO_PI; } if ( bNoise == true){ for (int i = 0; i < bufferSize; i++){ lAudio[i] = output[i*nChannels ] = ofRandom(0, 1) * volume * leftScale; rAudio[i] = output[i*nChannels + 1] = ofRandom(0, 1) * volume * rightScale; } } else { phaseAdder = 0.95f * phaseAdder + 0.05f * phaseAdderTarget; for (int i = 0; i < bufferSize; i++){ phase += phaseAdder; float sample = sin(phase); lAudio[i] = output[i*nChannels ] = sample * volume * leftScale; rAudio[i] = output[i*nChannels + 1] = sample * volume * rightScale; } }}

※sin波生成用のカウンタ(位相)をリセット

Page 32: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

サウンド出力 - audioOutputExample‣ testApp.cpp audioOutイベントvoid testApp::audioOut(float * output, int bufferSize, int nChannels){ float leftScale = 1 - pan; float rightScale = pan;

while (phase > TWO_PI){ phase -= TWO_PI; } if ( bNoise == true){ for (int i = 0; i < bufferSize; i++){ lAudio[i] = output[i*nChannels ] = ofRandom(0, 1) * volume * leftScale; rAudio[i] = output[i*nChannels + 1] = ofRandom(0, 1) * volume * rightScale; } } else { phaseAdder = 0.95f * phaseAdder + 0.05f * phaseAdderTarget; for (int i = 0; i < bufferSize; i++){ phase += phaseAdder; float sample = sin(phase); lAudio[i] = output[i*nChannels ] = sample * volume * leftScale; rAudio[i] = output[i*nChannels + 1] = sample * volume * rightScale; } }}

※ホワイトノイズの生成

Page 33: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

サウンド出力 - audioOutputExample‣ testApp.cpp audioOutイベントvoid testApp::audioOut(float * output, int bufferSize, int nChannels){ float leftScale = 1 - pan; float rightScale = pan;

while (phase > TWO_PI){ phase -= TWO_PI; } if ( bNoise == true){ for (int i = 0; i < bufferSize; i++){ lAudio[i] = output[i*nChannels ] = ofRandom(0, 1) * volume * leftScale; rAudio[i] = output[i*nChannels + 1] = ofRandom(0, 1) * volume * rightScale; } } else { phaseAdder = 0.95f * phaseAdder + 0.05f * phaseAdderTarget; for (int i = 0; i < bufferSize; i++){ phase += phaseAdder; float sample = sin(phase); lAudio[i] = output[i*nChannels ] = sample * volume * leftScale; rAudio[i] = output[i*nChannels + 1] = sample * volume * rightScale; } }}

※sin波の生成

Page 34: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

サウンド出力 - audioOutputExample‣ 実行結果:サウンド(sin波とホワイトノイズ)を出力

Page 35: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

サウンド入出力のプログラミング‣ testApp(ofBaseApp)に内蔵されているサウンド機能、audioIn() と audioOut() だけで高度な音響生成を行えるか?

‣ 技術的には不可能ではない‣ しかしながら、全てのデジタル信号処理(DSP)のプログラムを自前で用意しなければならない

‣ 専門的な知識が必要

‣ もう少し、お手軽な方法はないだろうか…?

Page 36: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

音響合成のためのAddonを利用ofxMaxim

Page 37: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

音響合成のためのAddon - ofxMaxim‣ ofxMaxim - C++で書かれた音響合成のためのライブラリ「Maxmilian」をopenFrameworksのAddonにしたもの

‣ Maxmilianページ(http://maximilian.strangeloop.co.uk/)

Page 38: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

音響合成のためのAddon - ofxMaxim‣ 自分で一から音響生成のコードを書くより、ずっと簡単

‣ 様々な波形のオシレータ‣ サンプリング、オーディオファイルの再生‣ エンベロープ (時間による音量変化)‣ フィルタ‣ FFT (高速フーリエ変換) による周波数解析 ... etc.

Page 39: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

ofxMaxim - ofxMaxiOscで波形を生成‣ ofxMaximに内蔵されているオシレータ‣ ofxMaxiOsc クラスを使用

オシレーター名称 説明

sinwave サイン波

saw のこぎり波

pulse 矩形波、パルス

triangle 三角波

noise ホワイトノイズ

Page 40: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

ofxMaxim - ofxMaxiOscで波形を生成‣ いろいろな波形の音響を生成するプログラムを作ってみる‣ ofxMaximを使用するために、addonsフォルダに追加する

Page 41: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

ofxMaxim - ofxMaxiOscで波形を生成‣ testApp.h#pragma once#include "ofMain.h"#include "ofxMaxim.h"

class testApp : public ofBaseApp{public: void setup(); void update(); void draw(); void keyPressed(int key); void audioOut(float * input, int bufferSize, int nChannels); void audioIn(float * input, int bufferSize, int nChannels);

int initialBufferSize; int sampleRate; int mode; double wave,sample,outputs[2];

ofxMaxiMix mymix; ofxMaxiOsc osc; vector <float> lAudio; vector <float> rAudio;};

Page 42: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

ofxMaxim - ofxMaxiOscで波形を生成‣ testApp.cpp - audioOut() 音を生成している部分void testApp::audioOut(float * output, int bufferSize, int nChannels){ for (int i = 0; i < bufferSize; i++){ float freq = mouseY; float pan = (float)mouseX / (float)ofGetWidth(); switch (mode) { case 0: wave = osc.sinewave(freq); break; case 1: wave = osc.saw(freq); break; case 2: wave = osc.pulse(freq, 0.99); break; case 3: wave = osc.phasor(freq); break; case 4: wave = osc.triangle(freq); break; case 5: wave = osc.noise(); break; default: wave = osc.sinewave(freq); break; }

モードに応じて、波形を変更

Page 43: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

ofxMaxim - ofxMaxiOscで波形を生成‣ testApp.cpp - audioOut() 音を生成している部分 mymix.stereo(wave, outputs, pan); lAudio[i] = output[i*nChannels ] = outputs[0]; rAudio[i] = output[i*nChannels + 1] = outputs[1]; }!}

生成された波形をミックス

サウンド再生波形表示用に値を確保している

Page 44: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

ofxMaxim - ofxMaxiOscで波形を生成‣ 実行結果 (キーボードで波形を変更)

Page 45: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

ofxMaximでFM合成‣ オシレータofxMaximOscをくみあわせた、音響合成も可能‣ 例えば、シンプルなFM合成を実装してみる

OSC(mod)

OSC(car)

freq amp

freq amp

+

Page 46: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

ofxMaximでFM合成‣ testApp.h#pragma once#include "ofMain.h"#include "ofxMaxim.h"

class testApp : public ofBaseApp{public: ~testApp(); void setup(); void update(); void draw(); void audioOut(float * input, int bufferSize, int nChannels); void audioIn(float * input, int bufferSize, int nChannels);! int initialBufferSize; int sampleRate; double outputs[2]; double wave;

ofxMaxiMix mymix; ofxMaxiOsc car; ofxMaxiOsc mod; vector <float> lAudio; vector <float> rAudio;};

Page 47: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

ofxMaximでFM合成‣ testApp.h#pragma once#include "ofMain.h"#include "ofxMaxim.h"

class testApp : public ofBaseApp{public: ~testApp(); void setup(); void update(); void draw(); void audioOut(float * input, int bufferSize, int nChannels); void audioIn(float * input, int bufferSize, int nChannels);! int initialBufferSize; int sampleRate; double outputs[2]; double wave;

ofxMaxiMix mymix; ofxMaxiOsc car; ofxMaxiOsc mod; vector <float> lAudio; vector <float> rAudio;};

バッファーサイズ、サンプリングレイト出力

Page 48: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

ofxMaximでFM合成‣ testApp.h#pragma once#include "ofMain.h"#include "ofxMaxim.h"

class testApp : public ofBaseApp{public: ~testApp(); void setup(); void update(); void draw(); void audioOut(float * input, int bufferSize, int nChannels); void audioIn(float * input, int bufferSize, int nChannels);! int initialBufferSize; int sampleRate; double outputs[2]; double wave;

ofxMaxiMix mymix; ofxMaxiOsc car; ofxMaxiOsc mod; vector <float> lAudio; vector <float> rAudio;};

ミキシングキャリアオシレーター周波数モジュレーターオシレーター周波数

Page 49: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

ofxMaximでFM合成‣ testApp.cpp - audioOut() FM合成をしている部分void testApp::audioOut(float * output, int bufferSize, int nChannels){ for (int i = 0; i < bufferSize; i++){ float index, modFreq; ofMap(modFreq, 0, mouseX, 20, 8000); ofMap(index, 0, mouseY, 1, 2000); wave = car.sinewave(mouseY*mod.sinewave(mouseX/10)+440); mymix.stereo(wave, outputs, 0.5); lAudio[i] = output[i*nChannels ] = outputs[0]; rAudio[i] = output[i*nChannels + 1] = outputs[1];! }}

Page 50: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

ofxMaximでFM合成‣ testApp.cpp - audioOut() FM合成をしている部分void testApp::audioOut(float * output, int bufferSize, int nChannels){ for (int i = 0; i < bufferSize; i++){ float index, modFreq; ofMap(modFreq, 0, mouseX, 20, 8000); ofMap(index, 0, mouseY, 1, 2000); wave = car.sinewave(mouseY*mod.sinewave(mouseX/10)+440); mymix.stereo(wave, outputs, 0.5); lAudio[i] = output[i*nChannels ] = outputs[0]; rAudio[i] = output[i*nChannels + 1] = outputs[1];! }}

モジュレーターの周波数とモジュレーターの音量(Index)を設定

Page 51: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

ofxMaximでFM合成‣ testApp.cpp - audioOut() FM合成をしている部分void testApp::audioOut(float * output, int bufferSize, int nChannels){ for (int i = 0; i < bufferSize; i++){ float index, modFreq; ofMap(modFreq, 0, mouseX, 20, 8000); ofMap(index, 0, mouseY, 1, 2000); wave = car.sinewave(mouseY*mod.sinewave(mouseX/10)+440); mymix.stereo(wave, outputs, 0.5); lAudio[i] = output[i*nChannels ] = outputs[0]; rAudio[i] = output[i*nChannels + 1] = outputs[1];! }}

FM合成

Page 52: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

ofxMaximでFM合成‣ testApp.cpp - audioOut() FM合成をしている部分void testApp::audioOut(float * output, int bufferSize, int nChannels){ for (int i = 0; i < bufferSize; i++){ float index, modFreq; ofMap(modFreq, 0, mouseX, 20, 8000); ofMap(index, 0, mouseY, 1, 2000); wave = car.sinewave(mouseY*mod.sinewave(mouseX/10)+440); mymix.stereo(wave, outputs, 0.5); lAudio[i] = output[i*nChannels ] = outputs[0]; rAudio[i] = output[i*nChannels + 1] = outputs[1];! }}

左右2chでミックス

Page 53: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

ofxMaximでFM合成‣ testApp.cpp - audioOut() FM合成をしている部分void testApp::audioOut(float * output, int bufferSize, int nChannels){ for (int i = 0; i < bufferSize; i++){ float index, modFreq; ofMap(modFreq, 0, mouseX, 20, 8000); ofMap(index, 0, mouseY, 1, 2000); wave = car.sinewave(mouseY*mod.sinewave(mouseX/10)+440); mymix.stereo(wave, outputs, 0.5); lAudio[i] = output[i*nChannels ] = outputs[0]; rAudio[i] = output[i*nChannels + 1] = outputs[1];! }} オーディオ出力

波形表示用にデータをコピー

Page 54: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

ofxMaximでFM合成‣ 実行結果:FM合成

Page 55: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

音響合成言語・アプリケーションとの連携Open Sound Control (OSC) について

Page 56: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

‣ Open Sound Control のプロジェクトのWebページより

‣ Open Sound Control (OSC) is a protocol for communication among computers, sound synthesizers, and other multimedia devices that is optimized for modern networking technology. Bringing the benefits of modern networking technology to the world of electronic musical instruments, OSC's advantages include interoperability, accuracy, flexibility, and enhanced organization and documentation.

Open Sound Control とは

Page 57: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

‣ Open Sound Control のプロジェクトのWebページより

‣ Open Sound Control (OSC) は、コンピュータやシンセサイザーや、その他のマルチメディアデバイス同士でコミュニケーションするための通信プロトコルです。現代のネットワーク技術の成果を電子楽器の世界に適用することで、OSCは、相互運用性、正確さ、柔軟さ、また、拡張性に優れた性能を持ちます。

Open Sound Control とは

Page 58: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

‣ Open Sound Control のポイント

‣ ポストMIDIを目指す‣ インターネットのプロトコルの仕組みを、音楽やマルチメディアの世界へ適用 (UDP/IPを利用)

‣ 多くの機器、言語、アプリケーションに実装済み‣ オープンでシンプルな命名規則 ← URLの仕組みに似ている

Open Sound Control とは

Page 59: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

‣ Open Sound Control が実装された主な環境

‣ サウンド系‣ Max/MSP‣ Pd‣ SuperCollider‣ Chuck‣ Csound‣ Reactor など

‣ ビジュアル系‣ Flash ( flosc )‣ Processing‣ OpenFrameworks‣ QuartzComposer‣ vvvv

Open Sound Control とは

Page 60: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

‣ Open Sound Control が実装された主な環境

‣ デバイス‣ Lemur‣ monome

Open Sound Control とは

Page 61: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

‣ Open Sound Control が実装された主な環境

‣ もちろんiPhoneも

Open Sound Control とは

Page 62: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

‣ では、実際にOSCのプロトコルは、どんななっているのか?

/trigger/inst/a 440 0.1 “hello”

OSCのプロトコル

OSC Message OSC Arguments

• 情報内容をラベリング• URLに同様の名前付けの規則

• 情報の本体• いろいろな型を同時に含めることができる

Page 63: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

‣ OSC Messageのアドレスパターン → URLのような階層構造

OSC Message

Page 64: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

OSC の通信のしくみ

Page 65: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

‣ 送信側:IPアドレスとportを指定

OSC の通信のしくみ

IP: 192.168.1.3port: 57120

Page 66: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

‣ 受信側:ポートをオープン

OSC の通信のしくみ

IP: 192.168.1.3port: 57120

Page 67: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

‣ 接続

OSC の通信のしくみ

IP: 192.168.1.3port: 57120

Page 68: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

‣ 送信側:情報を送信‣ 受信側:受信

OSC の通信のしくみ

/trigger/inst/a 440 0.1 “hello”

IP: 192.168.1.3port: 57120

Page 69: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

‣ 受信側:OSCのメッセージを解釈、アプリケーションに適用

OSC の通信のしくみ

/trigger/inst/a 440 0.1 “hello”

IP: 192.168.1.3port: 57120

Page 70: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

‣ openFrameworksでOSCを使用するには?‣ ofxOsc というアドオンを利用する‣ OSCメッセージの送受信ができる

openFrameworksでOSCを使用するには?

Page 71: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

‣ いくつかの、音響合成言語、アプリケーションは、独自にOSCを活用したAddonが存在する

‣ Pd (pure data):ofxPd‣ Pdを利用して音響合成が可能、Pdのパッチは、oFのプロジェクトに内包できる

‣ SuperCollider:ofxSuperCollider‣ OSCを介してSuperColliderのサーバーと通信して音響合成

‣ ofxSuperColliderServer‣ SuperColliderのパッチをoFのプロジェクトに内包できるバージョン (比嘉了さん作!!)

openFrameworksでOSCを使用するには?

Page 72: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

Pdとの連携 - ofxPd

Page 73: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

‣ 簡単なFM合成で実験‣ Pdのパッチ

Pdとの連携 - ofxPd

Page 74: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

‣ 作成したPdのパッチは、dataフォルダに入れる

‣ 連携の詳細は、サンプルファイル「06_ofxPd」をみながら解説します

Pdとの連携 - ofxPd

Page 75: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

SuperColliderとの連携 - ofxSuperCollider

Page 76: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

‣ ofxPdと同様、SuperColliderとの連携も可能

‣ 起動手順が重要、以下の手順で

‣ まず、SuperColliderのパッチを開く‣ SCのLocalhost ServerをBoot‣ SynthDefファイルを選択して評価、楽器を生成‣ openFrameworksのアプリを実行

SuperColliderと連携 - ofxSuperCollider

Page 77: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

ofxMaximでFM合成‣ SuperColliderの楽器定義、reverb, baseSound, newRingSynthDef("reverb", {

arg wet=1.0; var in, fx; in = In.ar(0, 2); fx = in; fx = GVerb.ar(fx, 80); ReplaceOut.ar(0, fx);}).store;

SynthDef("baseSound", { arg note=40, amp=0.1, fadein=12.0; var env, out; env = EnvGen.kr(Env.new([0, amp], [fadein])); out = RLPF.ar(LFPulse.ar([note, note+7].midicps, 0.15), SinOsc.kr(0.1, 0, 10, 72).midicps, 0.1, 0.1); Out.ar(0, out*env);}).store;

SynthDef("newRing", { arg note=40, amp=0.5, pan = 0.0, decay=4.0; var env1, out1, env2, out2, mix; out1 = RLPF.ar(LFPulse.ar([note, note+7].midicps, 0.15), SinOsc.kr(0.1, 0, 10, 72).midicps, 0.1, 0.1); out2 = SinOsc.ar([(note+48).midicps, (note+55).midicps]); env1 = EnvGen.kr(Env.perc(decay/4.0, decay/4.0*3.0, amp, -4), doneAction: 2); env2 = EnvGen.kr(Env.adsr(0.001, 0.4, 0.0, decay, amp*0.1, -4)); mix = (out1 * env1) + (out2 * env2); mix = CombN.ar(mix, 0.31, 0.31, 2, 0.5, mix); Out.ar(0, mix);}).store;

Page 78: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

‣ openFrameworks側の実装はサンプルファイルを見ながら解説します

‣ 「07_ofxSuperCollider」

SuperColliderと連携 - ofxSuperCollider

Page 79: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

‣ 実行結果:画面をクリック!

SuperColliderと連携 - ofxSuperCollider

Page 80: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

‣ ofxSuperColliderを活用したデモを作成してみました‣ 参考にしてみてください

‣http://goo.gl/9rH4K‣ 1_NodeGarden‣ 2_FallCircle‣ 3_RectSequencer

ofxSuperColliderデモ

Page 81: openFrameworks、サウンド機能・音響合成、ofxMaxim, ofxOsc, ofxPd, ofxSuperCollider

‣ 1_NodeGarden

ofxSuperColliderデモ