2009-04-28 7 views
18

Estoy tratando de detectar cuando el usuario está soplando en el micrófono de un iPhone. Ahora estoy usando la clase de SCListener Stephen Celis llamar¿Detectando soplar en el micrófono de iPhone?

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

en un NSTimer. Sin embargo, esto se vuelve cierto algunas veces cuando no estoy soplando. ¿Alguien tiene un código de muestra para comprobar si el usuario está soplando en el micrófono?

+4

Quizás el viento esté soplando. :) Lo siento, esta pregunta me hizo reír. –

+0

Hah, nah. Incluso cuando estaría dentro, simplemente tocar en la pantalla provocaría que la función dispare –

Respuesta

25

Recomendaría low-pass filtering primero la señal de alimentación. Siempre habrá una cierta cantidad de ruido transitorio que interferirá con las lecturas instantáneas; el filtrado de paso bajo ayuda a mitigar eso. Un filtro de paso bajo agradable y fácil sería algo como esto:

// 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

¿puede dejar de grabar si los niveles de volumen también superan el umbral? lo que significa que si tienes una aplicación de VoIP, y no quieres que una sirena de camión de bomberos ruja sobre la conversación, ¿puedo detener el micrófono una vez que se supera el umbral? –

11

Uso devolver como lowPassResults es más grande que 0.55. Esto funciona 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

¿dónde configura lowPassResults en el código? – user513790

+0

ahora puede ver lowPassResults. Estaba desalineado. perdón :) –

+0

+1 por buena respuesta shashank –

13

cuando se ejecuta en el iPhone, se debe añadir el código siguiente después [prepareToRecorder grabador]

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

Esto funcionó bien para mí .. – slaveCoder

+2

Estuve buscando esta información durante 3 horas. ¡Ahora funciona!. – bpolat

+0

oh dios muchas gracias –

2

Prueba este Se está trabajando muy bien para mí. Gracias @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]; 
} 
} 
Cuestiones relacionadas