2012-05-08 25 views
5

Estoy tratando de comprender AVAudioPlayer y la medición de nivel de audio. Lo que tengo a continuación es un objeto "AudioPlayer" que está reproduciendo un sonido de audio corto. Ahora quiero dar salida a la potencia de este sonido (decibelios). De alguna manera, no creo que esté haciendo esto bien.Intentando comprender AVAudioPlayer y la medición de nivel de audio

La salida NSLog de esto es 0 -160,00 -160,00 1 -160,00 -160,00

Ahora bien, según Apple "Un valor de retorno de 0 dB indica la escala completa, o la potencia máxima; un retorno el valor de -160 dB indica la potencia mínima "Entonces, ¿esto significa que este sonido tiene la potencia mínima? No creo que esto sea cierto porque el fragmento de audio es bastante ruidoso. Creo que me falta algo aquí, cualquier aclaración sería apreciada.

Respuesta

3

Está actualizando y luego preguntando por el valor de los medidores casi inmediatamente después de que se inicia el sonido, que updateMeters probablemente se esté ejecutando unas pocas decenas de milisegundos después de enviar play. Entonces, si hay algún silencio al comienzo del clip, es muy posible que obtengas la lectura correcta. Debería intentar retrasar su inspección, y también puede necesitar enviar updateMetersdentro de el ciclo, justo antes de inspeccionar los valores.

En realidad, nunca obtendrá los valores del medidor para los canales> 0, porque pasa 0 sin importar el valor de i que esté en el circuito. Creo que tenía intención de hacer esto:

for (int currChan = 0; currChan < channels; currChan++) { 
    //Log the peak and average power 
    NSLog(@"%d %0.2f %0.2f", currChan, [audioPlayer peakPowerForChannel:currChan], [audioPlayer averagePowerForChannel:currChan]); 
} 
9

Existen varios problemas con su código: Jacques ya ha señalado la mayoría de ellos.

Debe llamar al [audioPlayer updateMeters]; cada vez antes de leer los valores. Probablemente sea mejor que crea una instancia de NSTimer.

Declara un iVar NSTimer *playerTimer; en tu clase @interface.

También no hace daño adoptar <AVAudioPlayerDelegate> en su clase por lo que podrá invalidar el temporizador después de que el jugador haya terminado de jugar.

A continuación, cambiar el código para:

audioPlayer.meteringEnabled = YES; 
audioPlayer.delegate = self; 

if (!playerTimer) 
{ 
    playerTimer = [NSTimer scheduledTimerWithTimeInterval:0.001 
        target:self selector:@selector(monitorAudioPlayer) 
       userInfo:nil 
       repeats:YES]; 
} 

[audioPlayer play]; 

Añadir estos dos métodos a su clase:

-(void) monitorAudioPlayer 
{ 
    [audioPlayer updateMeters]; 
    
    for (int i=0; i<audioPlayer.numberOfChannels; i++) 
    { 
     //Log the peak and average power 
        NSLog(@"%d %0.2f %0.2f", i, [audioPlayer peakPowerForChannel:i],[audioPlayer averagePowerForChannel:i]); 
    } 
} 

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag 
{ 
    NSLog (@"audioPlayerDidFinishPlaying:"); 
    [playerTimer invalidate]; 
    playerTimer = nil; 
} 

y usted debe ser bueno para ir.

Cuestiones relacionadas