※2009/10/2追記《このエントリーはMac OS X 10.5での場合について書かれています。10.6以降の場合はこちらをご覧ください。》
今回はプロパティに値を設定してみたいと思います。
取得のときの〜GetPropertyの関数と同じような感じで、設定は〜SetPropertyと名前のついた関数を使います。<CoreAudio/AudioHardware.h>に以下のような関数があります。
extern OSStatus AudioHardwareSetProperty( AudioHardwarePropertyID inPropertyID, UInt32 inPropertyDataSize, const void* inPropertyData) extern OSStatus AudioDeviceSetProperty( AudioDeviceID inDevice, const AudioTimeStamp* inWhen, UInt32 inChannel, Boolean isInput, AudioDevicePropertyID inPropertyID, UInt32 inPropertyDataSize, const void* inPropertyData) extern OSStatus AudioStreamSetProperty( AudioStreamID inStream, const AudioTimeStamp* inWhen, UInt32 inChannel, AudioDevicePropertyID inPropertyID, UInt32 inPropertyDataSize, const void* inPropertyData)
取得のときと違い、AudioDeviceとAudioStreamにAudioTimeStampを渡すinWhenという引数があります。これは設定するタイミングを指定できるものですが、NULLを入れておけばすぐに変更されます。また、プロパティのサイズはポインタではなく値渡しになります。
それではAudioDeviceSetPropertyを使ってサンプリング周波数をアプリケーション側から変更してみたいと思います。今回もFoundation Toolでプロジェクトを作って、main関数に処理を書いてみます。オーディオデバイスのサンプリング周波数のプロパティはkAudioDevicePropertyNominalSampleRateです。
#import <Foundation/Foundation.h>
#import <CoreAudio/CoreAudio.h>
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
OSStatus err = noErr;
UInt32 size;
//デフォルトのアウトプットに設定されているオーディオデバイスを取得する
AudioDeviceID devID;
size = sizeof(devID);
err = AudioHardwareGetProperty(
kAudioHardwarePropertyDefaultOutputDevice, &size, &devID);
if (err != noErr) {
NSLog(@"Get DefaultOutputDevice Err");
goto catchErr;
}
//デバイスからサンプリング周波数を取得する
Float64 sampleRate;
size = sizeof(sampleRate);
err = AudioDeviceGetProperty(
devID, 0, false, kAudioDevicePropertyNominalSampleRate,
&size, &sampleRate);
if (err != noErr) {
NSLog(@"Get NominalSampleRate err");
goto catchErr;
}
//プロパティが書き換え可能か調べる
Boolean isWritable;
err = AudioDeviceGetPropertyInfo(
devID, 0, false, kAudioDevicePropertyNominalSampleRate,
NULL, &isWritable);
if (err != noErr) {
NSLog(@"Get isWritable err");
goto catchErr;
}
if (isWritable == false) {
NSLog(@"isWritable false");
goto catchErr;
}
//サンプリング周波数を変える
if (sampleRate == 44100) {
sampleRate = 48000;
} else {
sampleRate = 44100;
}
//デバイスにサンプリング周波数を設定する
size = sizeof(sampleRate);
err = AudioDeviceSetProperty(
devID, NULL, 0, false, kAudioDevicePropertyNominalSampleRate,
size, &sampleRate);
if (err != noErr) {
NSLog(@"Set NominalSampleRate err");
goto catchErr;
}
catchErr:
[pool drain];
return 0;
}
<foundation><coreaudio></coreaudio></foundation>
これを実行すると、オーディオデバイスのサンプリング周波数を44.1kHzであれば48kHzに切り替え、その他であれば44.1kHzに切り替えます。Audio MIDI 設定を立ち上げた状態で実行すると切り替わっているのが分かると思います。(本来ならAudio MIDI 設定のようにサポートされているサンプリング周波数を取得して、その中から選ぶのが正しいやり方だと思います。とりあえずサンプルですので。)
いちおうこれで設定はできるのですが、inWhenにNULLを設定してすぐに設定が行われるようにしても、デバイス本体はプログラムとは関係なく動作しますので、設定直後にサンプリング周波数が変更されたと想定して処理を進めてしまうと、実は設定が変更されていなくて問題が出てくる場合があります。今回のサンプルでも、main関数内のAudioDeviceSetPropertyの後に再びGetPropertyでサンプリング周波数を取得しても、設定直後だと変更前の値が返ってくるときがあります。
このようにデバイスに値が設定された事を確認してから続きの処理を開始したい場合や、Audio MIDI 設定などで外部から設定が変更されたときに何か処理を行いたい場合の方法は、次回にやってみたいと思います。