Android麦克风问题

时间:2010-08-01 23:03:08

标签: android audio microphone

是否可以(实时)检测是否有人吹进麦克风? 感谢

2 个答案:

答案 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

thema