es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Obtener datos de decibelios de audio grabado en iOS y Objective C.

Estoy tratando de obtener los valores en decibeles de una muestra de audio grabada para hacer un gráfico de ondas y procesar sus picos.
Actualmente estoy utilizando AVAudioRecorder para grabar un archivo de audio y acceder a sus valores en dB utilizando [recorder averagePowerForChannel:0], llamado por un temporizador, sin embargo me enfrento a una limitación. Como necesito ser lo más preciso posible, he configurado el temporizador para que se repita cada 0.001 segundos, sin embargo, llamar a [recorder averagePowerForChannel:0] en cada tick produce el mismo valor varias veces. Parece que el grabador no es capaz de actualizar los valores por debajo de 0.2 segundos.
¿Cómo podría superar esta limitación?

Estas son las configuraciones del grabador:

NSDictionary *settings = [NSDictionary dictionaryWithObjectsAndKeys:
                                  [NSNumber numberWithFloat: 44000.0],                 AVSampleRateKey,
                                  [NSNumber numberWithInt: kAudioFormatAppleLossless], AVFormatIDKey,
                                  [NSNumber numberWithInt: 1],                         AVNumberOfChannelsKey,
                                  [NSNumber numberWithInt: AVAudioQualityMax],         AVEncoderAudioQualityKey,
                                  nil];

Luego configuro el grabador:

recorder = [[AVAudioRecorder alloc] initWithURL:url settings:settings error:&error];
[recorder setMeteringEnabled:YES];
[recorder prepareToRecord];
[recorder record];
timer = [NSTimer scheduledTimerWithTimeInterval:0.001f target:self selector: @selector(cllBack:) userInfo: nil repeats: YES];

Y en cllBack llamo a:

[recorder updateMeters];
[recorder averagePowerForChannel:0];

¡Gracias de antemano por cualquier ayuda!

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Un enfoque para superar la limitación de la actualización de valores por debajo de 0.2 segundos en AVAudioRecorder sería utilizar el framework AVCaptureSession en su lugar. Este framework ofrece un acceso más preciso a los datos de audio y puede muestrear los datos a una frecuencia más alta que AVAudioRecorder.

    Para comenzar, necesitarías crear una instancia de AVCaptureSession, agregar una entrada de audio y configurar el formato de audio correcto. Una vez que la sesión esté en funcionamiento, puedes capturar datos de audio utilizando AVCaptureAudioDataOutput.

    Aquí tienes un ejemplo de implementación:

    // Configurar la sesión de captura
    AVCaptureSession *captureSession = [[AVCaptureSession alloc] init];
    NSError *error = nil;
    
    // Agregar la entrada de audio
    AVCaptureDevice *audioDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
    AVCaptureDeviceInput *audioInput = [AVCaptureDeviceInput deviceInputWithDevice:audioDevice error:&error];
    if ([captureSession canAddInput:audioInput]) {
        [captureSession addInput:audioInput];
    }
    
    // Configurar la salida de audio
    AVCaptureAudioDataOutput *audioOutput = [[AVCaptureAudioDataOutput alloc] init];
    if ([captureSession canAddOutput:audioOutput]) {
        [captureSession addOutput:audioOutput];
    }
    
    // Configurar el formato de audio
    audioOutput.audioSettings = @{ AVFormatIDKey : @(kAudioFormatLinearPCM) };
    [audioOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()];
    
    // Iniciar la sesión de captura
    [captureSession startRunning];
    

    Después de iniciar la sesión de captura, se llamará al método de delegado captureOutput:didOutputSampleBuffer:fromConnection: de AVCaptureAudioDataOutput cada vez que haya nuevas muestras de audio disponibles. Luego, puedes procesar las muestras y calcular su amplitud utilizando el siguiente código:

    // Procesar el buffer de muestras de audio
    - (void)captureOutput:(AVCaptureOutput *)output didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {
        // Obtener los datos de audio
        CMBlockBufferRef blockBufferRef = CMSampleBufferGetDataBuffer(sampleBuffer);
        size_t length = CMBlockBufferGetDataLength(blockBufferRef);
        float *samples = (float *)CMBlockBufferGetDataPointer(blockBufferRef, 0, &length);
        int sampleCount = length / sizeof(float);
    
        // Calcular la amplitud
        float sum = 0.0;
        for (int i = 0; i < sampleCount; i++) {
            float sample = samples[i];
            sum += (sample * sample);
        }
        float amplitude = sqrt(sum / sampleCount);
    
        // Utilizar la amplitud para actualizar el gráfico o procesar los picos
        // ...
    }
    

    Este enfoque ofrece un acceso más preciso a los datos de audio y puede muestrear los datos a una frecuencia más alta que AVAudioRecorder. Sin embargo, es más complejo de configurar y requiere más potencia de procesamiento. Es importante probar y optimizar la implementación para tu caso de uso específico.

Comments are closed.