2009-04-28 5 views
18

J'essaie de détecter quand l'utilisateur souffle dans le micro d'un iPhone. En ce moment je suis en utilisant la classe SCListener de Stephen Celis appelerDétection du souffle sur le microphone de l'iPhone?

if ([[SCListener sharedListener] peakPower] > 0.99) 

dans un NSTimer. Cependant, cela revient vrai parfois quand je ne souffle pas. Quelqu'un at-il un code d'échantillon pour vérifier si l'utilisateur souffle dans le micro?

+4

Peut-être que le vent souffle. :) Désolé, cette question m'a fait rire. –

+0

Hah, nah. Même lorsque je serais à l'intérieur, le simple fait de tapoter sur l'écran provoquerait le déclenchement de la fonction –

Répondre

25

Je recommanderais d'abord le signal d'alimentation low-pass filtering. Il y aura toujours une quantité de bruit transitoire qui perturbera les lectures instantanées; le filtrage passe-bas aide à atténuer cela. Un agréable et facile filtre passe-bas serait quelque chose comme ceci:

// Make this a global variable, or a member of your class: 
double micPower = 0.0; 
// Tweak this value to your liking (must be between 0 and 1) 
const double ALPHA = 0.05; 

// Do this every 'tick' of your application (e.g. every 1/30 of a second) 
double instantaneousPower = [[SCListener sharedListener] peakPower]; 

// This is the key line in computing the low-pass filtered value 
micPower = ALPHA * instantaneousPower + (1.0 - ALPHA) * micPower; 

if(micPower > THRESHOLD) // 0.99, in your example 
    // User is blowing on the microphone 
+0

pouvez-vous arrêter d'enregistrer si les niveaux de volume dépassent également le seuil? ce qui signifie si avoir une application VoIP, et ne veulent pas une sirène de camion de pompier à rugir au cours de la conversation puis-je mettre en pause le micro une fois que le seuil est dépassé? –

11

d'utilisation retour comme lowPassResults est plus grand que 0.55. Cela fonctionne très bien:

-(void)readyToBlow1 { 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.01 target: self selector: @selector(levelTimerCallback1:) userInfo: nil repeats: YES]; 
    } else 
     NSLog(@"%@",[error description]); 
} 

-(void)levelTimerCallback1:(NSTimer *)timer { [recorder updateMeters]; 
    const double ALPHA = 0.05; 
    double peakPowerForChannel = pow(10, (0.05 * [recorder peakPowerForChannel:0])); 
    double lowPassResults = ALPHA * peakPowerForChannel + (1.0 - ALPHA) * lowPassResults; 
    if (lowPassResults > 0.55) { 
     lowPassResults = 0.0; 
     [self invalidateTimers]; 
     NextPhase *objNextView =[[NextPhase alloc]init]; 
     [UIView transitionFromView:self.view 
         toView:objNextView.view 
         duration:2.0 
         options:UIViewAnimationOptionTransitionCurlUp 
         completion:^(BOOL finished) {} 
     ]; 
     [self.navigationController pushViewController:objNextView animated:NO]; 
    **return;** 
    } 
} 
+0

Où configurez-vous les lowPassResults dans le code? – user513790

+0

maintenant vous pouvez voir lowPassResults. C'était juste mal aligné. désolé :) –

+0

+1 pour une bonne réponse shashank –

13

lorsqu'il est exécuté sur iPhone, vous devez ajouter le code suivant après [enregistreur prepareToRecorder]

[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil]; 
[[AVAudioSession sharedInstance] setActive:YES error:nil]; 
+3

Cela a bien fonctionné pour moi .. – slaveCoder

+2

Je cherchais cette information pendant 3 heures. Ça fonctionne maintenant!. – bpolat

+0

oh mon dieu merci beaucoup –

2

Essayez cette Il fonctionne très bien pour moi. Merci @jinhua liao

- (void)viewDidLoad { 
    [super viewDidLoad]; 

lowPassResults = 0.0; 
[self readyToBlow1]; 

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]; 
    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil]; 
    [[AVAudioSession sharedInstance] setActive:YES error:nil]; 
    recorder.meteringEnabled = YES; 
    [recorder record]; 
    levelTimer = [NSTimer scheduledTimerWithTimeInterval: 0.03 target: self selector: @selector(levelTimerCallback:) userInfo: nil repeats: YES]; 
} else 
    NSLog([error description]); 

} 

- (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(@"lowpassResult is %f",lowPassResults); 
if (lowPassResults > 0.95){ 
    NSLog(@"Mic blow detected"); 
    [levelTimer invalidate]; 
} 
} 
Questions connexes