メインコンテンツまでスキップ

チュートリアルオーディオ入力を処理する

📚 Source Page

このチュートリアルでは、オーディオ入力を処理してオーディオ出力に渡す方法を説明します。

レベル初心者

プラットフォーム:Windows, macOS, Linux

クラス: Random,BigInteger,AudioBuffer

スタート

このチュートリアルのデモ・プロジェクトのダウンロードはこちらから:PIP|ZIP.プロジェクトを解凍し、最初のヘッダーファイルをProjucerで開く。

注記

お使いのオペレーティングシステムが、マイクへのアクセス許可を要求する必要がある場合(現在、iOS、Android、macOS Mojave)、Projucerの関連するエクスポーターの下に対応するオプションを設定し、プロジェクトを再保存する必要があります。

このステップにヘルプが必要な場合は、以下を参照してください。Tutorial: Projucer Part 1: Getting started with the Projucer.

デモ・プロジェクト

このデモ・プロジェクトは、入力信号をホワイト・ノイズで変調します。ホワイトノイズのレベルは変更可能で、出力全体のレベルに影響を与えます (Tutorial: Control audio levelsホワイトノイズを生成するために使用される技術については、こちらを参照)。その結果、入力信号は非常に "ファジー "なものになる。

警告

アプリケーションを実行する際には、フィードバックを避けるよう注意してください(効果はかなり面白いかもしれませんが!)。

マイクとヘッドフォンは別々に使うのがベストだろう。もちろん、このプロジェクトが正しく機能するためには、何らかのオーディオ入力デバイスが必要です。

音声入力

このチュートリアルではAudioAppComponentクラスをデモ・プロジェクト・アプリケーションの基礎として使用します。他のチュートリアルではgetNextAudioBlock()関数 - 参照Tutorial: Build a white noise generator,Tutorial: Control audio levelsそしてTutorial: Build a sine wave synthesiser.このチュートリアルでは、オーディオ入力を読み取り、音声も出力します。このチュートリアルではMainContentComponentコンストラクタで、2つのオーディオ入力と2つのオーディオ出力を要求します:

        setAudioChannels (2, 2);
注記

実際に利用可能な入力または出力の数は、私たちが要求する数よりも少ない場合があります。

バッファの再利用

重要なことは、入力と出力のバッファーは完全に分離されているわけではないということである。入力と出力には同じバッファが使われる。のすべてのコードを一時的にコメントアウトすることで、これをテストすることができる。getNextAudioBlock()関数を使います。アプリケーションを実行すると、オーディオ入力が直接出力に渡されます。アプリケーションのgetNextAudioBlock()関数のチャンネル数はAudioSampleBuffer オブジェクトをbufferToFill構造体は、入力チャンネル数、出力チャンネル数、またはその両方よりも大きくなる可能性があります。要求した入出力チャンネル数を参照するデータのみにアクセスすることが重要である、そしてを使用することができます。特に、入力チャンネル数が出力チャンネル数より多い場合は、以下のようになります。べからず読み取り専用データを含むチャンネルを変更する。

アクティブ・チャンネルの獲得

の中でgetNextAudioBlock()関数が得られる。BigIntegerこれは、アクティブな入出力チャンネルのリストをビットマスク(これはstd::bitsetクラスを使用するかstd::vector<bool>オブジェクト)。これらのBigIntegerを構成するビットの0(非アクティブ)または1(アクティブ)で表されます。BigInteger値である。

注記

参照Tutorial: The BigInteger classに対して実行可能なその他の操作についてはBigIntegerオブジェクトがある。

    void getNextAudioBlock (const juce::AudioSourceChannelInfo& bufferToFill) override
{
auto* device = deviceManager.getCurrentAudioDevice();
auto activeInputChannels = device->getActiveInputChannels();
auto activeOutputChannels = device->getActiveOutputChannels();

反復処理に必要な最大チャンネル数を調べるには、以下のビットを調べればよい。BigIntegerオブジェクトから最上位のビットを見つける。最大チャンネル数はこれより1つ多くなる。

        auto maxInputChannels  = activeInputChannels .getHighestBit() + 1;
auto maxOutputChannels = activeOutputChannels.getHighestBit() + 1;

次に、レベルスライダから希望のレベルを取得し、出力チャンネルを1つずつ処理してオーディオを処理します。入力チャンネルの最大数がゼロの場合(ハードウェアにオーディオ入力がない場合、2つのチャンネルを要求したにもかかわらず、そうなる可能性があります)、オーディオを処理しようとしてはいけません。この場合、単に出力チャンネルバッファをゼロにします(無音を出力します)。個々の出力チャンネルが非アクティブの場合もあるので、チャンネルの状態をチェックし、非アクティブの場合はそのチャンネルにサイレンスを出力する:

        auto level = (float) levelSlider.getValue();

for (auto channel = 0; channel < maxOutputChannels; ++channel)
{
if ((! activeOutputChannels[channel]) || maxInputChannels == 0)
{
bufferToFill.buffer->clear (channel, bufferToFill.startSample, bufferToFill.numSamples);
}

そして、入力されたデータを処理し、出力する:

            else
{
auto actualInputChannel = channel % maxInputChannels; // [1]

if (! activeInputChannels[channel]) // [2]
{
bufferToFill.buffer->clear (channel, bufferToFill.startSample, bufferToFill.numSamples);
}
else // [3]
{
auto* inBuffer = bufferToFill.buffer->getReadPointer (actualInputChannel,
bufferToFill.startSample);
auto* outBuffer = bufferToFill.buffer->getWritePointer (channel, bufferToFill.startSample);

for (auto sample = 0; sample < bufferToFill.numSamples; ++sample)
{
auto noise = (random.nextFloat() * 2.0f) - 1.0f;
outBuffer[sample] = inBuffer[sample] + (inBuffer[sample] * noise * level);
}
}
}
}
}

コードの説明は簡単であろうが、いくつかのハイライトを紹介しよう:

  • [1]入力チャンネルよりも多くの出力チャンネルをリクエストしたかもしれないので、アプリはこれらの余分な出力をどうするか決定する必要がある。この例では、入力チャンネルよりも出力チャンネルの方が多い場合、単純に入力チャンネルを繰り返す。(そのために、modulo演算子を使って、利用可能な入力チャンネル数に基づいて入力チャンネルへのアクセスを「ラップ」している)。他のアプリケーションでは、入力チャンネルより出力チャンネルの方が多い場合、より大きな番号のチャンネルにサイレンスを出力する方が適切かもしれない。
  • [2]個々の入力チャンネルが非アクティブの場合もあるので、その場合も無音を出力する。
  • [3]この最後のブロックは実際にが処理を行う!ここでは、入力と出力バッファのサンプルへのポインタを取得し、入力サンプルにノイズを加えます。
エクササイズ

この例では、次のように振幅の変化を平滑化しない。Tutorial: Build a sine wave synthesiser.これは例をシンプルに保つためでもありますが、いずれにせよ、クラックリング効果によるグリッチを追加で聞くことはないでしょう。入力チャンネルを単純にレベルスライダーの値でスケーリングして出力するようにコードを修正してください。

概要

このチュートリアルでは、JUCE アプリケーションのオーディオ入力からのオーディオ処理について紹介しました。特に

  • コンピュータのオーディオ入力ハードウェアからオーディオにアクセスできるようにオーディオアプリケーションを設定する方法。
  • 入力と出力のバッファは共有される。
  • アクティブなチャンネルと非アクティブなチャンネルをどう扱うか。
  • 入力と出力のチャンネル数が異なる場合、どうすればよいかを推論する方法。

こちらも参照