如何使用OpenAL在IOS上播放Ogg / Vorbis声音?

时间:2018-10-18 08:45:46

标签: ios openal ogg vorbis oggvorbis

我想使用OpenAL在低延迟的IAL设备上播放Ogg / Vorbis声音文件。

我有可以编译并部署到iPhone 6上的代码,但是没有声音。我实际上使用的是在Windows上可以正常运行的相同代码,所以我被困在这里。

加载ogg的代码:

#ifdef __APPLE__
#include <OpenAL/alc.h>
#include <OpenAL/al.h>
#include <UIKit/UIKit.h>
#else
#include <AL/al.h>
#include <AL/alc.h>
#endif
#include <vorbis/vorbisfile.h>
#define READ_BUFFER_SIZE 4096

static int endian = 2;

int load_ogg(const char* file_path, std::vector<char>* buffer, int* num_channels, int* freq)
{
    char readbuf[READ_BUFFER_SIZE];
    FILE* fp;
#ifdef __APPLE__
    char bundle_path[512];
    strcpy(bundle_path, file_path);
    char* p = bundle_path;
    while(*p != '.' && *p != 0)
        p++;
    *p = 0;
    NSString* path = [[NSBundle mainBundle] pathForResource: [NSString stringWithCString:bundle_path encoding:NSUTF8StringEncoding] ofType: @"ogg"];
    strcpy(bundle_path, path.UTF8String);
    fp = fopen(bundle_path, "rb");
#else
    fp = fopen(file_path, "rb");
#endif
    if(fp == NULL)
    {
        fflog_print("Load ogg failed - File not found.\n");
        return 1;
    }
    if(endian == 2)
    {
        uint32_t num = 0x01010000;
        uint8_t* p = (uint8_t*)&num;
        endian = *p;
    }
    OggVorbis_File ogg_file;
    vorbis_info* info;
    ov_open(fp, &ogg_file, NULL, 0);
    info = ov_info(&ogg_file, -1);
    *num_channels = info->channels;
    *freq = (int)info->rate;
    int bit_stream;
    int bytes;
    while(1)
    {
        bytes = ov_read(&ogg_file, readbuf, READ_BUFFER_SIZE, endian, 2, 1, &bit_stream);
        if(bytes > 0)
        {
            int starting_index = buffer->size();
            buffer->resize(buffer->size()+bytes);
            memcpy(&(*buffer)[starting_index], readbuf, bytes);
        }
        else
        {
            if(bytes < 0)
                fflog_print("read error.\n");
            break;
        }
    }
    ov_clear(&ogg_file);
    return 0;
}

运行上述代码的相关代码段:

ALCdevice* device = alcOpenDevice(NULL);
if(!device)
{
    fflog_print("device not found.\n");
    return NULL;
}
ALCcontext* context = alcCreateContext(device, NULL);
if(!alcMakeContextCurrent(context))
{
    fflog_print("Failed to make context current.\n");
    return NULL;
}
ALuint source;
alGenSources(1, &source);
//alListener3f(AL_POSITION, 0.0f, 0.0f, 0.0f);
alSource3f(source, AL_POSITION, 0, 0, 0);
alSource3f(source, AL_VELOCITY, 0, 0, 0);
ALuint buffer;
alGenBuffers((ALuint)1, &buffer);
std::vector<char> oggbuffer;
int num_channels;
int freq;
fflog_print("loading music.ogg\n");
if(load_ogg("music.ogg", &oggbuffer, &num_channels, &freq))
{
    fflog_print("Failed to load ogg data.\n");
    return NULL;
}
fflog_print("finished loading music.ogg.\n");
ALenum format;
if(num_channels == 1)
    format = AL_FORMAT_MONO16;
else
    format = AL_FORMAT_STEREO16;
fflog_print("oggbuffer size=%d, freq=%d\n", (int)oggbuffer.size(), freq);
alBufferData(buffer, format, &oggbuffer[0], (ALsizei)oggbuffer.size(), freq);
alSourcei(source, AL_BUFFER, buffer);
alSourcePlay(source);

为什么设备上没有声音播放?

1 个答案:

答案 0 :(得分:0)

结果是,我错过了打开OpenAL设备之前需要使用AudioSessionInitialize设置音频会话的步骤。

我必须在'ALCdevice * device = alcOpenDevice(NULL);'之前添加它

AudioSessionInitialize(NULL, NULL, NULL, NULL);
UInt32 session_category = kAudioSessionCategory_MediaPlayback;
AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(session_category), &session_category);
AudioSessionSetActive(true);