diff options
-rw-r--r-- | examples/alffmpeg.c | 24 | ||||
-rw-r--r-- | examples/alhelpers.c | 205 | ||||
-rw-r--r-- | examples/alhelpers.h | 74 | ||||
-rw-r--r-- | examples/alstream.c | 25 |
4 files changed, 194 insertions, 134 deletions
diff --git a/examples/alffmpeg.c b/examples/alffmpeg.c index 13cc0efe..424a07a6 100644 --- a/examples/alffmpeg.c +++ b/examples/alffmpeg.c @@ -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; } diff --git a/examples/alhelpers.c b/examples/alhelpers.c index ba23cabd..dbfe2383 100644 --- a/examples/alhelpers.c +++ b/examples/alhelpers.c @@ -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; diff --git a/examples/alhelpers.h b/examples/alhelpers.h index 5559ea6f..eda8925e 100644 --- a/examples/alhelpers.h +++ b/examples/alhelpers.h @@ -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); diff --git a/examples/alstream.c b/examples/alstream.c index f25ca0be..183d54f2 100644 --- a/examples/alstream.c +++ b/examples/alstream.c @@ -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 */ |