Search code examples
audiococos2d-iphonerecorder

Detecting blow in the iPhone Mic with Cocos2D


I'm using Cocos2D and the system particles and I hope I wrote this correctly in English. I'm having problems to recognize sounds with the iPhone mic in certain way.

I have different sections in my application, in one of them I use the mic to detect if someone is "blowing air" into the mic. This part works fine at the beginning, but if you go to other section of the app that plays sound and later you return to this area and try to blow air, it won't work.

I debuged the code, and the levelTimeCallback is always working even if I'm not in this scene. I don't really know what's happening. I've stopped all sounds using

[[SimpleAudioEngine sharedEngine] stopBackgroundMusic];

Anyone knows what I'm doing wrong? BTW works perfectly in simulator, but not in iPhone.

The recorder is set in the onEnter method

-(void) onEnter {
     [super onEnter];
     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];
          NSLog(@"I'm in the recorder");

       } else

              NSLog(@"recorder error");

}

This is the levelTimerCallback method were the sound is "checked"

- (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;  

if (lowPassResults > 0.55)
{   
    NSLog(@"Mic blow detected");

    self.emitter = [[CCParticleExplosion alloc] initWithTotalParticles:5];
    [self addChild: emitter z:1];           
    emitter.texture = [[CCTextureCache sharedTextureCache] addImage: @"hoja.png"];      
    emitter.autoRemoveOnFinish = YES;

}
NSLog(@"Inside levelTimerCallback");}

Solution

  • Finally, after reading the Audio Session cookbook and different kind of post related I found the solution. Jus put this code block in the init method:

        UInt32 sessionCategory = kAudioSessionCategory_PlayAndRecord;
        UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
        AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(sessionCategory), &sessionCategory);
        AudioSessionSetProperty(kAudioSessionProperty_OverrideAudioRoute, sizeof(audioRouteOverride), &audioRouteOverride);
        AudioSessionSetActive(true);