Echtzeit-audio-Verarbeitung ohne Ausgabe
Ich bin auf der Suche auf dieses Beispiel http://teragonaudio.com/article/How-to-do-realtime-recording-with-effect-processing-on-iOS.html
und ich möchte mich von meinem Ausgang. Ich versuche es zu ändern: kAudioSessionCategory_PlayAndRecord
zu kAudioSessionCategory_RecordAudio
aber das wird nicht funktionieren. Ich versuche auch, um loszuwerden off:
if(AudioUnitSetProperty(*audioUnit, kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output, 1, &streamDescription, sizeof(streamDescription)) != noErr) {
return 1;
}
Becouse will ich, um den Ton vom Mikrofon, aber nicht spielen. Aber egal, was ich tun, wenn mein sound zu bekommen renderCallback Methode gibt es einen -50 Fehler. Wenn audio spielt automatisch bei der Ausgabe funktioniert alles einwandfrei...
Update mit code:
using namespace std;
AudioUnit *audioUnit = NULL;
float *convertedSampleBuffer = NULL;
int initAudioSession() {
audioUnit = (AudioUnit*)malloc(sizeof(AudioUnit));
if(AudioSessionInitialize(NULL, NULL, NULL, NULL) != noErr) {
return 1;
}
if(AudioSessionSetActive(true) != noErr) {
return 1;
}
UInt32 sessionCategory = kAudioSessionCategory_PlayAndRecord;
if(AudioSessionSetProperty(kAudioSessionProperty_AudioCategory,
sizeof(UInt32), &sessionCategory) != noErr) {
return 1;
}
Float32 bufferSizeInSec = 0.02f;
if(AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareIOBufferDuration,
sizeof(Float32), &bufferSizeInSec) != noErr) {
return 1;
}
UInt32 overrideCategory = 1;
if(AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryDefaultToSpeaker,
sizeof(UInt32), &overrideCategory) != noErr) {
return 1;
}
//There are many properties you might want to provide callback functions for:
//kAudioSessionProperty_AudioRouteChange
//kAudioSessionProperty_OverrideCategoryEnableBluetoothInput
//etc.
return 0;
}
OSStatus renderCallback(void *userData, AudioUnitRenderActionFlags *actionFlags,
const AudioTimeStamp *audioTimeStamp, UInt32 busNumber,
UInt32 numFrames, AudioBufferList *buffers) {
OSStatus status = AudioUnitRender(*audioUnit, actionFlags, audioTimeStamp,
1, numFrames, buffers);
int doOutput = 0;
if(status != noErr) {
return status;
}
if(convertedSampleBuffer == NULL) {
//Lazy initialization of this buffer is necessary because we don't
//know the frame count until the first callback
convertedSampleBuffer = (float*)malloc(sizeof(float) * numFrames);
baseTime = (float)QRealTimer::getUptimeInMilliseconds();
}
SInt16 *inputFrames = (SInt16*)(buffers->mBuffers->mData);
//If your DSP code can use integers, then don't bother converting to
//floats here, as it just wastes CPU. However, most DSP algorithms rely
//on floating point, and this is especially true if you are porting a
//VST/AU to iOS.
int i;
for( i = numFrames; i < fftlength; i++ ) //Shifting buffer
x_inbuf[i - numFrames] = x_inbuf[i];
for( i = 0; i < numFrames; i++) {
x_inbuf[i + x_phase] = (float)inputFrames[i] / (float)32768;
}
if( x_phase + numFrames == fftlength )
{
x_alignment.SigProc_frontend(x_inbuf); //Signal processing front-end (FFT!)
doOutput = x_alignment.Align();
///Output as text! In the real-time version,
// this is where we update visualisation callbacks and launch other services
if ((doOutput) & (x_netscore.isEvent(x_alignment.Position()))
&(x_alignment.lastAction()<x_alignment.Position()) )
{
// here i want to do something with my input!
}
}
else
x_phase += numFrames;
return noErr;
}
int initAudioStreams(AudioUnit *audioUnit) {
UInt32 audioCategory = kAudioSessionCategory_PlayAndRecord;
if(AudioSessionSetProperty(kAudioSessionProperty_AudioCategory,
sizeof(UInt32), &audioCategory) != noErr) {
return 1;
}
UInt32 overrideCategory = 1;
if(AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryDefaultToSpeaker,
sizeof(UInt32), &overrideCategory) != noErr) {
//Less serious error, but you may want to handle it and bail here
}
AudioComponentDescription componentDescription;
componentDescription.componentType = kAudioUnitType_Output;
componentDescription.componentSubType = kAudioUnitSubType_RemoteIO;
componentDescription.componentManufacturer = kAudioUnitManufacturer_Apple;
componentDescription.componentFlags = 0;
componentDescription.componentFlagsMask = 0;
AudioComponent component = AudioComponentFindNext(NULL, &componentDescription);
if(AudioComponentInstanceNew(component, audioUnit) != noErr) {
return 1;
}
UInt32 enable = 1;
if(AudioUnitSetProperty(*audioUnit, kAudioOutputUnitProperty_EnableIO,
kAudioUnitScope_Input, 1, &enable, sizeof(UInt32)) != noErr) {
return 1;
}
AURenderCallbackStruct callbackStruct;
callbackStruct.inputProc = renderCallback; //Render function
callbackStruct.inputProcRefCon = NULL;
if(AudioUnitSetProperty(*audioUnit, kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Input, 0, &callbackStruct,
sizeof(AURenderCallbackStruct)) != noErr) {
return 1;
}
AudioStreamBasicDescription streamDescription;
//You might want to replace this with a different value, but keep in mind that the
//iPhone does not support all sample rates. 8kHz, 22kHz, and 44.1kHz should all work.
streamDescription.mSampleRate = 44100;
//Yes, I know you probably want floating point samples, but the iPhone isn't going
//to give you floating point data. You'll need to make the conversion by hand from
//linear PCM <-> float.
streamDescription.mFormatID = kAudioFormatLinearPCM;
//This part is important!
streamDescription.mFormatFlags = kAudioFormatFlagIsSignedInteger |
kAudioFormatFlagsNativeEndian |
kAudioFormatFlagIsPacked;
streamDescription.mBitsPerChannel = 16;
//1 sample per frame, will always be 2 as long as 16-bit samples are being used
streamDescription.mBytesPerFrame = 2;
streamDescription.mChannelsPerFrame = 1;
streamDescription.mBytesPerPacket = streamDescription.mBytesPerFrame *
streamDescription.mChannelsPerFrame;
//Always should be set to 1
streamDescription.mFramesPerPacket = 1;
//Always set to 0, just to be sure
streamDescription.mReserved = 0;
//Set up input stream with above properties
if(AudioUnitSetProperty(*audioUnit, kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input, 0, &streamDescription, sizeof(streamDescription)) != noErr) {
return 1;
}
//Ditto for the output stream, which we will be sending the processed audio to
if(AudioUnitSetProperty(*audioUnit, kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output, 1, &streamDescription, sizeof(streamDescription)) != noErr) {
return 1;
}
return 0;
}
int startAudioUnit(AudioUnit *audioUnit) {
if(AudioUnitInitialize(*audioUnit) != noErr) {
return 1;
}
if(AudioOutputUnitStart(*audioUnit) != noErr) {
return 1;
}
return 0;
}
Und Anrufe aus meinem VC:
initAudioSession();
initAudioStreams( audioUnit);
startAudioUnit( audioUnit);
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wenn Sie wollen nur eine Aufnahme, keine Wiedergabe, kommentieren Sie einfach die Zeile, die Sätze renderCallback:
Update nach dem sehen-code:
Als ich vermutete, Sie sind nicht input-callback. Fügen Sie diese Zeilen:
Nun in Ihrem recordingCallback:
Btw, ich bin Zuweisung von meinen eigenen Puffer, anstatt die von AudioUnit. Möchten Sie vielleicht ändern Sie die Teile, wenn Sie wollen, verwenden Sie die Virtuelle zugewiesenen Puffer übergeben wird.
Update:
Zuordnung von eigenen Puffer:
Auch, wenn Sie das tun, sagen, AudioUnit, um nicht allocate buffers:
Muss CoreAudio-utility Klassen
Danke für @Mar0ux 's Antwort. Wer kam hier auf der Suche nach kompletten Beispiel-code, dies zu tun, kann einen Blick hier:
https://code.google.com/p/ios-coreaudio-example/
Ich bin dabei eine ähnliche app funktioniert mit dem gleichen code und ich fand, dass Sie am Ende der Wiedergabe durch ändern der enumeration
kAudioSessionCategory_PlayAndRecord
zuRecordAudio
Beendet die Rückkopplung zwischen Mikrofon und Lautsprecher auf meiner hardware.