设置 AVAudioEngine 输入输出设备
Set AVAudioEngine Input and Output Devices
我一直在玩苹果闪亮的新 AVFoundation
库,但到目前为止我无法设置 [=11= 使用的输入或输出设备(例如 USB 声卡) ],而且我似乎无法在文档中找到任何东西来说明这是可能的。
有人有这方面的经验吗?
好的,在第 10 次重新阅读文档后,我注意到 AVAudioEngine
有成员 inputNode and outputNode(不知道我是怎么错过的!)。
以下代码似乎可以完成这项工作:
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));
我从 CAPlayThrough 示例中借用了非 AVFoundation C 代码。
这是一个完整的函数,虽然有些粗糙,但可以播放一些音频以供测试(当然,如果您没有在那里安装 GarageBand,请选择一个不同的文件)。为避免对设备 ID 进行硬编码,它会切换到您可以在系统偏好设置中设置的警报 ("sound effects") 设备。
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];
我一直在玩苹果闪亮的新 AVFoundation
库,但到目前为止我无法设置 [=11= 使用的输入或输出设备(例如 USB 声卡) ],而且我似乎无法在文档中找到任何东西来说明这是可能的。
有人有这方面的经验吗?
好的,在第 10 次重新阅读文档后,我注意到 AVAudioEngine
有成员 inputNode and outputNode(不知道我是怎么错过的!)。
以下代码似乎可以完成这项工作:
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));
我从 CAPlayThrough 示例中借用了非 AVFoundation C 代码。
这是一个完整的函数,虽然有些粗糙,但可以播放一些音频以供测试(当然,如果您没有在那里安装 GarageBand,请选择一个不同的文件)。为避免对设备 ID 进行硬编码,它会切换到您可以在系统偏好设置中设置的警报 ("sound effects") 设备。
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];