チュートリアル: AudioDeviceManagerクラス
このチュートリアルでは、すべてのプラットフォームでオーディオデバイスを管理するために使用されるAudioDeviceManagerクラスを紹介します。これにより、デバイスのサンプルレートや入出力の数などを設定できます。
レベル: 中級
プラットフォーム: Windows, macOS, Linux, iOS, Android
クラス: AudioDeviceManager, AudioDeviceSelectorComponent, ChangeListener, BigInteger
はじめに
このチュートリアルでは、オーディオの入出力にAudioAppComponentクラスを使用する基本的な理解があることを前提としています(Tutorial: Processing audio inputを参照)。また、基本的なGUIレイアウト技術に精通していることも前提としています(Tutorial: Parent and child componentsを参照)。
このチュートリアルのデモプロジェクトをダウンロードしてください: PIP | ZIP。プロジェクトを解凍し、Projucerで最初のヘッダーファイルを開いてください。
この手順でヘルプが必要な場合は、Tutorial: Projucer Part 1: Getting started with the Projucerを参照してください。
デモプロジェクト
このデモプロジェクトは、Projucerのオーディオアプリケーションテンプレートをベースにしています。AudioDeviceSelectorComponentオブジェクトを表示し、オーディオデバイス設定を構成できます。また、現在のオーディオデバイス設定を報告するシンプルなテキストコンソールも表示します。アプリケーションは、オーディオ処理要素の現在のCPU使用率も表示します。
ここで紹介するコードは、JUCEデモのAudioSettingsDemoと大まかに似ています。主な違いは、生成されるオーディオがTutorial: Processing audio inputと同じであることです(これはオーディオ入力をホワイトノイズでリング変調します)。

オーディオデバイス
JUCEは、サポートするすべてのプラットフォームでオーディオデバイスにアクセスするための一貫した手段を提供します。ここで提供されるデモアプリケーションはデスクトッププラットフォームにのみデプロイされる可能性がありますが、これはGUIレイアウトの制約によるものです。オーディオはモバイルプラットフォームでもシームレスに動作します。
オーディオアプリケーションテンプレートでは、AudioAppComponentクラスがAudioDeviceManagerオブジェクトdeviceManagerをインスタンス化します --- これはpublicメンバーであるため、サブクラスからアクセスできます。AudioAppComponentクラスは、このAudioDeviceManagerオブジェクトの基本的な初期化も実行します --- これはAudioAppComponent::setAudioChannels()を呼び出すときに行われます。
AudioDeviceManagerクラスは、オーバーライドされない限り、デフォルトのオーディオデバイスを使用しようとします。これはコードで構成するか、ここで説明するAudioDeviceSelectorComponentを介して構成できます。デバイスの設定と環境設定は、その後のアプリケーション起動時に保存および呼び出すことができます。AudioDeviceManagerクラスは、優先デバイスが使用できなくなった場合(たとえば、前回の起動以降に外部オーディオデバイスが取り外された場合)、このような状況でデフォルトデバイスにフォールバックすることもできます。
AudioDeviceManagerクラスは、受信MIDIメッセージのハブでもあります。これについては他のチュートリアルで説明します(Tutorial: Handling MIDI eventsを参照)。
AudioDeviceManagerクラスは、ChangeBroadcasterクラスを継承しているため、設定の変更をブロードキャストできます。コンポーネントの右側には、AudioDeviceManagerオブジェクトの変更がトリガーされるたびに、重要なオーディオデバイス設定の一部が表示されます。
AudioDeviceSelectorComponentクラス
AudioDeviceSelectorComponentクラスは、すべてのプラットフォームでオーディオデバイスを構成するための便利な方法を提供します。前述のように、これはデモプロジェクトのユーザーインターフェイスの右側に表示されます。AudioDeviceSelectorComponentオブジェクトが構築されるとき、制御したいAudioDeviceManagerオブジェクトを、サポートするチャンネル数を含む他の多くのオプションと一緒に渡します(詳細については、AudioDeviceSelectorComponentクラスのコンストラクタを参照してください)。ここでは、AudioAppComponentのメンバーであるAudioDeviceManagerオブジェクトを渡し、最大256の入出力チャンネルを許可し、MIDI設定を非表示にし、チャンネルをステレオペアではなく単一チャンネルとして表示することで、AudioDeviceSelectorComponentオブジェクトを作成します:
MainContentComponent()
: audioSetupComp (deviceManager,
0, // minimum input channels
256, // maximum input channels
0, // minimum output channels
256, // maximum output channels
false, // ability to select midi inputs
false, // ability to select midi output device
false, // treat channels as stereo pairs
false) // hide advanced options
{
インターフェイスは、以下を制御できるように構成されています:
- 出力デバイスの選択。
- 入力デバイスの選択。
- 入出力チャンネルの有効化と無効化。
changeListenerCallback()関数では、AudioDeviceManagerオブジェクトにアクセスして現在のオーディオデバイスを取得するdumpDeviceInfo()関数を呼び出します。次に、デバイスに関するさまざまな情報を取得します:
void dumpDeviceInfo()
{
logMessage ("--------------------------------------");
logMessage ("Current audio device type: " + (deviceManager.getCurrentDeviceTypeObject() != nullptr ? deviceManager.getCurrentDeviceTypeObject()->getTypeName() : "<none>"));
if (auto* device = deviceManager.getCurrentAudioDevice())
{
logMessage ("Current audio device: " + device->getName().quoted());
logMessage ("Sample rate: " + juce::String (device->getCurrentSampleRate()) + " Hz");
logMessage ("Block size: " + juce::String (device->getCurrentBufferSizeSamples()) + " samples");
logMessage ("Bit depth: " + juce::String (device->getCurrentBitDepth()));
logMessage ("Input channel names: " + device->getInputChannelNames().joinIntoString (", "));
logMessage ("Active input channels: " + getListOfActiveBits (device->getActiveInputChannels()));
logMessage ("Output channel names: " + device->getOutputChannelNames().joinIntoString (", "));
logMessage ("Active output channels: " + getListOfActiveBits (device->getActiveOutputChannels()));
}
else
{
logMessage ("No audio device open");
}
}
getListOfActiveBits()関数を使用して、アクティブなチャンネルのリストをビットマスクとして表すBigIntegerオブジェクトをStringオブジェクトに変換します。BigIntegerオブジェクトは、std::bitsetやstd::vector<bool>と同様にビットマスクとして使用されます。ここでは、チャンネルはBigInteger値を構成するビット内の0(非アクティブ)または1(アクティブ)で表されます。BigIntegerオブジェクトで実行できる他の操作については、Tutorial: The BigInteger classを参照してください。
このような変更に応答することは、実際のアプリケーションで非常に便利です。アプリケーションで使用可能なチャンネル数が変更された場合に知る必要があることがよくあります。多くの場合、サンプルレートや他のオーディオパラメータの変更に適切に対応することが重要です。
演習: AudioDeviceSelectorComponentクラスのコンストラクタのさまざまな設定を試してみてください --- これは、アプリケーションがアドレス指定できるチャンネル数を制限できるマルチチャンネルサウンドカードをお持ちの場合に特に便利です。また、チャンネルのペアをステレオペアとして表示する方法も確認できます。
AudioDeviceSelectorComponentクラスには、Testボタンも含まれています。これにより、デバイス出力からサイントーンが再生され、ユーザーがターゲットデバイスでオーディオ出力が機能していることをテストするのに役立ちます。
CPU使用率
AudioDeviceManager::getCpuUsage()関数を呼び出すことで、アプリケーションのオーディオ処理要素のCPU使用率を取得します。MainContentComponentクラスでは、Timerクラスを継承し、50msごとにトリガーするようにタイマーを開始します。timerCallback()関数では、AudioDeviceManagerオブジェクトからCPU使用率を取得します。この値は、Labelオブジェクトにパーセンテージ(小数点以下6桁)として表示されます:
void timerCallback() override
{
auto cpu = deviceManager.getCpuUsage() * 100;
cpuUsageText.setText (juce::String (cpu, 6) + " %", juce::dontSendNotification);
}
この特定のアプリケーションでは、オーディオ処理がほとんど行われていないため、CPU使用率は非常に低くなる可能性があります --- 多くのターゲットデバイスでおそらく1%未満です。ただし、さまざまな設定の組み合わせを試すことで、サンプルレートとバッファサイズがCPU負荷に与える影響を確認できます。一般的に、サンプルレートが高く、バッファサイズが小さいほど、CPUの使用量が多くなります。
まとめ
このチュートリアルでは、AudioDeviceManagerクラスとオーディオデバイス全般の機能の一部を紹介しました。以下の方法がわかるようになったはずです:
- オーディオアプリケーションテンプレートを使用して、AudioAppComponentオブジェクト内からAudioDeviceManagerオブジェクトにアクセスする。
- AudioDeviceManagerオブジェクトを制御するためのAudioDeviceSelectorComponentオブジェクトを作成する。
- オーディオデバイスの変更に応答する。
- サンプルレートや使用可能なチャンネル数など、オーディオデバイス内の有用な設定にアクセスする。