ノイズを発生させる音声処理の部分を見ていきたいと思います。
ノイズの作り方も参考になるね~
前回、ノイズジェネレータを作成して動作させることができました。とりあえず動作させることを目的として、音声処理の部分もなんとなくさらっと読みつつコピペしましたので、今回は、チュートリアルの記事を読んで、内容を理解していこうと思います。
今回参考にしている公式チュートリアルは、次のページの「Generating audio data」の項目です。
こんな人の役に立つかも
・JUCEフレームワークに入門したい人
・JUCEプログラミングでオーディオアプリを作成したい人
・JUCEで音声再生を行いたい人
音声データを生成する
getNextAudioBlock関数へ渡される引数「bufferToFill」は、「AudioSourceChannelInfo」という構造体です。
void MainComponent::getNextAudioBlock (const juce::AudioSourceChannelInfo& bufferToFill)
//[1]仮引数はアドレスで
{
bufferToFillは、AudioSourceChannelInfoクラスのオブジェクトのアドレスが格納されて渡されます。これは、C++の参照渡しという方法が利用されています。C++の参照渡しについては次のサイトがわかりやすかったです。
また、「AudioSourceChannelInfo」構造体については、以下のドキュメントを参考にします。
ということで、仮引数で音声データが格納されているバッファの位置がわかる、ということですね~。
次のプログラムの[2]のforの条件では、bufferという変数が出てきます。「AudioSourceChannelInfo」構造体(bufferToFill)には、publicなメンバ変数として、「buffer」というものを持っています。
このメンバ変数のbufferは、「AudioBuffer<float>」クラスです。
//[2]チャンネル数分のループです。
for (auto channel = 0; channel < bufferToFill.buffer->getNumChannels(); ++channel)
{
//[3]特定のチャンネルの音声バッファデータを取り出します。
auto* buffer = bufferToFill.buffer->getWritePointer(channel, bufferToFill.startSample);
//[4]音声バッファへノイズを書き込みます。
for (auto sample = 0; sample < bufferToFill.numSamples; ++sample)
buffer[sample] = random.nextFloat() * 0.25f - 0.125f;
}
}
AudioBufferクラスには、「getNumChannels」というメンバ関数があり、バッファが持っているチャンネル数を返してくれます。このバッファーのチャンネル数は、コンストラクタで実行した「setAudioChannels」関数の出力の値と一致する必要があるようです。
[2]の部分では、LとRの2チャンネル分の出力を作成する必要があるので、バッファから得られたチャンネル数のループを作成しています。
ループの中の[3]から、実際に音声データを扱う処理が始まります。ここで「buffer」というローカル変数が作成されますが、これは先のものとは違う変数です。名称変更したいですね^^;
先ほどのbuffer変数は「bufferToFill.buffer」と記載します。
「bufferToFill.buffer」(「AudioBuffer<float>」クラス)には、「getWritePointer」というメンバ関数があり、特定のチャンネルの音声バッファの書き込み可能なポインタを返してくれるようです。引数としては、(チャンネル数、開始サンプル)を与えているようです。第二引数のstartSampleについてはこのように与えるとサンプルの最初が指定されるようですね。
多分、こんな感じ、というイメージを記載してみました^^;
勝手な脳内イメージ発動ですね。
これで、チャンネル0の音声ブロックの最初を指し示すポインタが得られました。
文章が長くなったので、[4]のプログラムを再度掲載します。
//[4]音声バッファへノイズを書き込みます。
for (auto sample = 0; sample < bufferToFill.numSamples; ++sample)
buffer[sample] = random.nextFloat() * 0.25f - 0.125f;
for文で、先ほどのイメージのように、音声バッファ、浮動小数点の配列に順次アクセスしていきます。配列の最後は「bufferToFill.numSamples」となり、開始を0とすることで、順番にすべてのサンプルへアクセスすることができます。
randomは、JUECのrandomクラスで、nextFloat関数を実行すると「0.0~1.0」の範囲のランダムなfloatを得ることができます。
ランダムに得られる0~1のfloatからプログラムのような計算で、-0.125~0.125のランダムなホワイトノイズを発生させています。
最小値:0.0のとき
0.0×0.25-0.125=-0.125
中間値:0.5のとき
0.5×0.25-0.125=0
最大値:1.0のとき
1.0×0.25-0.125=0.125
ちなみに、チュートリアルでは先に解説されていますが、フルスケール(最大音量)の波形は-1.0~1.0になります。(出力段階でこの範囲に収まっていれば、処理の中間で超えることは問題がないとのことです。)
1や-1はかなり大きい音量なので、注意する必要がありそうです。
GitHub
GitHubの以下のリポジトリに今回のノイズジェネレータのプログラムを配置しましたので、ご参考に、どうぞご利用ください。