1

是否可以(实时)检测是否有人对着麦克风吹气?谢谢

4

2 回答 2

3

是的,

您可以使用 AudioRecord 类并分析返回的波形。

编辑:刚刚做了一些研究——对此有一个警告。事实证明,Android 不能很好地实时处理音频。您会看到 100 毫秒的延迟。如果这对您的项目没问题(可能听起来不错),但只是需要注意的事情。

于 2011-07-07T08:43:13.393 回答
0

添加 AVFoundation 框架

为了使用 SDK 的 AVAudioRecorder 类,我们需要将 AVFoundation 框架添加到项目中:

接下来,我们将在视图控制器的接口文件中导入 AVFoundation 头文件并设置一个 AVAudioRecorder 实例变量:

在项目的 Groups & Files 面板中展开 MicBlow 项目分支 展开 Classes 文件夹 通过选择它来编辑 MicBlowViewController.h 更新文件:

#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
#import <CoreAudio/CoreAudioTypes.h>

@interface MicBlowViewController : UIViewController {
AVAudioRecorder *recorder;
}

从麦克风 中获取输入 取消注释样板 ViewDidLoad 方法 如下更新它。

- (void)viewDidLoad {
[super viewDidLoad];

NSURL *url = [NSURL fileURLWithPath:@"/dev/null"];

NSDictionary *settings = [NSDictionary dictionaryWithObjectsAndKeys:
    [NSNumber numberWithFloat: 44100.0],                 AVSampleRateKey,
    [NSNumber numberWithInt: kAudioFormatAppleLossless], AVFormatIDKey,
    [NSNumber numberWithInt: 1],                         AVNumberOfChannelsKey,
    [NSNumber numberWithInt: AVAudioQualityMax],         AVEncoderAudioQualityKey,
  nil];

NSError *error;

recorder = [[AVAudioRecorder alloc] initWithURL:url settings:settings error:&error];

if (recorder) {
    [recorder prepareToRecord];
    recorder.meteringEnabled = YES;
    [recorder record];
} else
    NSLog([error description]);

}

对音频电平进行采样 我们将使用一个计时器每秒检查大约 30 次音频电平。在 MicBlowViewController.h 中添加一个 NSTimer 实例变量及其回调方法。

#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
#import <CoreAudio/CoreAudioTypes.h>

@interface MicBlowViewController : UIViewController {
AVAudioRecorder *recorder;
NSTimer *levelTimer;
  }

  - (void)levelTimerCallback:(NSTimer *)timer;

  @end

更新 .m 文件的 ViewDidLoad 以启用计时器。- (void)viewDidLoad { [超级 viewDidLoad];

NSURL *url = [NSURL fileURLWithPath:@"/dev/null"];

NSDictionary *settings = [NSDictionary dictionaryWithObjectsAndKeys:
    [NSNumber numberWithFloat: 44100.0],                 AVSampleRateKey,
    [NSNumber numberWithInt: kAudioFormatAppleLossless], AVFormatIDKey,
    [NSNumber numberWithInt: 1],                         AVNumberOfChannelsKey,
    [NSNumber numberWithInt: AVAudioQualityMax],         AVEncoderAudioQualityKey,
  nil];

NSError *error;

recorder = [[AVAudioRecorder alloc] initWithURL:url settings:settings error:&error];

if (recorder) {
    [recorder prepareToRecord];
    recorder.meteringEnabled = YES;
    [recorder record];
    levelTimer = [NSTimer scheduledTimerWithTimeInterval: 0.03 target: self selector: @selector(levelTimerCallback:) userInfo: nil repeats: YES];
} else
    NSLog([error description]);

}

现在,我们将直接采样音频输入电平/不进行过滤。将 levelTimerCallback: 的实现添加到 .m 文件中:

  - (void)levelTimerCallback:(NSTimer *)timer {
[recorder updateMeters];
NSLog(@"Average input: %f Peak input: %f", [recorder averagePowerForChannel:0],     [recorder peakPowerForChannel:0]);

}

发送 updateMeters 消息会刷新平均功率计和峰值功率计。仪表使用对数刻度,-160 表示完全安静,0 表示最大输入。

不要忘记在 dealloc 中释放计时器。更改为粗体:

- (void)dealloc {
[levelTimer release];
[recorder release];
[super dealloc];
 }

聆听吹响的声音 如概述中所述,我们将使用低通滤波器来减少高频声音对电平的贡献。该算法创建了一组包含过去样本输入的运行结果;我们需要一个实例变量来保存结果。更新 .h 文件。

#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
#import <CoreAudio/CoreAudioTypes.h>

@interface MicBlowViewController : UIViewController {
AVAudioRecorder *recorder;
NSTimer *levelTimer;
double lowPassResults;
}

通过将 levelTimerCallback: 方法替换为:

- (void)levelTimerCallback:(NSTimer *)timer {
[recorder updateMeters];

const double ALPHA = 0.05;
double peakPowerForChannel = pow(10, (0.05 * [recorder peakPowerForChannel:0]));
lowPassResults = ALPHA * peakPowerForChannel + (1.0 - ALPHA) * lowPassResults;  

NSLog(@"Average input: %f Peak input: %f Low pass results: %f", [recorder     averagePowerForChannel:0], [recorder peakPowerForChannel:0], lowPassResults);
 }

对于我的应用程序的需要,0.95 有效。我们将用一个简单的条件替换日志行:

 - (void)listenForBlow:(NSTimer *)timer {
[recorder updateMeters];

const double ALPHA = 0.05;
double peakPowerForChannel = pow(10, (0.05 * [recorder peakPowerForChannel:0]));
lowPassResults = ALPHA * peakPowerForChannel + (1.0 - ALPHA) * lowPassResults;

if (lowPassResults > 0.95)
    NSLog(@"Mic blow detected");
}

这个例子

主题

于 2013-11-21T16:38:27.827 回答