如何使用avaudiorecorder制作音频表电平

问题描述 投票:0回答:6

我正在尝试创建音频表级别,同时使用 avaudiorecorder 录制用户语音。我可以尝试什么来实现这一目标?

iphone
6个回答
16
投票

实际上,代码非常简单,因为 AVAudioPlayer 和 AVAudioRecorder 已经内置了方法来帮助您上路。我的方法是这样的:

  • 重复调用
    -updateMeters
    averagePowerForChannel:
    &
    peakPowerForChannel:
    方法并调用委托方法来通知控制对象

示例:

NSOperationQueue *queue=[[NSOperationQueue alloc] init];
NSInvocationOperation *operation=[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(updateMeter) object:nil];
[queue addOperation: operation];

-(void)updateMeter
{
  do {
      //don't forget:
      [recorder updateMeters];
       self.averagePower   = [recorder averagePowerForChannel:0];
       self.peakPower      = [recorder peakPowerForChannel:0];

       // we don't want to surprise a ViewController with a method call
       // not in the main thread
      [self.delegate performSelectorOnMainThread: @selector(meterLevelsDidUpdate:) withObject:self waitUntilDone:NO];
      [NSThread sleepForTimeInterval:.05]; // 20 FPS
     }while(someCondition);
}

如果您的视图控制器实现了

meterLevelsDidUpdate:
方法,您可以使用此方法来更新您的 Level Meter。

  • 创建一个 UIView 子类,其中的子视图根据平均值或峰值更改其高度。调整口味。

7
投票

很简单,你可以使用 NSTimer 来实现:

- (void)startAudioMetering {
    self.meterTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(updateAudioMeter)userInfo:nil repeats:YES];
}

- (void)stopAudioMetering {
    [self.meterTimer invalidate];
}

- (void)updateAudioMeter { //called by timer
    // audioRecorder being your instance of AVAudioRecorder
    [self.audioRecorder updateMeters];
    self.dBLevel = [self.audioRecorder averagePowerForChannel:0];
}

警告:创建 AVAudioRecorder 实例时,必须在调用prepareToRecord或record后调用meteringEnabled,否则不会更新Meters:

[self.audioRecorder prepareToRecord];
self.audioRecorder.meteringEnabled = YES;

2
投票

Swift 代码基于 Tom 的答案:

 NSOperationQueue().addOperationWithBlock({[weak self] in
        repeat {
            self?.audioRecorder.updateMeters()
            self?.averagePower = self?.audioRecorder.averagePowerForChannel(0)
            self?.peakPower = self?.audioRecorder.peakPowerForChannel(0)

            self?.performSelectorOnMainThread(#selector(DictaphoneViewController.updateMeter), withObject: self, waitUntilDone: false)
            NSThread.sleepForTimeInterval(0.05)//20 FPS
        }
            while (someCondition)
        })

在里面做仪表 UI 的事情

func updateMeter(){//UI stuff here}


0
投票

其实很简单, 您在缓冲区中获得的值有正有负(这就是波的工作原理),因此如果您对这些值求平均值,它将给您一个接近 0 的值。

因此,您要做的就是将所有值设为正值(使用 Math.abs() 函数),然后求平均值,它将返回声级。

希望这有帮助;)


0
投票

您还可以使用 ReactiveCocoa 并利用

interval:onScheduler:
:

返回一个信号,该信号在调度程序上的每个时间间隔发送当前日期/时间。

使用单个音频通道:

  @weakify(self)
  RACDisposable *metersDisposable = [[RACSignal // make sure you dispose it eventually
      interval:0.1
      onScheduler:[RACScheduler scheduler]]
      subscribeNext:^(NSDate *) {
        @strongify(self)
        [recorder updateMeters];
        auto averagePower = [recorder averagePowerForChannel:0];
        auto peakPower = [recorder peakPowerForChannel:0];
        // Inform the delegate or make other use of averagePower and peakPower
      }];

-5
投票

我在以下链接中找到了答案。

AVPlayer 的AVMeter

虽然它需要大量的定制,但我觉得我能够做到。

© www.soinside.com 2019 - 2024. All rights reserved.