是否可以(实时)检测是否有人吹进麦克风? 感谢
答案 0 :(得分:2)
是的,
您可以使用AudioRecord类并分析返回的波形。
编辑:刚做了一些研究 - 对此有一点警告。事实证明,Android不能很好地实时处理音频处理。你会看到100毫秒的延迟。如果这对你的项目来说没问题(可能它听起来很棒)很棒,但只是需要注意的事情。答案 1 :(得分:0)
添加AVFoundation框架
为了使用SDK的AVAudioRecorder类,我们需要将AVFoundation框架添加到项目中:
接下来,我们将在视图控制器的接口文件中导入AVFoundation标头并设置AVAudioRecorder实例变量:
扩展群组中的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 { [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];
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表示完全安静,零表示最大输入。
不要忘记在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");
}
这example。