Как воспроизвести звук Ogg / Vorbis на IOS с использованием OpenAL? - PullRequest
0 голосов
/ 18 октября 2018

Я хотел бы воспроизвести звуковой файл Ogg / Vorbis на устройстве IOS, использующем OpenAL из-за его низкой задержки.

У меня есть код, который компилируется и развертывается на 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 голосов
/ 23 октября 2018

Оказывается, я пропустил шаг, где мне нужно использовать AudioSessionInitialize для настройки моего аудио-сеанса до открытия устройства OpenAL.

Мне пришлось добавить это до 'ALCdevice * device = alcOpenDevice (NULL);'

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