我正在尝试将OpenAL用于我正在进行的IOS游戏,但在打开音频设备时出现问题。具体来说,当我调用函数alcOpenDevice(NULL)时,我得到'NULL'作为回报。当然,这会导致问题,但我不知道我做错了什么。
我是OpenAL的新手,所以我一直在寻找一些指南here和here,看看我需要做什么。如果我下载他们的示例项目并测试他们,他们都工作正常。如果我将他们的文件复制到我的项目中,并忽略我制作的文件,他们仍然可以正常工作。当我开始重建代码以便在我的项目中使用时,我假设在翻译中丢失了一些东西。在网上询问并在网上搜索并没有给我任何线索,所以我希望这里有人能让我走上正轨。
这是我在AudioPlayer.m中使用的实际设置代码
- (void)setup {
audioSampleBuffers = [NSMutableDictionary new];
audioSampleSources = [NSMutableArray new];
[self setupAudioSession];
[self setupAudioDevice];
[self setupNotifications];
}
- (BOOL)setupAudioSession {
// // This has been depricated.
//
// /* Setup the Audio Session and monitor interruptions */
// AudioSessionInitialize(NULL, NULL, AudioInterruptionListenerCallback, NULL);
//
// /* Set the category for the Audio Session */
// UInt32 session_category = kAudioSessionCategory_MediaPlayback;
// AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(session_category), &session_category);
//
// /* Make the Audio Session active */
// AudioSessionSetActive(true);
BOOL success = NO;
NSError *error = nil;
AVAudioSession *session = [AVAudioSession sharedInstance];
success = [session setCategory:AVAudioSessionCategoryPlayback error:&error];
if (!success) {
NSLog(@"%@ Error setting category: %@", NSStringFromSelector(_cmd), [error localizedDescription]);
return success;
}
success = [session setActive:YES error:&error];
if (!success) {
NSLog(@"Error activating session: %@", [error localizedDescription]);
}
return success;
}
- (BOOL)setupAudioDevice {
// 'NULL' uses the default device.
openALDevice = alcOpenDevice(NULL); // Returns 'NULL'
ALenum error = alGetError(); // Returns '0'
NSLog(@"%i", error);
if (!openALDevice) {
NSLog(@"Something went wrong setting up the audio device.");
return NO;
}
// Create a context to use with the device, and make it the current context.
openALContext = alcCreateContext(openALDevice, NULL);
alcMakeContextCurrent(openALContext);
[self createAudioSources];
// Setup was successful
return YES;
}
- (void)createAudioSources {
ALuint sourceID;
for (int i = 0; i < kMaxConcurrentSources; i++) {
// Create a single source.
alGenSources(1, &sourceID);
// Add it to the array.
[audioSampleSources addObject:[NSNumber numberWithUnsignedInt:sourceID]];
}
}
注意:我在新的iPad上运行IOS 7.1.1,并使用Xcode 5.1.1。此问题已在iPad,我的模拟器和iPod touch上得到确认。
答案 0 :(得分:1)
简答:
Apple的alcOpenDevice()
实现仅返回设备一次。每个后续调用都返回NULL。许多Apple音频代码都可以调用此函数,因此在使用OpenAL并手动调用该函数之前,请先取出所有音频代码。
长答案:
我在使用ObjectAL时花了半天时间处理这个问题,最后完成了你所做的事情,重新制作了整个项目。它工作,直到出于好奇我复制整个项目,然后再次出现同样的问题,alcOpenDevice(NULL)
返回NULL。我偶然发现了答案。在我的快速游戏场景中,这是一段代码:
let jumpSound = SKAction.playSoundFileNamed("WhistleJump.mp3", waitForCompletion: false)
然后我记得在没有涉及SKAction之前我遇到过这个问题。那时我发现我以两种不同的方式使用ObjectAL,我在一个地方使用OALSimpleAudio,在另一个地方使用OpenAL对象,它正在初始化我的音频会话两次。
这两个事件之间的共同点是两次alcOpenDevice()
在应用程序的生命周期中被多次调用。由于我滥用库,第一次被ObjectAL调用它两次。第二个SKAction.playSoundFileNamed()
必须在我的ObjectAL代码之前调用alcOpenDevice()
。经过进一步研究,我在OpenAL 1.1规范中找到了这一点:
alcOpenDevice函数允许应用程序(即客户端程序)连接到设备(即服务器)。 ALCdevice * alcOpenDevice(const ALCchar * deviceSpecifier); 如果函数返回NULL,则表示未找到声音驱动程序/设备。参数是一个以空字符结尾的字符串,它请求某个设备或设备配置。如果指定NULL,则实现将提供特定于实现的默认值。
我的预感是,Apple在此功能的实现仅在应用程序的生命周期内返回正确的设备 ONCE 。每次在此之后调用alcOpenDevice时,它返回NULL。所以底线:在切换到OpenAL之前,取出每一段音频代码。即使是看似安全的代码,例如SKAction.playSoundFileNamed()
,仍然可能包含对alcOpenDevice()
的调用,深深埋藏在其实现中。
对于那些使用ObjectAL的人来说,这是这个问题的控制台输出,以帮助他们从谷歌找到他们的方式,因为我自己找不到一个好的答案:
OAL Error: +[ALWrapper openDevice:]: Could not open device (null)
OAL Error: -[ALDevice initWithDeviceSpecifier:]: <ALDevice: 0x17679b20>: Failed to create OpenAL device (null)
OAL Error: +[ALWrapper closeDevice:]: Invalid Enum (error code 0x0000a003)
OAL Warning: -[OALAudioSession onAudioError:]: Received audio error notification, but last reset was 0.012216 seconds ago. Doing nothing.
fatal error: unexpectedly found nil while unwrapping an Optional value
答案 1 :(得分:0)
This SO answer似乎验证了我对{1}}与OpenAL冲突的评论。尝试删除AVAudioSession
,或首先初始化OpenAL(我想这会导致反问题)。
答案 2 :(得分:-2)
好吧,所以我最终重新开始了一个新项目,其中包含我链接的第一个示例项目中的复制粘贴版本的AudioSamplePlayer。 - 工作了。
然后我逐步将其编辑回我在项目中设置的格式。 - 它仍然有用!
我还是第一次不知道自己做错了什么,而且我不确定它是否已经在我的音频播放器中了,但它现在正在运行。我责怪小鬼。
......也许是外星人的监视。