linux自动读取麦克风,检测用户向麦克吹气
如果幾年前你告訴我人們可以通過晃動手機或向麥克吹氣使手機有所動作,我一定會大笑不止。但現在這已經是事實了。
檢查晃動動作是很直接的,所有這些在3.0“motion event”(動作事件)中都有介紹。
檢測向麥克吹氣困難一點。本教程將建立一個簡單的單視圖程序,它將在用戶向麥克吹氣時向控制臺寫入記錄信息。
源代碼/Github
可從GitHub獲得。 你可以克隆軟件倉庫或直接下載。
概述
檢測向麥克吹氣的工作可分為兩部分:(1) 獲取麥克輸入 (2) “聽”吹氣的聲音。
我們將使用3.0中新的AVAudioRecorder類來捕獲麥克輸入。使用AVAudioRecorder可以讓我們使用Objective-C,而不需像其他方法一樣使用C。
向麥克吹氣的噪聲/聲音是由低頻聲音組成的。我們將使用 來降低來自麥克的高頻聲音;當濾波信號的電平等級突然增大時,我們就知道有人向麥克吹氣了。
創建項目
啟動Xcode創建一個View-Based iPhone程序,叫MicBlow:
使用Xcode菜單File > New Project… 創建一個新項目
從 iPhone OS > Application 選擇View-based Applications然后按Choose…
將項目命名為MicBlow,按Save
添加AVFoundation Framework
為使用AVAudioRecorder類,我們需要向項目添加AVFoundation framework:
在項目Groups & Files面板上展開Targets
按Control-點擊或右擊MicBlow
選擇Add > Existing Frameworks…
按下Linked Libraries左下角的+按鈕
選擇AVFoundation.framework并按下Add
AVFoundation.framework出現在Linked Libraries下。關閉窗口
然后,我們在view controller接口中引入AVFoundation頭文件并設置AVAudioRecorder實例變量:
展開項目Groups & Files面板下的MicBlow
展開Classes文件夾
選擇MicBlowViewController.h進行編輯
更新文件。修改見如下2,3,7行:
#import
#import
#import
@interface MicBlowViewController : UIViewController
{
AVAudioRecorder *recorder;
}
@end
引入CoreAudioTypes頭文件實際上是下一步需要的工作。我們還需要在設置AVAudioRecorder定義更多的常量。
獲取麥克輸入
我們在ViewDidLoad進行設置并開始“聽“取麥克:
解除樣本ViewDidLoad方法注釋
更新如下。見4-18行:
- (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]);
}
AVAudioRecorder的主要功能就像前名字暗示的那樣進行音頻錄制。其第二個功能是提供音頻電平等級信息。所以,這里我們只是將音頻輸入指向/dev/null位 – 我沒有找到任何文檔支持我的觀點,但一致意見是就像在任何Unix下一樣,/dev/null將打開音頻計量表。
注意: 如果你準備采用上述代碼,記住在設置meteringEnabled屬性或音頻計量開始工作前,要調用prepareToRecord (或者record)。
記住在dealloc中釋放recorder。 見第三行:
- (void)dealloc
{
[recorder release];
[super dealloc];
}
音頻采樣
我們將使用定時器每秒30次檢查一次音頻電平等級。NSTimer實例變量以及其回調函數在MicBlowViewController.h中定義。修改見7,10行:
#import
#import
#import
@interface MicBlowViewController : UIViewController {
AVAudioRecorder *recorder;
NSTimer *levelTimer;
}
- (void)levelTimerCallback:(NSTimer *)timer;
@end
更新.m文件中ViewDidLoad啟用定時器。修改見16,17行:
- (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]);
}
現在,我們只是直接進行音頻采樣而未使用濾波。在.m文件中添加levelTimerCallback:
- (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
#import
#import
@interface MicBlowViewController : UIViewController {
AVAudioRecorder *recorder;
NSTimer *levelTimer;
double lowPassResults;
}
替換levelTimerCallback:方法來實現此算法:
- (void)levelTimerCallback:(NSTimer *)timer {
[recorder updateMeters];
const double ALPHA = 0.05;
double peakPowerForChannel = (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);
}
我們在每次定時器回調時重新計算一次lowPassResults變量。為方便,我們將其轉換為0-1,0代表完全安靜,1代表最大音量。
但低通濾波值超過一定門檻范圍時,我們就可以判斷有人向麥克吹了氣。門檻范圍值的設定是一種技巧。它設定太小,則太容易被觸發,如果設定太高,則必須長時間用盡力氣吹氣才會有效果。在我們的程序中,我將其設為0.95。我們要改變一下log的條件,見第6,7行:
- (void)listenForBlow:(NSTimer *)timer {
[recorder updateMeters];
const double ALPHA = 0.05;
double peakPowerForChannel = (10, (0.05 * [recorder peakPowerForChannel:0]));
lowPassResults = ALPHA * peakPowerForChannel + (1.0 - ALPHA) * lowPassResults;
if (lowPassResults > 0.95)
NSLog(@"Mic blow detected");
}
好了!你可以檢測是否有人吹了麥克了。
鳴謝及說明
此方法在大部分情況下工作良好,但并非任何情況都正確。我是在飛行中寫的這篇文章,飛機的引擎聲經常觸發我的算法。類似地,在一個噪聲很大的房間內足夠多的低頻聲也會觸發我的算法。
算法節選自。上面帖子使用的是庫來進行音頻電平檢測。SCListener比AVAudioRecorder更早出現;它是用來隱藏C語言細節的獲取音頻電平代碼。而無疑AVAudioRecorder更容易使用。
最后,此方法確實可以在模擬器中正常工作。但你要找到Mac上的麥克。出乎我的意料,第一代Macbook上的麥克處于攝像頭左方的小孔中。
總結
以上是生活随笔為你收集整理的linux自动读取麦克风,检测用户向麦克吹气的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php 简易 blog,PHP实现简易b
- 下一篇: ArcPy常用类介绍