Domanda

Sono consapevole che ci sono diversi thread con lo stesso problema, ma non sono stato in grado di far funzionare la loro soluzione. Ho finito per creare questa classe:

Microcontroller.H

#import Foundation/Foundation.h>

#import <AVFoundation/AVFoundation.h>
#import <CoreAudio/CoreAudioTypes.h>

#import <UIKit/UIKit.h>

@interface MicroController : UIView < UITextFieldDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate, AVAudioSessionDelegate > {
    AVAudioRecorder *recorder;
    NSTimer *levelTimer;
    double lowPassResults;
}

- (void)levelTimerCallback:(NSTimer *)timer;
@end

Microcontroller.mm

#import "MicroController.h"


@implementation MicroController

- (id)init
{
    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;

        if ([recorder prepareToRecord] == YES){
            [recorder record];
        }else {
            int errorCode = CFSwapInt32HostToBig ([error code]); 
            NSLog(@"Error: %@ [%4.4s])" , [error localizedDescription], (char*)&errorCode); 

        }

        levelTimer = [NSTimer scheduledTimerWithTimeInterval: 0.03 target: self selector: @selector(levelTimerCallback:) userInfo: nil repeats: YES];
    } else
        NSLog([error description]); 

    // input 'level' is in meter.mAveragePower

    return self;
}

- (void)levelTimerCallback:(NSTimer *)timer {
    [recorder updateMeters];

    const double ALPHA = 1.0; // 0.05f
    double peakPowerForChannel = pow(10, (0.05 * [recorder peakPowerForChannel:0]));
    lowPassResults = ALPHA * peakPowerForChannel + (1.0 - ALPHA) * lowPassResults;  

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


    [recorder updateMeters];
    NSLog(@"Average input: %f Peak input: %f", [recorder averagePowerForChannel:0], [recorder peakPowerForChannel:0]);

}
    - (void)viewDidLoad {
        [super viewDidLoad];

        NSLog(@"initiated");

        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]);

    }


    - (void)dealloc {
        [levelTimer release];
        [recorder release];
        [super dealloc];
    }
    @end

Ma non riesco a far funzionare il microfono. Ricevo solo questo output e il microfono non risponde mai:

Input medio: -120.000000 Input di picco: -120.000000

Qualche idea su cosa può essere sbagliato?

Grazie per l'aiuto !

È stato utile?

Soluzione

Beh, non pensavo importante menzionare che stavo lavorando con Unity, ed era il colpevole.

Unità modifica alcune impostazioni, quindi è importante farlo quando si carica il tuo ViewController:

[[AVAudioSession sharedInstance]
 setCategory: AVAudioSessionCategoryPlayAndRecord
 error: &setCategoryError];
if (setCategoryError) {
    NSLog([setCategoryError description]);
}

Altrimenti un audio ordinatore perfettamente scritto non funzionerà correttamente. E questo è stato ... Problema risolto!

Questo bug è stato un dolore da rilevare, spero che questo messaggio aiuti chiunque altro nella stessa situazione.

Altri suggerimenti

OK, ecco il risoluzione: file "miccontroller.m"

#import "MicController.h"


static MicController *sharedListener = nil;


@implementation MicController


+ (MicController *)sharedListener {
    @synchronized(self) {
        if (sharedListener == nil)
            [[self alloc] init];
    }

    return sharedListener;
}

- (void)dealloc {
    //[sharedListener stop];
    //[levelTimer release];
    [recorder release];
    [super dealloc];
}

#pragma mark -
#pragma mark Listening

- (void)listen {

    [[AVAudioSession sharedInstance]
     setCategory: AVAudioSessionCategoryPlayAndRecord
     error: nil];




    NSURL *url = [NSURL fileURLWithPath:@"/dev/null"];

    //kAudioFormatAppleIMA4
    //kAudioFormatMPEG4AAC
    /*
    NSMutableDictionary *settings = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                     [NSNumber numberWithFloat: 44100.0],                 AVSampleRateKey,
                                     [NSNumber numberWithInt: kAudioFormatAppleLossless], AVFormatIDKey,
                                     [NSNumber numberWithInt: 1],                         AVNumberOfChannelsKey,
                                     [NSNumber numberWithInt: AVAudioQualityMax],         AVEncoderAudioQualityKey,
                                     nil];
    */

    NSDictionary *settings = [[NSDictionary alloc] initWithObjectsAndKeys:
                              [NSNumber numberWithFloat: 44100.0],                 AVSampleRateKey,
                              [NSNumber numberWithInt: kAudioFormatAppleLossless], AVFormatIDKey,
                              [NSNumber numberWithInt: 2],                         AVNumberOfChannelsKey,
                              [NSNumber numberWithInt: AVAudioQualityMax],         AVEncoderAudioQualityKey,
                              nil];
                              /*
                              [NSNumber numberWithFloat: 44100.0],                  AVSampleRateKey,
                              [NSNumber numberWithInt: kAudioFormatMPEG4AAC],      AVFormatIDKey,
                              [NSNumber numberWithInt: 2],                          AVNumberOfChannelsKey,
                              [NSNumber numberWithInt: AVAudioQualityMax],          AVEncoderAudioQualityKey,
                              [NSNumber numberWithInt:16],                          AVLinearPCMBitDepthKey,
                              [NSNumber numberWithBool:NO],                         AVLinearPCMIsBigEndianKey,
                              [NSNumber numberWithBool:NO],                         AVLinearPCMIsFloatKey,
                              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]); 
}
- (void)stop {
    [recorder release];
}

/*
- (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.95)
    //NSLog(@"Mic blow detected");
    NSLog(@"Average input: %f Peak input: %f Low pass results: %f", [recorder averagePowerForChannel:0], [recorder peakPowerForChannel:0], lowPassResults);


}
 */

#pragma mark -
#pragma mark Levels getters

- (Float32)averagePower {
    [recorder updateMeters];

    const double ALPHA = 0.7;
    double peakPowerForChannel = pow(10, (0.05 * [recorder averagePowerForChannel:0]));
    lowPassResults = ALPHA * peakPowerForChannel + (1.0 - ALPHA) * lowPassResults;
    return [recorder averagePowerForChannel:0];
    //return lowPassResults;
    //NSLog(@"Average input: %f Peak input: %f Low pass results: %f", [recorder averagePowerForChannel:0], [recorder peakPowerForChannel:0], lowPassResults);

}
- (Float32)peakPower {
    [recorder updateMeters];

    const double ALPHA = 0.7;
    double peakPowerForChannel = pow(10, (0.05 * [recorder peakPowerForChannel:0]));
    lowPassResults = ALPHA * peakPowerForChannel + (1.0 - ALPHA) * lowPassResults;
    return [recorder peakPowerForChannel:0];
    //return lowPassResults;
    //NSLog(@"Average input: %f Peak input: %f Low pass results: %f", [recorder averagePowerForChannel:0], [recorder peakPowerForChannel:0], lowPassResults);

}

#pragma mark -
#pragma mark Singleton Pattern

+ (id)allocWithZone:(NSZone *)zone {
    @synchronized(self) {
        if (sharedListener == nil) {
            sharedListener = [super allocWithZone:zone];
            return sharedListener;
        }
    }

    return nil;
}

- (id)copyWithZone:(NSZone *)zone {
    return self;
}

- (id)init {
    if ([super init] == nil)
        return nil;

    return self;
}

- (id)retain {
    return self;
}

- (unsigned)retainCount {
    return UINT_MAX;
}

- (void)release {
    // Do nothing.
}

- (id)autorelease {
    return self;
}


@end

Basta aggiungere il codice

 [[AVAudioSession sharedInstance]
     setCategory: AVAudioSessionCategoryPlayAndRecord
     error: nil];

sopra de void "- (void) ascolta {"

Grazie. Ciao

Ho lo stesso problema, nel caso in cui utilizzo un Applerator in titanio. Nel simulatore la classe funziona correttamente, ma nel dispositivo no, input medio = -120 ecco il codice:

//
//  MicController.h
//  Mic
//
//  Created by DekWilde on 10/26/11.
//  Copyright 2011 DekWilde. All rights reserved.
//

#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>
#import <CoreAudio/CoreAudioTypes.h>

@interface MicController : NSObject {
    AVAudioRecorder *recorder;
    //NSTimer *levelTimer;
    double lowPassResults;  
}

+ (MicController *)sharedListener;
- (void)listen;
- (void)stop;
//- (void)levelTimerCallback:(NSTimer *)timer;
- (Float32)averagePower;
- (Float32)peakPower;
@end

e MicController.M

    #import "MicController.h"


    static MicController *sharedListener = nil;


    @implementation MicController


    + (MicController *)sharedListener {
        @synchronized(self) {
            if (sharedListener == nil)
                [[self alloc] init];
        }

        return sharedListener;
    }

    - (void)dealloc {
        //[sharedListener stop];
        //[levelTimer release];
        [recorder release];
        [super dealloc];
    }

    #pragma mark -
    #pragma mark Listening

    - (void)listen {

        NSURL *url = [NSURL fileURLWithPath:@"/dev/null"];

        //kAudioFormatAppleIMA4
        //kAudioFormatMPEG4AAC
        /*
        NSMutableDictionary *settings = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                         [NSNumber numberWithFloat: 44100.0],                 AVSampleRateKey,
                                         [NSNumber numberWithInt: kAudioFormatAppleLossless], AVFormatIDKey,
                                         [NSNumber numberWithInt: 1],                         AVNumberOfChannelsKey,
                                         [NSNumber numberWithInt: AVAudioQualityMax],         AVEncoderAudioQualityKey,
                                         nil];
        */

        NSDictionary *settings = [[NSDictionary alloc] initWithObjectsAndKeys:
                                  [NSNumber numberWithFloat: 44100.0],                 AVSampleRateKey,
                                  [NSNumber numberWithInt: kAudioFormatAppleLossless], AVFormatIDKey,
                                  [NSNumber numberWithInt: 2],                         AVNumberOfChannelsKey,
                                  [NSNumber numberWithInt: AVAudioQualityMax],         AVEncoderAudioQualityKey,
                                  nil];
                                  /*
                                  [NSNumber numberWithFloat: 44100.0],                  AVSampleRateKey,
                                  [NSNumber numberWithInt: kAudioFormatMPEG4AAC],      AVFormatIDKey,
                                  [NSNumber numberWithInt: 2],                          AVNumberOfChannelsKey,
                                  [NSNumber numberWithInt: AVAudioQualityMax],          AVEncoderAudioQualityKey,
                                  [NSNumber numberWithInt:16],                          AVLinearPCMBitDepthKey,
                                  [NSNumber numberWithBool:NO],                         AVLinearPCMIsBigEndianKey,
                                  [NSNumber numberWithBool:NO],                         AVLinearPCMIsFloatKey,
                                  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]); 
    }
    - (void)stop {
        [recorder release];
    }

    /*
    - (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.95)
        //NSLog(@"Mic blow detected");
        NSLog(@"Average input: %f Peak input: %f Low pass results: %f", [recorder averagePowerForChannel:0], [recorder peakPowerForChannel:0], lowPassResults);


    }
     */

    #pragma mark -
    #pragma mark Levels getters

    - (Float32)averagePower {
        [recorder updateMeters];

        const double ALPHA = 0.7;
        double peakPowerForChannel = pow(10, (0.05 * [recorder averagePowerForChannel:0]));
        lowPassResults = ALPHA * peakPowerForChannel + (1.0 - ALPHA) * lowPassResults;
        return [recorder averagePowerForChannel:0];
        //return lowPassResults;
        //NSLog(@"Average input: %f Peak input: %f Low pass results: %f", [recorder averagePowerForChannel:0], [recorder peakPowerForChannel:0], lowPassResults);

    }
    - (Float32)peakPower {
        [recorder updateMeters];

        const double ALPHA = 0.7;
        double peakPowerForChannel = pow(10, (0.05 * [recorder peakPowerForChannel:0]));
        lowPassResults = ALPHA * peakPowerForChannel + (1.0 - ALPHA) * lowPassResults;
        return [recorder peakPowerForChannel:0];
        //return lowPassResults;
        //NSLog(@"Average input: %f Peak input: %f Low pass results: %f", [recorder averagePowerForChannel:0], [recorder peakPowerForChannel:0], lowPassResults);

    }

    #pragma mark -
    #pragma mark Singleton Pattern

    + (id)allocWithZone:(NSZone *)zone {
        @synchronized(self) {
            if (sharedListener == nil) {
                sharedListener = [super allocWithZone:zone];
                return sharedListener;
            }
        }

        return nil;
    }

    - (id)copyWithZone:(NSZone *)zone {
        return self;
    }

    - (id)init {
        if ([super init] == nil)
            return nil;

        return self;
    }

    - (id)retain {
        return self;
    }

    - (unsigned)retainCount {
        return UINT_MAX;
    }

    //- (void)release {
        // Do nothing.
    //}

    - (id)autorelease {
        return self;
    }


@end

La mia domanda è: dove devo mettere questo codice che hai pubblicato sulla soluzione di questo problema. . . Come posso risolvere questo problema?

Ora che Unity 3.5 ha aggiunto supporto per Microfono Input ti suggerisco di farlo in unità in modo da non dover mantenere il codice del cacao e semplificare il porto su Android/Web/nativo in futuro.

Ci sono già alcuni post utili al riguardo:

http://forum.unity3d.com/threads/123036-ios-microphone-input

http://forum.unity3d.com/threads/118215-blow-tection-(using-ios-microfono)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top