iOS/iPhone/iPad/watchOS/tvOS/MacOSX/Android プログラミング, Objective-C, Cocoa, Swiftなど
Audio UnitはCore Audioを拡張するPlug-insの事で、Audio Unitを使用すれば、音の生成や変換等の機能が利用できる。
追加するフレームワークは、『AudioUnit.framework』。インポートするヘッダ・ファイルは『AudioUnit/AudioUnit.h』だ。
今回は、録音部分についてチャレンジだ!
ループペダルの実装には、録音と再生のためのAudio Unitを別々用意することになると思うが、扱いが楽になるという事と、将来の拡張を考え、Audio Unit Processing Graph Servicesを利用する事にする。
以下が初期化のコードだ。
- (AudioStreamBasicDescription)canonicalASBDSampleRate:(Float64)sampleRate channel:(UInt32)channel
{
AudioStreamBasicDescription audioFormat;
audioFormat.mSampleRate = sampleRate;
audioFormat.mFormatID = kAudioFormatLinearPCM;
audioFormat.mFormatFlags = kAudioFormatFlagsCanonical;
audioFormat.mChannelsPerFrame = channel;
audioFormat.mBytesPerPacket = sizeof(AudioSampleType) * channel;
audioFormat.mBytesPerFrame = sizeof(AudioSampleType) * channel;
audioFormat.mFramesPerPacket = 1;
audioFormat.mBitsPerChannel = 8 * sizeof(AudioSampleType);
audioFormat.mReserved = 0;
return audioFormat;
}
- (void)prepareAUGraph
{
AUNode remoteIONode;
AudioUnit remoteIOUnit;
NewAUGraph(&__auGraph);
AUGraphOpen(self.auGraph);
AudioComponentDescription cd;
cd.componentType = kAudioUnitType_Output;
cd.componentSubType = kAudioUnitSubType_RemoteIO;
cd.componentManufacturer = kAudioUnitManufacturer_Apple;
cd.componentFlags = 0;
cd.componentFlagsMask = 0;
AUGraphAddNode(self.auGraph, &cd, &remoteIONode);
AUGraphNodeInfo(self.auGraph, remoteIONode, NULL, &remoteIOUnit);
UInt32 flag = 1;
AudioUnitSetProperty(remoteIOUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &flag, sizeof(flag));
AudioStreamBasicDescription audioFormat = [self canonicalASBDSampleRate:44100.0 channel:1];
AudioUnitSetProperty(remoteIOUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &audioFormat, sizeof(AudioStreamBasicDescription));
AudioUnitSetProperty(remoteIOUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &audioFormat, sizeof(AudioStreamBasicDescription));
AUGraphInitialize(self.auGraph);
}
RemoteIOユニットでマイクを開く。その際、入力がモノラルで、出力がステレオだと、片方から再生となってしまう為、出力をモノラルに合わせている。
recordボタンを押下されるとレンダリングを開始し、レンダリング通知関数を登録して、録音されたデータを受け取れるようにする。
- (IBAction)record:(id)sender
{
if (self.isRecording) return;
AUGraphStart(self.auGraph);
AUGraphAddRenderNotify(self.auGraph, MyAURenderCallack, NULL);
self.isRecording = YES;
}
レンダリング通知関数では、今な何もしていない。
static OSStatus MyAURenderCallack(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData)
{
DBGMSG(@"%s, inNumberFrames:%u", __func__, (unsigned int)inNumberFrames);
return noErr;
}
次回は、レンダリング通知関数に渡されたデータをリングバッファに書き込み、これをループ再生させる予定だ。