Audio Unitを使おう
プロフェッショナルプログラマーよりの転載です。
Audio Unit というのは, Core Audio のオーディオ処理の機能を持つ1つの単位のこと。Input, Effect, Output などが Audio Unit になります。 詳しい説明は, 各所ありますのでこれくらいです。
Mac OS X と, iOS ではプログラムの書き方が違います。
Mac OS Xでは, My Codex Leister さんの第03回.Audio Unitを使って音を鳴らす(前準備) のサンプルが完璧です。
My Codex Leister さんでも言及のとおり, iOSでは, kAudioUnitType_Generatorつまり, 入力を発生させるような Audio Unit がないような気がします。
Output, Effect あたりはできそうな気がします。
コンポーネントの違い
Mac OS X | AudioUnit.framework | ComponentDescription |
iOS | AudioToolbox.framework | AudioComponentDescripton |
iOSでは, AudioComponentDescription
struct AudioComponentDescription { OSType componentType; OSType componentSubStype; OSType componentManufacturer; UInt32 componentFlags; UInt32 componentFlagsMask; }; typedef struct AudioComponentDescription AudioComponentDescription;
を使って, AudioComponent を取り出します。
その違い以外は, ほぼ Mac OS Xと同じコードです。
iOS で, Audio Unit で sin波を発生させて聞いてみるサンプルです。
サンプル
AudioUnitViewController.h
#import "ViewController.h" #import <AudioToolbox/AudioToolbox.h> #define kRate 44100 #define kFreq 440 @interface AudioUnitViewController : ViewController @property (nonatomic)AudioUnit unit; @property (nonatomic)float phase; - (IBAction)startClick:(id)sender; - (IBAction)stopClick:(id)sender; @end
AudioUnitViewController.m
#import “AudioUnitViewController.h”
@interface AudioUnitViewController ()
@end
@implementation AudioUnitViewController
@synthesize unit;
– (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
– (void)viewDidLoad
{
[super viewDidLoad];
}
– (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
OSStatus AuRenderCallback(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData)
{
//NSLog(@”inNumberFrames: %ld”, inNumberFrames);
//NSLog(@”Bufs %ld”, ioData->mNumberBuffers);
AudioUnitViewController *controller = (__bridge AudioUnitViewController *)inRefCon;
float *buf = ioData->mBuffers[0].mData;
float freq = kFreq * 2 * M_PI / kRate;
for ( int i=0; i < inNumberFrames; i++ ) { float wave = sin(controller.phase); *buf++ = wave; controller.phase += freq; } return noErr; } -(void)audioUnit { OSStatus status; AudioComponentDescription cd; cd.componentType = kAudioUnitType_Output; cd.componentSubType = kAudioUnitSubType_RemoteIO; cd.componentManufacturer = kAudioUnitManufacturer_Apple; cd.componentFlags = 0; cd.componentFlagsMask = 0; // Find compoent and create instance AudioComponent comp = AudioComponentFindNext(NULL, &cd); status = AudioComponentInstanceNew(comp, &unit); // Set Callback AURenderCallbackStruct input; input.inputProc = AuRenderCallback; input.inputProcRefCon = (__bridge void *)(self); status = AudioUnitSetProperty(unit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &input, sizeof(input)); status = AudioUnitInitialize(unit); status = AudioOutputUnitStart(unit); self.phase = 0; } -(void)stop { AudioOutputUnitStop(unit); } - (IBAction)startClick:(id)sender { [self audioUnit]; } - (IBAction)stopClick:(id)sender { [self stop]; } @end [/cpp] UIはボタンを入れたのみ。ボタンを押すと, Output用のAudioUnitを作成して, スタートします。 Callbackでは, 生成したsin波を入れて再生させます。