2012-04-09 17 views
5

Soy nuevo en iOS y sus fundamentos C, pero no en la programación en general. Mi dilema es esto. Estoy implementando un efecto de eco en una aplicación compleja basada en AudioUnits. La aplicación necesita reverberación, eco y compresión, entre otras cosas. Sin embargo, el eco solo funciona bien cuando utilizo un formato particular AudioStreamBasicDescription para las muestras de audio generadas en mi aplicación. Sin embargo, este formato no funciona con las otras AudioUnits. Si bien hay otras formas de resolver este problema, la fijación de los bits en el algoritmo de eco podría ser el enfoque más directo.Muestras de audio de desplazamiento de bits de Float32 a SInt16 dan como resultado recorte grave

El * * AudioStreamBasicDescription que trabaja con eco tiene una mFormatFlag de: kAudioFormatFlagsAudioUnitCanonical; Se específicos son:

AudioUnit Stream Format (ECHO works, NO AUDIO UNITS) 
Sample Rate:    44100 
Format ID:     lpcm 
Format Flags:    3116 = kAudioFormatFlagsAudioUnitCanonical 
Bytes per Packet:    4 
Frames per Packet:   1 
Bytes per Frame:    4 
Channels per Frame:   2 
Bits per Channel:   32 
Set ASBD on input 
Set ASBD on output 
au SampleRate rate: 0.000000, 2 channels, 12 formatflags, 1819304813 mFormatID, 16 bits per channel 

El formato de flujo que funciona con AudioUnits es el mismo excepto por el mFormatFlag: kAudioFormatFlagIsFloat | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked | kAudioFormatFlagIsNonInterleaved - Sus características específicas son:

AudioUnit Stream Format (NO ECHO, AUDIO UNITS WORK) 
Sample Rate:    44100 
Format ID:     lpcm 
Format Flags:    41 
Bytes per Packet:    4 
Frames per Packet:   1 
Bytes per Frame:    4 
Channels per Frame:   2 
Bits per Channel:   32 
Set ASBD on input 
Set ASBD on output 
au SampleRate rate: 44100.000000, 2 channels, 41 formatflags, 1819304813 mFormatID, 32 bits per channel 

Con el fin de crear el efecto de eco que utiliza dos funciones que desplazamiento de bit de datos de ejemplo en Sint16 espacio, y la espalda. Como dije, esto funciona para el formato kAudioFormatFlagsAudioUnitCanonical, pero no para el otro. Cuando falla, los sonidos son recortados y distorsionados, pero están allí. Creo que esto indica que la diferencia entre estos dos formatos es cómo se organizan los datos en el Float32.

// convert sample vector from fixed point 8.24 to SInt16 
void fixedPointToSInt16(SInt32 * source, SInt16 * target, int length) { 
    int i; 
    for(i = 0;i < length; i++) { 
     target[i] = (SInt16) (source[i] >> 9); 
     //target[i] *= 0.003; 

    } 
} 

* Como se puede ver He intentado modificar la amplitud de las muestras para deshacerse del recorte - claramente que no funcionó.

// convert sample vector from SInt16 to fixed point 8.24 
void SInt16ToFixedPoint(SInt16 * source, SInt32 * target, int length) { 
    int i; 
    for(i = 0;i < length; i++) { 
     target[i] = (SInt32) (source[i] << 9); 
     if(source[i] < 0) { 
      target[i] |= 0xFF000000; 
     } 
     else { 
      target[i] &= 0x00FFFFFF; 
     } 
    } 
} 

Si puedo determinar la diferencia entre kAudioFormatFlagIsFloat | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked | kAudioFormatFlagIsNonInterleaved, entonces puedo modificar los métodos anteriores en consecuencia. Pero no estoy seguro de cómo resolver eso. La documentación en CoreAudio es enigmática, pero por lo que he leído allí, y extraído del archivo CoreAudioTypes.h, ambos mFormatFlag (s) se refieren al mismo formato de punto fijo 8.24. Claramente, algo es diferente, pero no puedo entender qué.

Gracias por leer esta larga pregunta y gracias de antemano por cualquier información que pueda proporcionar.

+0

De alguna manera sospecho que está experimentando distorsión en lugar de recorte, muy probablemente causado por cambio de signo. ¿Puedes publicar un archivo WAV generado por tu algoritmo aquí para que podamos ver lo que está pasando? –

+0

Mi aplicación reproduce sonidos como un instrumento musical. No crea ni almacena archivos de onda. Pero creo que tienes razón. Básicamente, si supiera qué formato * kAudioFormatFlagIsFloat | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked | kAudioFormatFlagIsNonInterleaved * representa, podría deducir cómo funciona ese formato dentro y fuera de SInt16. En este momento, todo lo que sé es que no es FixedPoint 8.24 –

Respuesta

11

kAudioFormatFlagIsFloat significa que el búfer contiene valores de coma flotante. Si mBitsPerChannel es 32, entonces está tratando con float datos (también llamado Float32), y si es 64 está tratando con double datos.

kAudioFormatFlagsNativeEndian se refiere al hecho de que los datos en el búfer coinciden con la endianidad del procesador, por lo que no tiene que preocuparse por el intercambio de bytes.

kAudioFormatFlagIsPacked significa que cada bit en los datos es significativo.Por ejemplo, si almacena datos de audio de 24 bits en 32 bits, este indicador no se establecerá.

kAudioFormatFlagIsNonInterleaved significa que cada memoria intermedia individual se compone de un canal de datos. Es común que los datos de audio se intercalen, con las muestras alternando entre los canales L y R: LRLRLRLR. Para las aplicaciones DSP a menudo es más fácil desentrelazar los datos y trabajar en un canal a la vez.

Creo que en su caso el error es que está tratando datos de coma flotante como punto fijo. Los datos flotantes generalmente se escalan al intervalo [-1, +1). Para convertir float en SInt16, necesita multiplicar cada muestra por el valor máximo de 16 bits (1u << 15, 32768) y luego ajustar el intervalo [-32768, 32767].

+0

Gracias por una respuesta tan informativa. De hecho, confirma mucho de lo que he leído. Sin embargo, cuando he intentado convertir el búfer AudioSample en Float32 * en mi devolución de llamada, recibo una advertencia. inSamplesLeft = (Float32 *) ioData-> mBuffers [0] .mData; Tipos de punteros incompatibles asignados a 'AudioUnitSampleType *' (también conocido como 'long *') de 'Float32 *' (aka Float32) –

+0

Sin ver el código es difícil saber exactamente lo que está sucediendo, pero generalmente no se puede transmitir desde un 'largo * 'a' flotar * 'y esperar obtener resultados correctos. – sbooth

+0

Tomé otra puñalada y solucioné este problema y después de volver a leer tu respuesta, hice un buen progreso. Todavía tengo mucha distorsión, pero creo que esto puede deberse al método de trival con el que estoy convirtiendo Float32 en SInt16. ¿Podrías exponer la sintaxis de 16 bit bit-shift que escribiste? Todavía no soy un programador de C y no estoy seguro de cómo implementarlo: (1u << 15, 32768) –

Cuestiones relacionadas