2015-02-28 18 views
5

Grałem z nową błyszczącą biblioteką Apple AVFoundation, ale jak dotąd nie mogę ustawić urządzeń wejściowych ani wyjściowych (np. Karty dźwiękowej USB) używanej przez AVAudioEngine, a także nie można znaleźć niczego w dokumentacji, aby powiedzieć, że jest to możliwe.Zestaw urządzeń wejściowych i wyjściowych AVAudioEngine

Czy ktoś ma z tym jakieś doświadczenie?

+0

Jak długie ujęcie, próbowałem odlewania 'mainMixerNode' danego' AVAudioEngine' do 'AVAudioIONode' który faktycznie pracował (z jakiegoś powodu?) - to początek. – benjineer

Odpowiedz

2

OK, po ponownym przeczytaniu dokumentów po raz dziesiąty, zauważyłem, że AVAudioEngine ma członków inputNode i outputNode (nie jestem pewien, jak to przegapiłem!).

Poniższy kod wydaje się wykonać zadanie:

AudioDeviceID inputDeviceID = 53; // get this using AudioObjectGetPropertyData 
AVAudioEngine *engine = [[AVAudioEngine alloc] init]; 
AudioUnit audioUnit = [[engine inputNode] audioUnit]; 

OSStatus error = AudioUnitSetProperty(audioUnit, 
             kAudioOutputUnitProperty_CurrentDevice, 
             kAudioUnitScope_Global, 
             0, 
             &inputDeviceID, 
             sizeof(inputDeviceID)); 

pożyczyłem kod non-AVFoundation C z przykładu CAPlayThrough.

+0

Kiedy próbuję to zrobić dla węzła wyjściowego, otrzymuję komunikat o błędzie "warunek wymagany to false: numChannelsAggDevice> = numChannelsSubDevice'. – DanielGibbs

+0

Czy otrzymałeś poprawny identyfikator urządzenia za pomocą 'AudioObjectGetPropertyData', czy po prostu używasz' 53'? Ile kanałów ma twoje urządzenie wejściowe? – benjineer

+0

Mam poprawny identyfikator urządzenia, a stan powrotu wynosił 0, ale z urządzenia nie wyprowadzono żadnych danych wyjściowych. – DanielGibbs

2

Oto pełna, jeśli nieco szorstka, funkcja, która odtwarza dźwięk do celów testowych (wybierz inny plik, jeśli nie masz zainstalowanego tam GarageBand, oczywiście). Aby uniknąć zakodowania identyfikatora urządzenia, przełącza się na urządzenie alarmowe ("efekty dźwiękowe"), które można ustawić w Preferencjach systemowych.

AVAudioEngine *engine = [[AVAudioEngine alloc] init]; 
AudioUnit outputUnit = engine.outputNode.audioUnit; 

OSStatus err = noErr; 
AudioDeviceID outputDeviceID; 
UInt32 propertySize; 

AudioObjectPropertyAddress propertyAddress = { 
    kAudioHardwarePropertyDefaultSystemOutputDevice, 
    kAudioObjectPropertyScopeGlobal, 
    kAudioObjectPropertyElementMaster }; 
propertySize = sizeof(outputDeviceID); 
err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &propertySize, &outputDeviceID); 
if (err) { NSLog(@"AudioHardwareGetProperty: %d", (int)err); return; } 

err = AudioUnitSetProperty(outputUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &outputDeviceID, sizeof(outputDeviceID)); 
if (err) { NSLog(@"AudioUnitSetProperty: %d", (int)err); return; } 

NSURL *url = [NSURL URLWithString:@"/Applications/GarageBand.app/Contents/Frameworks/MAAlchemy.framework/Versions/A/Resources/Libraries/WaveNoise/Liquid.wav"]; 
NSError *error = nil; 
AVAudioFile *file = [[AVAudioFile alloc] initForReading:url error:&error]; 
if (file == nil) { NSLog(@"AVAudioFile error: %@", error); return; } 

AVAudioPlayerNode *player = [[AVAudioPlayerNode alloc] init]; 
[engine attachNode:player]; 
[engine connect:player to:engine.outputNode format:nil]; 

NSLog(@"engine: %@", engine); 

if (![engine startAndReturnError:&error]) { 
    NSLog(@"engine failed to start: %@", error); 
    return; 
} 

[player scheduleFile:file atTime:[AVAudioTime timeWithHostTime:mach_absolute_time()] completionHandler:^{ 
    NSLog(@"complete"); 
}]; 
[player play]; 
+0

To jest świetne, otrzymywałem błędy przekazując format do '[engine connect]' - przekazanie 'nil' robi lewę – benjineer

Powiązane problemy