サウンド再生中のタイマーの使用

音声ファイルからサウンドを再生する。かつ再生している間、サウンドの出力レベルを読み取り続ける処理をタイマーで行う。そのために、ソースコードViewController.mの中で以下のように記述した。主要部分のみを示す。

まずは、オブジェクト変数名を定義しておく。

@implementation ViewController
{
    AVAudioPlayer *ap;
}


AVAudioPlayerクラスのオブジェクトを生成する。ここでは音声ファイルsample.mp3を用意しておき、それを再生する。meteringEnabledプロパティを設定すると、サウンドの出力レベルを読み取ることが可能になるので、それをYESとしている。

    NSBundle *bd = [NSBundlemainBundle];
    NSString *path
    = [bd pathForResource:@"sample.mp3"ofType:@""];
    NSURL *url = [NSURLfileURLWithPath:path];
    ap = [[AVAudioPlayer alloc]
          initWithContentsOfURL:url error:nil];
   
    ap.meteringEnabled = YES;
    ap.delegate = self;
    channels = ap.numberOfChannels;


画面上には、サウンドの再生ボタンを設置している。このボタンを押すと、NSTimerクラスのオブジェクト(下の例では、playerTimer)を生成し、音声ファイルの再生([ap play])を始める。NSTimerクラスを使うことで、タイマーを管理できる。つまり、一定間隔(ここでは0.1秒間隔)でmonitorAudioPlayerを呼び出す。

- (IBAction)bt_touchdown:(UIButton *)sender
{
    if(sender == bt[0]){
        bt[0].enabled = NO;
       
        if (!playerTimer)
        {
            playerTimer = [NSTimer scheduledTimerWithTimeInterval:0.1
                        target:selfselector:@selector(monitorAudioPlayer)userInfo:nil
                        repeats:YES];
        }
        [ap play];
    }


チャネルごとに最大出力レベルを読み取る。出力はデシベル単位で表示される。

- (void)monitorAudioPlayer
{
    for (int i=0; i<channels; i++) {
        float db;
        [ap updateMeters];
        db = [ap peakPowerForChannel:i];
        NSLog(@"db=%f", db);
    }
}


音声ファイルの再生を止めた後の処理の中で、タイマーを止める(出力レベルの読み取りをやめる)ために以下の処理を行う。

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)sender successfully:(BOOL)flag
{
    [playerTimer invalidate];
    playerTimer = nil;
}

参考サイト:iphone - Trying to understand AVAudioPlayer and audio level metering - Stack Overflow