Fix compiling the example program, and support AL_SOFT_buffer_samples with it

This commit is contained in:
Chris Robinson
2012-01-10 02:12:54 -08:00
parent e772fb7d0e
commit d4670faafd
4 changed files with 194 additions and 134 deletions
+12 -12
View File
@@ -370,15 +370,15 @@ int getAVAudioInfo(StreamPtr stream, ALuint *rate, ALenum *channels, ALenum *typ
/* Get the sample type for OpenAL given the format detected by ffmpeg. */
if(stream->CodecCtx->sample_fmt == AV_SAMPLE_FMT_U8)
*type = AL_UNSIGNED_BYTE;
*type = AL_UNSIGNED_BYTE_SOFT;
else if(stream->CodecCtx->sample_fmt == AV_SAMPLE_FMT_S16)
*type = AL_SHORT;
*type = AL_SHORT_SOFT;
else if(stream->CodecCtx->sample_fmt == AV_SAMPLE_FMT_S32)
*type = AL_INT;
*type = AL_INT_SOFT;
else if(stream->CodecCtx->sample_fmt == AV_SAMPLE_FMT_FLT)
*type = AL_FLOAT;
*type = AL_FLOAT_SOFT;
else if(stream->CodecCtx->sample_fmt == AV_SAMPLE_FMT_DBL)
*type = AL_DOUBLE;
*type = AL_DOUBLE_SOFT;
else
return 1;
@@ -386,22 +386,22 @@ int getAVAudioInfo(StreamPtr stream, ALuint *rate, ALenum *channels, ALenum *typ
* by ffmpeg. NOTE: some file types may not specify a channel layout. In
* that case, one must be guessed based on the channel count. */
if(stream->CodecCtx->channel_layout == AV_CH_LAYOUT_MONO)
*channels = AL_MONO;
*channels = AL_MONO_SOFT;
else if(stream->CodecCtx->channel_layout == AV_CH_LAYOUT_STEREO)
*channels = AL_STEREO;
*channels = AL_STEREO_SOFT;
else if(stream->CodecCtx->channel_layout == AV_CH_LAYOUT_QUAD)
*channels = AL_QUAD;
*channels = AL_QUAD_SOFT;
else if(stream->CodecCtx->channel_layout == AV_CH_LAYOUT_5POINT1)
*channels = AL_5POINT1;
*channels = AL_5POINT1_SOFT;
else if(stream->CodecCtx->channel_layout == AV_CH_LAYOUT_7POINT1)
*channels = AL_7POINT1;
*channels = AL_7POINT1_SOFT;
else if(stream->CodecCtx->channel_layout == 0)
{
/* Unknown channel layout. Try to guess. */
if(stream->CodecCtx->channels == 1)
*channels = AL_MONO;
*channels = AL_MONO_SOFT;
else if(stream->CodecCtx->channels == 2)
*channels = AL_STEREO;
*channels = AL_STEREO_SOFT;
else
return 1;
}
+149 -56
View File
@@ -41,13 +41,13 @@ const char *ChannelsName(ALenum chans)
{
switch(chans)
{
case AL_MONO: return "Mono";
case AL_STEREO: return "Stereo";
case AL_REAR: return "Rear";
case AL_QUAD: return "Quadraphonic";
case AL_5POINT1: return "5.1 Surround";
case AL_6POINT1: return "6.1 Surround";
case AL_7POINT1: return "7.1 Surround";
case AL_MONO_SOFT: return "Mono";
case AL_STEREO_SOFT: return "Stereo";
case AL_REAR_SOFT: return "Rear";
case AL_QUAD_SOFT: return "Quadraphonic";
case AL_5POINT1_SOFT: return "5.1 Surround";
case AL_6POINT1_SOFT: return "6.1 Surround";
case AL_7POINT1_SOFT: return "7.1 Surround";
}
return "Unknown Channels";
}
@@ -56,14 +56,14 @@ const char *TypeName(ALenum type)
{
switch(type)
{
case AL_BYTE: return "S8";
case AL_UNSIGNED_BYTE: return "U8";
case AL_SHORT: return "S16";
case AL_UNSIGNED_SHORT: return "U16";
case AL_INT: return "S32";
case AL_UNSIGNED_INT: return "U32";
case AL_FLOAT: return "Float32";
case AL_DOUBLE: return "Float64";
case AL_BYTE_SOFT: return "S8";
case AL_UNSIGNED_BYTE_SOFT: return "U8";
case AL_SHORT_SOFT: return "S16";
case AL_UNSIGNED_SHORT_SOFT: return "U16";
case AL_INT_SOFT: return "S32";
case AL_UNSIGNED_INT_SOFT: return "U32";
case AL_FLOAT_SOFT: return "Float32";
case AL_DOUBLE_SOFT: return "Float64";
}
return "Unknown Type";
}
@@ -73,25 +73,25 @@ ALsizei FramesToBytes(ALsizei size, ALenum channels, ALenum type)
{
switch(channels)
{
case AL_MONO: size *= 1; break;
case AL_STEREO: size *= 2; break;
case AL_REAR: size *= 2; break;
case AL_QUAD: size *= 4; break;
case AL_5POINT1: size *= 6; break;
case AL_6POINT1: size *= 7; break;
case AL_7POINT1: size *= 8; break;
case AL_MONO_SOFT: size *= 1; break;
case AL_STEREO_SOFT: size *= 2; break;
case AL_REAR_SOFT: size *= 2; break;
case AL_QUAD_SOFT: size *= 4; break;
case AL_5POINT1_SOFT: size *= 6; break;
case AL_6POINT1_SOFT: size *= 7; break;
case AL_7POINT1_SOFT: size *= 8; break;
}
switch(type)
{
case AL_BYTE: size *= sizeof(ALbyte); break;
case AL_UNSIGNED_BYTE: size *= sizeof(ALubyte); break;
case AL_SHORT: size *= sizeof(ALshort); break;
case AL_UNSIGNED_SHORT: size *= sizeof(ALushort); break;
case AL_INT: size *= sizeof(ALint); break;
case AL_UNSIGNED_INT: size *= sizeof(ALuint); break;
case AL_FLOAT: size *= sizeof(ALfloat); break;
case AL_DOUBLE: size *= sizeof(ALdouble); break;
case AL_BYTE_SOFT: size *= sizeof(ALbyte); break;
case AL_UNSIGNED_BYTE_SOFT: size *= sizeof(ALubyte); break;
case AL_SHORT_SOFT: size *= sizeof(ALshort); break;
case AL_UNSIGNED_SHORT_SOFT: size *= sizeof(ALushort); break;
case AL_INT_SOFT: size *= sizeof(ALint); break;
case AL_UNSIGNED_INT_SOFT: size *= sizeof(ALuint); break;
case AL_FLOAT_SOFT: size *= sizeof(ALfloat); break;
case AL_DOUBLE_SOFT: size *= sizeof(ALdouble); break;
}
return size;
@@ -103,72 +103,154 @@ ALsizei BytesToFrames(ALsizei size, ALenum channels, ALenum type)
}
ALenum GetFormat(ALenum channels, ALenum type)
ALenum GetFormat(ALenum channels, ALenum type, LPALISBUFFERFORMATSUPPORTEDSOFT palIsBufferFormatSupportedSOFT)
{
ALenum format = 0;
ALenum format = AL_NONE;
/* If using AL_SOFT_buffer_samples, try looking through its formats */
if(palIsBufferFormatSupportedSOFT)
{
/* AL_SOFT_buffer_samples is more lenient with matching formats. The
* specified sample type does not need to match the returned format,
* but it is nice to try to get something close. */
if(type == AL_UNSIGNED_BYTE_SOFT || type == AL_BYTE_SOFT)
{
if(channels == AL_MONO_SOFT) format = AL_MONO8_SOFT;
else if(channels == AL_STEREO_SOFT) format = AL_STEREO8_SOFT;
else if(channels == AL_QUAD_SOFT) format = AL_QUAD8_SOFT;
else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_8_SOFT;
else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_8_SOFT;
else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_8_SOFT;
}
else if(type == AL_UNSIGNED_SHORT_SOFT || type == AL_SHORT_SOFT)
{
if(channels == AL_MONO_SOFT) format = AL_MONO16_SOFT;
else if(channels == AL_STEREO_SOFT) format = AL_STEREO16_SOFT;
else if(channels == AL_QUAD_SOFT) format = AL_QUAD16_SOFT;
else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_16_SOFT;
else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_16_SOFT;
else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_16_SOFT;
}
else if(type == AL_UNSIGNED_BYTE3_SOFT || type == AL_BYTE3_SOFT ||
type == AL_UNSIGNED_INT_SOFT || type == AL_INT_SOFT ||
type == AL_FLOAT_SOFT || type == AL_DOUBLE_SOFT)
{
if(channels == AL_MONO_SOFT) format = AL_MONO32F_SOFT;
else if(channels == AL_STEREO_SOFT) format = AL_STEREO32F_SOFT;
else if(channels == AL_QUAD_SOFT) format = AL_QUAD32F_SOFT;
else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_32F_SOFT;
else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_32F_SOFT;
else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_32F_SOFT;
}
if(format != AL_NONE && !palIsBufferFormatSupportedSOFT(format))
format = AL_NONE;
/* A matching format was not found or supported. Try 32-bit float. */
if(format == AL_NONE)
{
if(channels == AL_MONO_SOFT) format = AL_MONO32F_SOFT;
else if(channels == AL_STEREO_SOFT) format = AL_STEREO32F_SOFT;
else if(channels == AL_QUAD_SOFT) format = AL_QUAD32F_SOFT;
else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_32F_SOFT;
else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_32F_SOFT;
else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_32F_SOFT;
if(format != AL_NONE && !palIsBufferFormatSupportedSOFT(format))
format = AL_NONE;
}
/* 32-bit float not supported. Try 16-bit int. */
if(format == AL_NONE)
{
if(channels == AL_MONO_SOFT) format = AL_MONO16_SOFT;
else if(channels == AL_STEREO_SOFT) format = AL_STEREO16_SOFT;
else if(channels == AL_QUAD_SOFT) format = AL_QUAD16_SOFT;
else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_16_SOFT;
else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_16_SOFT;
else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_16_SOFT;
if(format != AL_NONE && !palIsBufferFormatSupportedSOFT(format))
format = AL_NONE;
}
/* 16-bit int not supported. Try 8-bit int. */
if(format == AL_NONE)
{
if(channels == AL_MONO_SOFT) format = AL_MONO8_SOFT;
else if(channels == AL_STEREO_SOFT) format = AL_STEREO8_SOFT;
else if(channels == AL_QUAD_SOFT) format = AL_QUAD8_SOFT;
else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_8_SOFT;
else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_8_SOFT;
else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_8_SOFT;
if(format != AL_NONE && !palIsBufferFormatSupportedSOFT(format))
format = AL_NONE;
}
return format;
}
/* We use the AL_EXT_MCFORMATS extension to provide output of Quad, 5.1,
* and 7.1 channel configs, AL_EXT_FLOAT32 for 32-bit float samples, and
* AL_EXT_DOUBLE for 64-bit float samples. */
if(type == AL_UNSIGNED_BYTE)
if(type == AL_UNSIGNED_BYTE_SOFT)
{
if(channels == AL_MONO)
if(channels == AL_MONO_SOFT)
format = AL_FORMAT_MONO8;
else if(channels == AL_STEREO)
else if(channels == AL_STEREO_SOFT)
format = AL_FORMAT_STEREO8;
else if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
{
if(channels == AL_QUAD)
if(channels == AL_QUAD_SOFT)
format = alGetEnumValue("AL_FORMAT_QUAD8");
else if(channels == AL_5POINT1)
else if(channels == AL_5POINT1_SOFT)
format = alGetEnumValue("AL_FORMAT_51CHN8");
else if(channels == AL_6POINT1)
else if(channels == AL_6POINT1_SOFT)
format = alGetEnumValue("AL_FORMAT_61CHN8");
else if(channels == AL_7POINT1)
else if(channels == AL_7POINT1_SOFT)
format = alGetEnumValue("AL_FORMAT_71CHN8");
}
}
else if(type == AL_SHORT)
else if(type == AL_SHORT_SOFT)
{
if(channels == AL_MONO)
if(channels == AL_MONO_SOFT)
format = AL_FORMAT_MONO16;
else if(channels == AL_STEREO)
else if(channels == AL_STEREO_SOFT)
format = AL_FORMAT_STEREO16;
else if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
{
if(channels == AL_QUAD)
if(channels == AL_QUAD_SOFT)
format = alGetEnumValue("AL_FORMAT_QUAD16");
else if(channels == AL_5POINT1)
else if(channels == AL_5POINT1_SOFT)
format = alGetEnumValue("AL_FORMAT_51CHN16");
else if(channels == AL_6POINT1)
else if(channels == AL_6POINT1_SOFT)
format = alGetEnumValue("AL_FORMAT_61CHN16");
else if(channels == AL_7POINT1)
else if(channels == AL_7POINT1_SOFT)
format = alGetEnumValue("AL_FORMAT_71CHN16");
}
}
else if(type == AL_FLOAT && alIsExtensionPresent("AL_EXT_FLOAT32"))
else if(type == AL_FLOAT_SOFT && alIsExtensionPresent("AL_EXT_FLOAT32"))
{
if(channels == AL_MONO)
if(channels == AL_MONO_SOFT)
format = alGetEnumValue("AL_FORMAT_MONO_FLOAT32");
else if(channels == AL_STEREO)
else if(channels == AL_STEREO_SOFT)
format = alGetEnumValue("AL_FORMAT_STEREO_FLOAT32");
else if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
{
if(channels == AL_QUAD)
if(channels == AL_QUAD_SOFT)
format = alGetEnumValue("AL_FORMAT_QUAD32");
else if(channels == AL_5POINT1)
else if(channels == AL_5POINT1_SOFT)
format = alGetEnumValue("AL_FORMAT_51CHN32");
else if(channels == AL_6POINT1)
else if(channels == AL_6POINT1_SOFT)
format = alGetEnumValue("AL_FORMAT_61CHN32");
else if(channels == AL_7POINT1)
else if(channels == AL_7POINT1_SOFT)
format = alGetEnumValue("AL_FORMAT_71CHN32");
}
}
else if(type == AL_DOUBLE && alIsExtensionPresent("AL_EXT_DOUBLE"))
else if(type == AL_DOUBLE_SOFT && alIsExtensionPresent("AL_EXT_DOUBLE"))
{
if(channels == AL_MONO)
if(channels == AL_MONO_SOFT)
format = alGetEnumValue("AL_FORMAT_MONO_DOUBLE");
else if(channels == AL_STEREO)
else if(channels == AL_STEREO_SOFT)
format = alGetEnumValue("AL_FORMAT_STEREO_DOUBLE");
}
@@ -181,6 +263,17 @@ ALenum GetFormat(ALenum channels, ALenum type)
}
void AL_APIENTRY wrap_BufferSamples(ALuint buffer, ALuint samplerate,
ALenum internalformat, ALsizei samples,
ALenum channels, ALenum type,
const ALvoid *data)
{
alBufferData(buffer, internalformat, data,
FramesToBytes(samples, channels, type),
samplerate);
}
int InitAL(void)
{
ALCdevice *device;
+13 -61
View File
@@ -13,65 +13,6 @@
extern "C" {
#endif /* __cplusplus */
#ifndef AL_SOFT_buffer_samples
#define AL_SOFT_buffer_samples 1
/* Sample types */
#define AL_BYTE 0x1400
#define AL_UNSIGNED_BYTE 0x1401
#define AL_SHORT 0x1402
#define AL_UNSIGNED_SHORT 0x1403
#define AL_INT 0x1404
#define AL_UNSIGNED_INT 0x1405
#define AL_FLOAT 0x1406
#define AL_DOUBLE 0x1407
#define AL_BYTE3 0x1408
#define AL_UNSIGNED_BYTE3 0x1409
/* Channel configurations */
#define AL_MONO 0x1500
#define AL_STEREO 0x1501
#define AL_REAR 0x1502
#define AL_QUAD 0x1503
#define AL_5POINT1 0x1504
#define AL_6POINT1 0x1505
#define AL_7POINT1 0x1506
/* Storage formats */
#define AL_MONO8 0x1100
#define AL_MONO16 0x1101
#define AL_MONO32F 0x10010
#define AL_STEREO8 0x1102
#define AL_STEREO16 0x1103
#define AL_STEREO32F 0x10011
#define AL_QUAD8 0x1204
#define AL_QUAD16 0x1205
#define AL_QUAD32F 0x1206
#define AL_REAR8 0x1207
#define AL_REAR16 0x1208
#define AL_REAR32F 0x1209
#define AL_5POINT1_8 0x120A
#define AL_5POINT1_16 0x120B
#define AL_5POINT1_32F 0x120C
#define AL_6POINT1_8 0x120D
#define AL_6POINT1_16 0x120E
#define AL_6POINT1_32F 0x120F
#define AL_7POINT1_8 0x1210
#define AL_7POINT1_16 0x1211
#define AL_7POINT1_32F 0x1212
/* Buffer attributes */
#define AL_INTERNAL_FORMAT 0x2008
#define AL_BYTE_LENGTH 0x2009
#define AL_SAMPLE_LENGTH 0x200A
#define AL_SEC_LENGTH 0x200B
typedef void (AL_APIENTRY*LPALBUFFERSAMPLESSOFT)(ALuint,ALuint,ALenum,ALsizei,ALenum,ALenum,const ALvoid*);
typedef void (AL_APIENTRY*LPALBUFFERSUBSAMPLESSOFT)(ALuint,ALsizei,ALsizei,ALenum,ALenum,const ALvoid*);
typedef void (AL_APIENTRY*LPALGETBUFFERSAMPLESSOFT)(ALuint,ALsizei,ALsizei,ALenum,ALenum,ALvoid*);
typedef ALboolean (AL_APIENTRY*LPALISBUFFERFORMATSUPPORTEDSOFT)(ALenum);
#endif
/* Some helper functions to get the name from the channel and type enums. */
const char *ChannelsName(ALenum chans);
const char *TypeName(ALenum type);
@@ -81,8 +22,19 @@ ALsizei FramesToBytes(ALsizei size, ALenum channels, ALenum type);
ALsizei BytesToFrames(ALsizei size, ALenum channels, ALenum type);
/* Retrieves a compatible buffer format given the channel configuration and
* sample type. Returns 0 if no supported format can be found. */
ALenum GetFormat(ALenum channels, ALenum type);
* sample type. If an alIsBufferFormatSupportedSOFT-compatible function is
* provided, it will be called to find the closest-matching format from
* AL_SOFT_buffer_samples. Returns AL_NONE (0) if no supported format can be
* found. */
ALenum GetFormat(ALenum channels, ALenum type, LPALISBUFFERFORMATSUPPORTEDSOFT palIsBufferFormatSupportedSOFT);
/* Loads samples into a buffer using the standard alBufferData call, but with a
* LPALBUFFERSAMPLESSOFT-compatible prototype. Assumes internalformat is valid
* for alBufferData, and that channels and type match it. */
void AL_APIENTRY wrap_BufferSamples(ALuint buffer, ALuint samplerate,
ALenum internalformat, ALsizei samples,
ALenum channels, ALenum type,
const ALvoid *data);
/* Easy device init/deinit functions. InitAL returns 0 on success. */
int InitAL(void);
+20 -5
View File
@@ -38,6 +38,10 @@
#include "alffmpeg.h"
LPALBUFFERSAMPLESSOFT palBufferSamplesSOFT = wrap_BufferSamples;
LPALISBUFFERFORMATSUPPORTEDSOFT palIsBufferFormatSupportedSOFT = NULL;
/* Define the number of buffers and buffer size (in samples) to use. 4 buffers
* with 8192 samples each gives a nice per-chunk size, and lets the queue last
* for almost 3/4ths of a second for a 44.1khz stream. */
@@ -140,7 +144,7 @@ static int OpenPlayerFile(StreamPlayer *player, const char *filename)
goto error;
}
player->format = GetFormat(player->channels, player->type);
player->format = GetFormat(player->channels, player->type, palIsBufferFormatSupportedSOFT);
if(player->format == 0)
{
fprintf(stderr, "Unsupported format (%s, %s) for %s\n",
@@ -199,8 +203,9 @@ static int StartPlayer(StreamPlayer *player)
got = readAVAudioData(player->stream, player->data, player->datasize);
if(got == 0) break;
alBufferData(player->buffers[i], player->format, player->data, got,
player->rate);
palBufferSamplesSOFT(player->buffers[i], player->rate, player->format,
BytesToFrames(got, player->channels, player->type),
player->channels, player->type, player->data);
}
if(alGetError() != AL_NO_ERROR)
{
@@ -247,8 +252,9 @@ static int UpdatePlayer(StreamPlayer *player)
got = readAVAudioData(player->stream, player->data, player->datasize);
if(got > 0)
{
alBufferData(bufid, player->format, player->data, got,
player->rate);
palBufferSamplesSOFT(bufid, player->rate, player->format,
BytesToFrames(got, player->channels, player->type),
player->channels, player->type, player->data);
alSourceQueueBuffers(player->source, 1, &bufid);
}
if(alGetError() != AL_NO_ERROR)
@@ -295,6 +301,15 @@ int main(int argc, char **argv)
if(InitAL() != 0)
return 1;
if(alIsExtensionPresent("AL_SOFT_buffer_samples"))
{
printf("AL_SOFT_buffer_samples supported!\n");
palBufferSamplesSOFT = alGetProcAddress("alBufferSamplesSOFT");
palIsBufferFormatSupportedSOFT = alGetProcAddress("alIsBufferFormatSupportedSOFT");
}
else
printf("AL_SOFT_buffer_samples not supported\n");
player = NewPlayer();
/* Play each file listed on the command line */