音量を取得する

iPhoneでマイクから拾った音の音量を取得する方法。


① AudioToolBoxをインポートする

#import <AudioToolbox/AudioToolbox.h>


②音声入力用のキューとタイマーのインスタンス変数を用意する

@implementation ViewController{
    AudioQueueRef _queue;
    NSTimer *_timer;
}


③コールバック関数を宣言する(今回は録音をしないので、中身は空)

static void AudioInputCallback(
                               void* inUserData,
                               AudioQueueRef inAQ,
                               AudioQueueBufferRef inBuffer,
                               const AudioTimeStamp *inStartTime,
                               UInt32 inNumberPacketDescriptions,
                               const AudioStreamPacketDescription *inPacketDescs)
{
}


④音検知の設定、開始

- (void)startUpdatingVolume{
    // 記録するデータフォーマットを決める
    AudioStreamBasicDescription dataFormat;
    //サンプリング周波数(1秒間のフレーム数)
    dataFormat.mSampleRate = 44100.0f;
    //フォーマットID(リニアPCM、MP3、AACなど)
    dataFormat.mFormatID = kAudioFormatLinearPCM;
    //フォーマットフラグ(エンディアン、整数or浮動小数点数)
    dataFormat.mFormatFlags = kLinearPCMFormatFlagIsBigEndian | kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
    //1バケットのバイト数
    dataFormat.mBytesPerPacket = 2;
    //1バケットのフレーム数
    dataFormat.mFramesPerPacket = 1;
    //1フレームのバイト数
    dataFormat.mBytesPerFrame = 2;
    //1フレームのチャンネル数
    dataFormat.mChannelsPerFrame = 1;
    //1チャンネルののビット数
    dataFormat.mBitsPerChannel = 16;
    //?
    dataFormat.mReserved = 0;
    
    // レベルの監視を開始する
    AudioQueueNewInput(&dataFormat, AudioInputCallback, (__bridge void *)(self), CFRunLoopGetCurrent(), kCFRunLoopCommonModes, 0, &_queue);
    AudioQueueStart(_queue, NULL);
    
    // レベルメータを有効化する
    UInt32 enabledLevelMeter = true;
    AudioQueueSetProperty(_queue, kAudioQueueProperty_EnableLevelMetering, &enabledLevelMeter, sizeof(UInt32));
    
    // 定期的にレベルメーターを監視するタイマーを設定
    _timer = [NSTimer scheduledTimerWithTimeInterval:0.1
                                              target:self
                                            selector:@selector(detectVolume:)
                                            userInfo:nil
                                             repeats:YES];
}


⑤一定時間ごとにレベルを取得する(④で指定した秒数ごとに呼ばれる)

- (void)detectVolume:(NSTimer *)timer
{
    // レベルを取得
    AudioQueueLevelMeterState levelMeter;
    UInt32 levelMeterSize = sizeof(AudioQueueLevelMeterState);
    AudioQueueGetProperty(_queue, kAudioQueueProperty_CurrentLevelMeterDB, &levelMeter, &levelMeterSize);
    
    // 最大レベルと平均レベルを表示(値はマイナスを取る、最大が0.0)
    NSLog(@"mPeakPower:%f",levelMeter.mPeakPower);
    NSLog(@"mAveragePower:%f",levelMeter.mAveragePower);
    
    if (levelMeter.mPeakPower > -1.0) {
         //音量が一定値を越えると処理を行う
    }
}


⑥音の検知の終了

- (void)stopUpdatingVolume{
    // キューを空にして停止
    AudioQueueFlush(_queue);
    AudioQueueStop(_queue, NO);
    AudioQueueDispose(_queue, YES);
    //タイマーを停止する
    if ([_timer isValid]) {
	[_timer invalidate];
	_timer = nil;
    }
}

使ったあとは停止しましょう。