如何使用 OpenAL 在 IOS 上播放 Ogg/Vorbis 声音?
How do I play an Ogg/Vorbis sound on IOS using OpenAL?
我想在 IOS 设备上播放 Ogg/Vorbis 声音文件,使用 OpenAL 以实现低延迟。
我有可以编译并部署到 iPhone6 上的代码,但我听不到任何声音。我使用的代码几乎与在 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*)#
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);
为什么设备上没有播放声音?
原来我错过了在打开 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);
我想在 IOS 设备上播放 Ogg/Vorbis 声音文件,使用 OpenAL 以实现低延迟。
我有可以编译并部署到 iPhone6 上的代码,但我听不到任何声音。我使用的代码几乎与在 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*)#
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);
为什么设备上没有播放声音?
原来我错过了在打开 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);