トップ «前の日記(2012-03-26) 最新 次の日記(2012-03-28)» 編集

Cocoa練習帳

iOS/iPhone/iPad/watchOS/tvOS/MacOSX/Android プログラミング, Objective-C, Cocoa, Swiftなど

2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|

2012-03-27 [iOS]Looping Recorderの基礎(Audio Unit)

_ Audio Units

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;
}

次回は、レンダリング通知関数に渡されたデータをリングバッファに書き込み、これをループ再生させる予定だ。

_ ソースコード

GitHubからどうぞ。
https://github.com/murakami/DemoAudio - GitHub

_ 関連情報

Cocoa Life KOF2011特別編 - Facebook
Cocoa勉強会 関西の会誌。
iPhone Core Audioプログラミング(永野 哲久 著)
とれも参考にさせていただきました。

トップ «前の日記(2012-03-26) 最新 次の日記(2012-03-28)» 編集