मैं एक आईओएस ऐप लिख रहा हूं जो माइक्रोफ़ोन से इनपुट लेता है, इसे उच्च-पास फ़िल्टर ऑडियो इकाई के माध्यम से चलाता है, और इसे स्पीकर के माध्यम से वापस चलाता है। मैं AUGraph API का उपयोग कर सफलतापूर्वक ऐसा करने में सक्षम हूं। इसमें, मैंने दो नोड्स डाले: एक रिमोट आई/ओ यूनिट, और एक प्रभाव ऑडियो यूनिट (kAudioUnitType_Effect
, kAudioUnitSubType_HighPassFilter
), और आईओ यूनिट के इनपुट तत्व के आउटपुट स्कोप को प्रभाव इकाई के इनपुट में जोड़ा, और आईओ यूनिट के प्रभाव नोड का आउटपुट आउटपुट तत्व का इनपुट दायरा। लेकिन अब मुझे संसाधित ऑडियो नमूने के आधार पर कुछ विश्लेषण करने की आवश्यकता है, इसलिए मुझे बफर तक सीधे पहुंच की आवश्यकता है। इसका मतलब है (और अगर मैं गलत हूं तो कृपया मुझे सही करें) अब मैं प्रभाव नोड के आउटपुट और आईओ यूनिट के आउटपुट तत्व के बीच कनेक्शन बनाने के लिए AUGraphConnectNodeInput
का उपयोग नहीं कर सकता, और आईओ इकाई के आउटपुट तत्व के लिए रेंडर कॉलबैक फ़ंक्शन संलग्न करना होगा, ताकि जब भी वक्ताओं को नए नमूने की आवश्यकता हो तो मैं बफर तक पहुंच सकता हूं। मैंने ऐसा किया है, लेकिन जब मैं AudioUnitRender
फ़ंक्शन कॉलबैक में कॉल करता हूं तो मुझे एक -50 त्रुटि मिलती है। मेरा मानना है कि मेरे पास दो ऑडियो इकाइयों के बीच एएसबीडी विसंगति का मामला है, क्योंकि मैं इसके बारे में कॉलबैक प्रस्तुत करने में कुछ भी नहीं कर रहा हूं (और ऑग्राफ ने पहले इसका ख्याल रखा था)। कोड यह रहा:रिमोट I/O को कॉलबैक फ़ंक्शन प्रस्तुत करने में समस्या
AudioController.h:
@interface AudioController : NSObject
{
AUGraph mGraph;
AudioUnit mEffects;
AudioUnit ioUnit;
}
@property (readonly, nonatomic) AudioUnit mEffects;
@property (readonly, nonatomic) AudioUnit ioUnit;
-(void)initializeAUGraph;
-(void)startAUGraph;
-(void)stopAUGraph;
@end
AudioController.mm:
@implementation AudioController
…
static OSStatus renderInput(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData)
{
AudioController *THIS = (__bridge AudioController*)inRefCon;
AudioBuffer buffer;
AudioStreamBasicDescription fxOutputASBD;
UInt32 fxOutputASBDSize = sizeof(fxOutputASBD);
AudioUnitGetProperty([THIS mEffects], kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &fxOutputASBD, &fxOutputASBDSize);
buffer.mDataByteSize = inNumberFrames * fxOutputASBD.mBytesPerFrame;
buffer.mNumberChannels = fxOutputASBD.mChannelsPerFrame;
buffer.mData = malloc(buffer.mDataByteSize);
AudioBufferList bufferList;
bufferList.mNumberBuffers = 1;
bufferList.mBuffers[0] = buffer;
//TODO prender ARM y solucionar problema de memoria
OSStatus result = AudioUnitRender([THIS mEffects], ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, &bufferList);
[THIS hasError:result:__FILE__:__LINE__];
memcpy(ioData, buffer.mData, buffer.mDataByteSize);
return noErr;
}
- (void)initializeAUGraph
{
OSStatus result = noErr;
// create a new AUGraph
result = NewAUGraph(&mGraph);
AUNode outputNode;
AUNode effectsNode;
AudioComponentDescription effects_desc;
effects_desc.componentType = kAudioUnitType_Effect;
effects_desc.componentSubType = kAudioUnitSubType_LowPassFilter;
effects_desc.componentFlags = 0;
effects_desc.componentFlagsMask = 0;
effects_desc.componentManufacturer = kAudioUnitManufacturer_Apple;
AudioComponentDescription output_desc;
output_desc.componentType = kAudioUnitType_Output;
output_desc.componentSubType = kAudioUnitSubType_RemoteIO;
output_desc.componentFlags = 0;
output_desc.componentFlagsMask = 0;
output_desc.componentManufacturer = kAudioUnitManufacturer_Apple;
// Add nodes to the graph to hold the AudioUnits
result = AUGraphAddNode(mGraph, &output_desc, &outputNode);
[self hasError:result:__FILE__:__LINE__];
result = AUGraphAddNode(mGraph, &effects_desc, &effectsNode);
[self hasError:result:__FILE__:__LINE__];
// Connect the effect node's output to the output node's input
// This is no longer the case, as I need to access the buffer
// result = AUGraphConnectNodeInput(mGraph, effectsNode, 0, outputNode, 0);
[self hasError:result:__FILE__:__LINE__];
// Connect the output node's input scope's output to the effectsNode input
result = AUGraphConnectNodeInput(mGraph, outputNode, 1, effectsNode, 0);
[self hasError:result:__FILE__:__LINE__];
// open the graph AudioUnits
result = AUGraphOpen(mGraph);
[self hasError:result:__FILE__:__LINE__];
// Get a link to the effect AU
result = AUGraphNodeInfo(mGraph, effectsNode, NULL, &mEffects);
[self hasError:result:__FILE__:__LINE__];
// Same for io unit
result = AUGraphNodeInfo(mGraph, outputNode, NULL, &ioUnit);
[self hasError:result:__FILE__:__LINE__];
// Enable input on io unit
UInt32 flag = 1;
result = AudioUnitSetProperty(ioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &flag, sizeof(flag));
[self hasError:result:__FILE__:__LINE__];
// Setup render callback struct
AURenderCallbackStruct renderCallbackStruct;
renderCallbackStruct.inputProc = &renderInput;
renderCallbackStruct.inputProcRefCon = (__bridge void*)self;
// Set a callback for the specified node's specified input
result = AUGraphSetNodeInputCallback(mGraph, outputNode, 0, &renderCallbackStruct);
[self hasError:result:__FILE__:__LINE__];
// Get fx unit's input current stream format...
AudioStreamBasicDescription fxInputASBD;
UInt32 sizeOfASBD = sizeof(AudioStreamBasicDescription);
result = AudioUnitGetProperty(mEffects, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &fxInputASBD, &sizeOfASBD);
[self hasError:result:__FILE__:__LINE__];
// ...and set it on the io unit's input scope's output
result = AudioUnitSetProperty(ioUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output,
1,
&fxInputASBD,
sizeof(fxInputASBD));
[self hasError:result:__FILE__:__LINE__];
// Set fx unit's output sample rate, just in case
Float64 sampleRate = 44100.0;
result = AudioUnitSetProperty(mEffects,
kAudioUnitProperty_SampleRate,
kAudioUnitScope_Output,
0,
&sampleRate,
sizeof(sampleRate));
[self hasError:result:__FILE__:__LINE__];
// Once everything is set up call initialize to validate connections
result = AUGraphInitialize(mGraph);
[self hasError:result:__FILE__:__LINE__];
}
@end
जैसा कि मैंने पहले कहा, मैं AudioUnitRender
कॉल पर एक -50 त्रुटि मिल रही है, और मुझे इसके बारे में कोई दस्तावेज नहीं मिल रहा है।
किसी भी मदद की बहुत सराहना की जाएगी।
टिम बोलस्टेड (http://timbolstad.com/2010/03/14/core-audio-getting-started/) के लिए धन्यवाद एक उत्कृष्ट प्रारंभिक बिंदु ट्यूटोरियल प्रदान करने के लिए धन्यवाद।