Ich entwickle eine Bassgitarre Tonhöhenerkennung App auf iphone 3GS. Ich habe festgestellt, dass ich mit RemoteIO keine Tondaten unter 150 Hz erhalten kann. Die Bassgitarre kann jedoch Töne unter 50 Hz erzeugen. Laut dem Bericht "iPhone 4 Headset Input Frequency Response", http://blog.faberacoustical.com/2010/iphone/iphone-4-audio-and-frequency-response-limitations/ Unterhalb von 150 Hz gibt es einen starken Abfall.
Hier wird gezeigt, wie ich die AudioUnit eingerichtet habe.
// set audio unit
{
// create AudioUnit
{
AudioComponentDescription desc;
desc.componentType = kAudioUnitType_Output;
desc.componentSubType = kAudioUnitSubType_RemoteIO;
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
desc.componentFlags = 0;
desc.componentFlagsMask = 0;
AudioComponent comp = AudioComponentFindNext(NULL, &desc);
OSAssert(AudioComponentInstanceNew(comp, &m_AudioUnit));
}
//enable input on the remote I/O unit (output is default enabled, but input is not)
{
UInt32 one = 1;
OSAssert(AudioUnitSetProperty(m_AudioUnit, kAudioOutputUnitProperty_EnableIO,
kAudioUnitScope_Input, 1, &one, sizeof(one)));
}
//set render callback function
{
AURenderCallbackStruct callbackInfo;
callbackInfo.inputProc=staticPerformThru;
callbackInfo.inputProcRefCon=this;
OSAssert(AudioUnitSetProperty(m_AudioUnit,
kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Input,
0, &callbackInfo, sizeof(callbackInfo)));
}
//set in/output format
{
CAStreamBasicDescription outFormat;
outFormat.SetAUCanonical(channels, false);
outFormat.mSampleRate = sampleRate;
OSAssert(AudioUnitSetProperty(m_AudioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &outFormat, sizeof(outFormat)));
OSAssert(AudioUnitSetProperty(m_AudioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &outFormat, sizeof(outFormat)));
}
//Initialize remote I/O unit
OSStatus r=AudioUnitInitialize(m_AudioUnit);
OSAssert(r);
}
//start audio output
OSAssert(AudioOutputUnitStart(m_AudioUnit));
Dies ist die Rückruffunktion.
OSStatus AudioThruWorker::staticPerformThru(
void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData)
{
AudioUnitRender(((AudioThruWorker*)inRefCon)->m_AudioUnit, ioActionFlags, inTimeStamp, 1, inNumberFrames, ioData);
//Detect pitch here...
return 0;
}
Ermittlung der Grundursache,
- Ich habe meine Callback-Funktion so geändert, dass sie nur die Eingabedaten zur Ausgabe umleitet.
- Mac zur Erzeugung von weißem Rauschen verwenden
- Verwenden Sie iRig, um das Signal vom Mac-Headset auf das iPhone3Gs umzuleiten, auf dem mein Programm läuft.
- Verwenden Sie iRig, um die Ausgabe des iPhone zurück auf den Mac zu leiten.
- Daten auf dem Mac aufzeichnen.
Das Spektrum der Ausgangsdaten ist in der folgenden Abbildung dargestellt.
Sie können den starken Abfall bei 150 Hz sehen.
Um festzustellen, ob das Problem auf der Eingabe- oder der Ausgabeseite liegt, habe ich die Callback-Funktion so geändert, dass sie die Eingabedaten ignoriert und ein weißes Rauschen ausgibt. Hier ist das Ergebnis. Ganz klar, dass es bei 150 Hz KEINEN Abfall gibt. Daher sollte das Problem auf der Eingangsseite liegen.
Ich dachte, dies sei eine Hardware-Beschränkung. JEDOCH habe ich die App "Amplitube" auf demselben Gerät ausprobiert, alle Effekte ausgeschaltet, weißes Rauschen eingegeben und die Ausgabe analysiert. Es hat KEINEN Abfall bei 150Hz. Hier ist das Ergebnis. Das bedeutet, dass das Drop-off-Problem NICHT auf die Hardware zurückzuführen ist. Es muss einen Weg geben, wie die Software das Problem umgehen kann.
Kennt jemand das Geheimnis?
Danke.