使用OpenAL获取音频设备

时间:2014-06-05 18:10:08

标签: ipad ios7 openal

我正在尝试将OpenAL用于我正在进行的IOS游戏,但在打开音频设备时出现问题。具体来说,当我调用函数alcOpenDevice(NULL)时,我得到'NULL'作为回报​​。当然,这会导致问题,但我不知道我做错了什么。

我是OpenAL的新手,所以我一直在寻找一些指南herehere,看看我需要做什么。如果我下载他们的示例项目并测试他们,他们都工作正常。如果我将他们的文件复制到我的项目中,并忽略我制作的文件,他们仍然可以正常工作。当我开始重建代码以便在我的项目中使用时,我假设在翻译中丢失了一些东西。在网上询问并在网上搜索并没有给我任何线索,所以我希望这里有人能让我走上正轨。

这是我在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上得到确认。

3 个答案:

答案 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规范中找到了这一点:


6.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。 - 工作了。

然后我逐步将其编辑回我在项目中设置的格式。 - 它仍然有用!

我还是第一次不知道自己做错了什么,而且我不确定它是否已经在我的音频播放器中了,但它现在正在运行。我责怪小鬼。

......也许是外星人的监视。