[iOS]Looping Recorderの基礎(Audio Unit (7))
一応、録音した音が再生できた。だが、かなり荒いコードだ。そもそも、iPhoneシミュレータでAudio Unitを使用する場合、今のXcodeのバージョンだと問題があるようで、エラーメッセージが表示されていて、意図した動きをしない。自分のバグの可能性もあるが。実機で動作できたが、モノラル/ステレオの扱い等がいい加減なコードだ。でも、第一歩としては、今回はこれでヨシとしよう。
録音したデータをバッファに保存するコードだ。
- (void)write:(UInt32)inNumberFrames data:(AudioBufferList *)ioData
{
uint32_t available = self.maxSampleCount - self.startingSampleCount;
if (available < inNumberFrames) {
inNumberFrames = available;
}
memcpy(self.buffer + self.startingSampleCount, ioData->mBuffers[0].mData, sizeof(AudioUnitSampleType) * inNumberFrames);
self.startingSampleCount = self.startingSampleCount + inNumberFrames;
if (self.maxSampleCount <= self.startingSampleCount) {
[self stop:nil];
}
}
static OSStatus MyAURenderCallack(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData)
{
AudioUnitViewController *viewController = (AudioUnitViewController *)inRefCon;
[viewController write:inNumberFrames data:ioData];
return noErr;
}
ループ再生するコードだ。
- (void)read:(UInt32)inNumberFrames data:(AudioBufferList *)ioData
{
uint32_t available = self.maxSampleCount - self.startingSampleCount;
uint32_t num = inNumberFrames;
if (available < num) {
num = available;
}
memcpy(ioData->mBuffers[0].mData, self.buffer + self.startingSampleCount, sizeof(AudioUnitSampleType) * num);
self.startingSampleCount = self.startingSampleCount + num;
if (self.maxSampleCount <= self.startingSampleCount)
self.startingSampleCount = 0;
if (num < inNumberFrames) {
num = inNumberFrames - num;
memcpy(ioData->mBuffers[0].mData, self.buffer + self.startingSampleCount, sizeof(AudioUnitSampleType) * num);
self.startingSampleCount = self.startingSampleCount + num;
}
memcpy(ioData->mBuffers[1].mData, ioData->mBuffers[0].mData, sizeof(AudioUnitSampleType) * inNumberFrames);
}
static OSStatus MyPlayAURenderCallack (
void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData
)
{
AudioUnitViewController *viewController = (AudioUnitViewController *)inRefCon;
[viewController read:inNumberFrames data:ioData];
return noErr;
}
例えば、鍵盤楽器のようなアプリケーションを作る場合は、Audio Unitのレスポンスの早さは魅力的だと思う。そうでなければ、ちょっと、面倒かな。
ソースコード
GitHubからどうぞ。
https://github.com/murakami/DemoAudio - GitHub
関連情報
Cocoa Life KOF2011特別編 - Facebook
Cocoa勉強会 関西の会誌。
iPhone Core Audioプログラミング(永野 哲久 著)
とれも参考にさせていただきました。