1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

openframeworksでオーディオ(音声)データをofxshadertoyのシェーダーに渡す

Posted at

openframeworks+ofxshadertoyでオーディオ(音声)データの扱い

openframeworksでサウンドデータをofxshadertoyのシェーダーに渡すやり方は、本家
https://openframeworks.cc
でもあまり詳しく論じられていません。それがわからないと、https://www.shadertoy.com/view/Xds3Rr
とかは、openframeworksで動作しません。
今回、色々試して、とりあえず動いているようなので、手順を記します。

out000001.jpg

out000122.jpg

アドオンofxFftの導入

先ず、アドオンofxFftを導入します。
projectGenerator.exeなどのツールを使って、ofxFftを組み込んでください。

ofApp.hの修正

ofApp.hに

enum { SINE, MIC, NOISE };

及び

 #include "ofxFft.h"

を追加します。
また、以下の関数と変数を追加します。

 void audioReceived(float* input, int bufferSize, int nChannels);	
 ofxFft *fft;
 ofMutex soundMutex;
 ofSoundStream sound_stream;
 vector<float> middleBins, audioBins;
 vector<float> middleBuffer, audioBuffer;
ofTexture mTexture;

ofApp.cppの修正

次に、audioReceivedの処理を以下のようにします。

 void ofApp::audioReceived(float* input, int bufferSize, int nChannels) {

	if (!audioOn) return;
	if (mode == MIC) {
		// store input in audioInput buffer
		memcpy(&audioBuffer[0], input, sizeof(float) * bufferSize);

		float maxValue = 0;
		for (int i = 0; i < bufferSize; i++) {
			if (abs(audioBuffer[i]) > maxValue) {
				maxValue = abs(audioBuffer[i]);
			}
		}
		for (int i = 0; i < bufferSize; i++) {
			audioBuffer[i] /= maxValue;
		}

	}
	else if (mode == NOISE) {
		for (int i = 0; i < bufferSize; i++)
			audioBuffer[i] = ofRandom(-1, 1);
	}
	else if (mode == SINE) {
		for (int i = 0; i < bufferSize; i++)
			audioBuffer[i] = sinf(PI * i * mouseX / appWidth);
	}

	fft->setSignal(&audioBuffer[0]);

	float* curFft = fft->getAmplitude();
	memcpy(&audioBins[0], curFft, sizeof(float) * fft->getBinSize());

	float maxValue = 0;
	for (int i = 0; i < fft->getBinSize(); i++) {
		if (abs(audioBins[i]) > maxValue) {
			maxValue = abs(audioBins[i]);
		}
	}
	for (int i = 0; i < fft->getBinSize(); i++) {
		audioBins[i] /= maxValue;
	}

	soundMutex.lock();
	middleBuffer = audioBuffer;
	middleBins = audioBins;
	soundMutex.unlock();
}

上記はオーディオデータを受け取った場合の処理です。
この受け取ったデータをシェーダーに渡すためにテクスチャーに変換します。
void ofApp::update()内に、

    soundMutex.lock();
    unsigned char signal[1024];
    // for FFT
    for (int i = 0; i < 512; i++) {
       signal[i] = (unsigned char)(middleBins.at(i) * 255);
    }
    // for wave
    for (int i = 0; i < 512; i++) {
       signal[512 + i] = ofMap(middleBuffer.at(i), -1.0, 1.0, 0, 255);
    }
    soundMutex.unlock();
    mTexture.loadData(signal, 512, 2, GL_RED);

を追加し、フレームごとに音声データをmTextureにロードします。
そして以下のようにチャンネル(0-3)とmTextureを指定して

shadertoy[shdrNum].setTexture(<チャンネル>, mTexture);

とすればオーディオデータがシェーダーに渡ります。

1
2
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
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?