Actualmente estoy creando una aplicación que calcula la magnitud a una frecuencia predefinida (16780Hz) en tiempo real desde el micrófono del iPhone.Core-audio, el algoritmo Goertzel no funciona
Tengo los datos de sonido en un búfer e intento procesarlos usando Goertzel, un algoritmo diseñado para esta tarea. Goertzel info. Aquí es donde comienza el problema.
El algoritmo responde con resultados muy positivos cuando se graba un sonido de una frecuencia mucho más baja (5000 Hz) que la definida (16780Hz). De hecho, el resultado es mucho más positivo que el producido cuando se graba un sonido de la frecuencia correcta.
Aquí es mi implementación de Goertzel:
double goertzel(unsigned short *sample, int sampleRate, double Freq, int len)
{
double realW = 2.0 * cos(2.0 * M_PI * Freq/sampleRate);
double imagW = 2.0 * sin(2.0 * M_PI * Freq/sampleRate);
double d1 = 0;
double d2 = 0;
int z;
double y;
for (int i = 0; i < len; i++) {
y=(double)(signed short)sample[i] +realW * d1 - d2;
d2 = d1;
d1 = y;
}
double rR = 0.5 * realW *d1-d2;
double rI = 0.5 * imagW *d1-d2;
return (sqrt(pow(rR, 2)+pow(rI,2)))/len;
} /* end function goertzel */
Aquí es cómo puedo recuperar el audio si es en absoluto relevante
-(void)startListeningWithFrequency:(float)frequency;
{
OSStatus status;
//AudioComponentInstance audioUnit;
AudioComponentDescription desc;
desc.componentType = kAudioUnitType_Output;
desc.componentSubType = kAudioUnitSubType_RemoteIO;
desc.componentFlags = 0;
desc.componentFlagsMask = 0;
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
AudioComponent inputComponent = AudioComponentFindNext(NULL, &desc);
status = AudioComponentInstanceNew(inputComponent, &audioUnit);
checkStatus(status);
UInt32 flag = 1;
status = AudioUnitSetProperty(audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input,kInputBus, &flag, sizeof(flag));
checkStatus(status);
AudioStreamBasicDescription audioFormat;
audioFormat.mSampleRate = 44100.00;//44100.00;
audioFormat.mFormatID = kAudioFormatLinearPCM;
audioFormat.mFormatFlags = kAudioFormatFlagIsPacked | kAudioFormatFlagIsSignedInteger;
audioFormat.mFramesPerPacket = 1;
audioFormat.mChannelsPerFrame = 1;
audioFormat.mBitsPerChannel = 16;
// float
audioFormat.mBytesPerPacket = 2;
audioFormat.mBytesPerFrame = 2;
status = AudioUnitSetProperty(audioUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output,
kInputBus,
&audioFormat,
sizeof(audioFormat));
checkStatus(status);
//status = AudioUnitSetProperty(audioUnit,
// kAudioUnitProperty_StreamFormat,
// kAudioUnitScope_Input,
// kOutputBus,
// &audioFormat,
// sizeof(audioFormat));
checkStatus(status);
AURenderCallbackStruct callbackStruct;
callbackStruct.inputProc = recordingCallback;
callbackStruct.inputProcRefCon = self;
status = AudioUnitSetProperty(audioUnit,
kAudioOutputUnitProperty_SetInputCallback,
kAudioUnitScope_Global,
kInputBus, &callbackStruct, sizeof(callbackStruct));
checkStatus(status);
/* UInt32 shouldAllocateBuffer = 1;
AudioUnitSetProperty(audioUnit, kAudioUnitProperty_ShouldAllocateBuffer, kAudioUnitScope_Global, 1, &shouldAllocateBuffer, sizeof(shouldAllocateBuffer));
*/
status = AudioOutputUnitStart(audioUnit);
}
static OSStatus recordingCallback(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData) {
AudioBuffer buffer;
buffer.mNumberChannels = 1;
buffer.mDataByteSize = inNumberFrames * 2;
//NSLog(@"%d",inNumberFrames);
buffer.mData = malloc(inNumberFrames * 2);
// Put buffer in a AudioBufferList
AudioBufferList bufferList;
bufferList.mNumberBuffers = 1;
bufferList.mBuffers[0] = buffer;
OSStatus status;
status = AudioUnitRender(audioUnit,
ioActionFlags,
inTimeStamp,
inBusNumber,
inNumberFrames,
&bufferList);
checkStatus(status);
//double g = calculateGoertzel((const char *)(&bufferList)->mBuffers[0].mData,16789.0,96000.0);
UInt16 *q = (UInt16 *)(&bufferList)->mBuffers[0].mData;
int N = sizeof(q)/sizeof(UInt16);
double Qr,Qi;
double theta = 2.0*M_PI*16780/44100;
double g = goertzel(q,44100,16780,N);
NSLog(@"goertzel:%f", g);
}
Esto devuelve números en los cientos de frecuencia mucho más bajos que 16780Hz , y para frecuencias de 16780Hz devuelve números mucho más pequeños.
Estoy muy frustrado y la ayuda sería muy apreciada.
Lamentablemente, ha sido únicamente ondas sinusoidales que he estado probando con :(. ¿Alguna otra sugerencia? Intenté doblar la velocidad de muestreo en vano – 123hal321
Duplicar la frecuencia de muestreo podría no funcionar en el iPhone, si no puede muestrear tan alto. Tendría que volver a leer la frecuencia de muestreo para asegurarse de que fue aceptada. Además, es posible que tenga que establecer la frecuencia de muestreo en las propiedades de la sesión primero, para evitar que silencie silenciosamente en lo que cree que debería ser la frecuencia de muestreo nativa: – Vagrant
float64 preferredSampleRate = audioFormat-> mSampleRate; XThrowIfError (AudioSessionSetProperty (kAudioSessionProperty_PreferredHardwareSampleRate, sizeof (preferredSampleRate), y preferredSampleRate)); – Vagrant