Detecting blowing on the iPhone microphone?

前端 未结 5 2093
再見小時候
再見小時候 2020-12-23 19:01

I am trying to detect when the user is blowing into the mic of an iPhone. Right now I am using the SCListener class from Stephen Celis to call

if ([[SCListen         


        
相关标签:
5条回答
  • 2020-12-23 19:39

    Use return as lowPassResults is bigger than 0.55. This is working fine:

    -(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 讨论(0)
  • 2020-12-23 19:52

    Try this It is working fine for me. Thanks @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];
    }
    }
    
    0 讨论(0)
  • 2020-12-23 19:53

    I would recommend low-pass filtering the power signal first. There is always going to be some amount of transient noise that will mess with instantaneous readings; low-pass filtering helps mitigate that. A nice and easy low-pass filter would be something like this:

    // 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 讨论(0)
  • 2020-12-23 19:53

    http://mobileorchard.com/tutorial-detecting-when-a-user-blows-into-the-mic/

    this tutorial works fine with simulator but its not working in iphone there is no response from iphone mic

    0 讨论(0)
  • 2020-12-23 19:56

    when run on iPhone, you should add the following code after [recorder prepareToRecorder]

    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
    [[AVAudioSession sharedInstance] setActive:YES error:nil];
    
    0 讨论(0)
提交回复
热议问题