aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt26
-rw-r--r--examples/alstream.c65
-rw-r--r--examples/common/alhelpers.h4
-rw-r--r--examples/common/sdl_sound.c149
-rw-r--r--examples/common/sdl_sound.h43
5 files changed, 239 insertions, 48 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8fbf775b..792bf393 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -766,6 +766,11 @@ SET(BACKENDS "${BACKENDS} Null")
IF(ALSOFT_EXAMPLES)
# Might be able to use earlier versions, but these definitely work
PKG_CHECK_MODULES(FFMPEG libavcodec>=53.61.100 libavformat>=53.32.100 libavutil>=51.35.100)
+
+ FIND_PACKAGE(SDL)
+ IF(SDL_FOUND)
+ FIND_PACKAGE(SDL_sound)
+ ENDIF()
ENDIF()
IF(LIBTYPE STREQUAL "STATIC")
@@ -864,13 +869,24 @@ IF(ALSOFT_UTILS)
ENDIF()
IF(ALSOFT_EXAMPLES)
- IF(FFMPEG_FOUND)
+ IF(SDL_FOUND AND SDL_SOUND_FOUND)
ADD_EXECUTABLE(alstream examples/common/alhelpers.c
- examples/common/alffmpeg.c
+ examples/common/sdl_sound.c
examples/alstream.c)
- TARGET_LINK_LIBRARIES(alstream ${FFMPEG_LIBRARIES} ${LIBNAME})
- SET_TARGET_PROPERTIES(alstream PROPERTIES COMPILE_FLAGS "${FFMPEG_CFLAGS}")
+ TARGET_LINK_LIBRARIES(alstream ${SDL_SOUND_LIBRARIES} ${LIBNAME})
+ SET_TARGET_PROPERTIES(alstream PROPERTIES INCLUDE_DIRECTORIES "${SDL_SOUND_INCLUDE_DIR}")
+ INSTALL(TARGETS alstream
+ RUNTIME DESTINATION bin
+ LIBRARY DESTINATION "lib${LIB_SUFFIX}"
+ ARCHIVE DESTINATION "lib${LIB_SUFFIX}"
+ )
+
+ MESSAGE(STATUS "Building SDL_sound example programs")
+ MESSAGE(STATUS "")
+ ENDIF()
+
+ IF(FFMPEG_FOUND)
ADD_EXECUTABLE(alreverb examples/common/alhelpers.c
examples/common/alffmpeg.c
examples/alreverb.c)
@@ -883,7 +899,7 @@ IF(ALSOFT_EXAMPLES)
TARGET_LINK_LIBRARIES(allatency ${FFMPEG_LIBRARIES} ${LIBNAME})
SET_TARGET_PROPERTIES(allatency PROPERTIES COMPILE_FLAGS "${FFMPEG_CFLAGS}")
- INSTALL(TARGETS alstream alreverb allatency
+ INSTALL(TARGETS alreverb allatency
RUNTIME DESTINATION bin
LIBRARY DESTINATION "lib${LIB_SUFFIX}"
ARCHIVE DESTINATION "lib${LIB_SUFFIX}"
diff --git a/examples/alstream.c b/examples/alstream.c
index 809d37bb..2972d375 100644
--- a/examples/alstream.c
+++ b/examples/alstream.c
@@ -35,32 +35,26 @@
#include "AL/alext.h"
#include "common/alhelpers.h"
-#include "common/alffmpeg.h"
+#include "common/sdl_sound.h"
static LPALBUFFERSAMPLESSOFT alBufferSamplesSOFT = wrap_BufferSamples;
static LPALISBUFFERFORMATSUPPORTEDSOFT alIsBufferFormatSupportedSOFT;
-/* 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. */
+/* Define the number of buffers and buffer size (in milliseconds) to use. 4
+ * buffers with 200ms each gives a nice per-chunk size, and lets the queue last
+ * for almost one second. */
#define NUM_BUFFERS 4
-#define BUFFER_SIZE 8192
+#define BUFFER_TIME_MS 200
typedef struct StreamPlayer {
/* These are the buffers and source to play out through OpenAL with */
ALuint buffers[NUM_BUFFERS];
ALuint source;
- /* Handles for the audio stream */
+ /* Handle for the audio file */
FilePtr file;
- StreamPtr stream;
-
- /* A temporary data buffer for readAVAudioData to write to and pass to
- * OpenAL with */
- ALbyte *data;
- ALsizei datasize;
/* The format of the output stream */
ALenum format;
@@ -128,17 +122,15 @@ static int OpenPlayerFile(StreamPlayer *player, const char *filename)
ClosePlayerFile(player);
/* Open the file and get the first stream from it */
- player->file = openAVFile(filename);
- player->stream = getAVAudioStream(player->file, 0);
- if(!player->stream)
+ player->file = openAudioFile(filename, BUFFER_TIME_MS);
+ if(!player->file)
{
fprintf(stderr, "Could not open audio in %s\n", filename);
goto error;
}
/* Get the stream format, and figure out the OpenAL format */
- if(getAVAudioInfo(player->stream, &player->rate, &player->channels,
- &player->type) != 0)
+ if(getAudioInfo(player->file, &player->rate, &player->channels, &player->type) != 0)
{
fprintf(stderr, "Error getting audio info for %s\n", filename);
goto error;
@@ -153,23 +145,11 @@ static int OpenPlayerFile(StreamPlayer *player, const char *filename)
goto error;
}
- /* Allocate enough space for the temp buffer, given the format */
- player->datasize = FramesToBytes(BUFFER_SIZE, player->channels,
- player->type);
- player->data = malloc(player->datasize);
- if(player->data == NULL)
- {
- fprintf(stderr, "Error allocating %d bytes\n", player->datasize);
- goto error;
- }
-
return 1;
error:
- closeAVFile(player->file);
+ closeAudioFile(player->file);
player->file = NULL;
- player->stream = NULL;
- player->datasize = 0;
return 0;
}
@@ -177,20 +157,15 @@ error:
/* Closes the audio file stream */
static void ClosePlayerFile(StreamPlayer *player)
{
- closeAVFile(player->file);
+ closeAudioFile(player->file);
player->file = NULL;
- player->stream = NULL;
-
- free(player->data);
- player->data = NULL;
- player->datasize = 0;
}
/* Prebuffers some audio from the file, and starts playing the source */
static int StartPlayer(StreamPlayer *player)
{
- size_t i, got;
+ size_t i;
/* Rewind the source position and clear the buffer queue */
alSourceRewind(player->source);
@@ -199,13 +174,16 @@ static int StartPlayer(StreamPlayer *player)
/* Fill the buffer queue */
for(i = 0;i < NUM_BUFFERS;i++)
{
+ uint8_t *data;
+ size_t got;
+
/* Get some data to give it to the buffer */
- got = readAVAudioData(player->stream, player->data, player->datasize);
- if(got == 0) break;
+ data = getAudioData(player->file, &got);
+ if(!data) break;
alBufferSamplesSOFT(player->buffers[i], player->rate, player->format,
BytesToFrames(got, player->channels, player->type),
- player->channels, player->type, player->data);
+ player->channels, player->type, data);
}
if(alGetError() != AL_NO_ERROR)
{
@@ -242,6 +220,7 @@ static int UpdatePlayer(StreamPlayer *player)
while(processed > 0)
{
ALuint bufid;
+ uint8_t *data;
size_t got;
alSourceUnqueueBuffers(player->source, 1, &bufid);
@@ -249,12 +228,12 @@ static int UpdatePlayer(StreamPlayer *player)
/* Read the next chunk of data, refill the buffer, and queue it
* back on the source */
- got = readAVAudioData(player->stream, player->data, player->datasize);
- if(got > 0)
+ data = getAudioData(player->file, &got);
+ if(data != NULL)
{
alBufferSamplesSOFT(bufid, player->rate, player->format,
BytesToFrames(got, player->channels, player->type),
- player->channels, player->type, player->data);
+ player->channels, player->type, data);
alSourceQueueBuffers(player->source, 1, &bufid);
}
if(alGetError() != AL_NO_ERROR)
diff --git a/examples/common/alhelpers.h b/examples/common/alhelpers.h
index eda8925e..62ed5be2 100644
--- a/examples/common/alhelpers.h
+++ b/examples/common/alhelpers.h
@@ -9,6 +9,10 @@
#include <windows.h>
#endif
+#include "AL/alc.h"
+#include "AL/al.h"
+#include "AL/alext.h"
+
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
diff --git a/examples/common/sdl_sound.c b/examples/common/sdl_sound.c
new file mode 100644
index 00000000..9e9f1d62
--- /dev/null
+++ b/examples/common/sdl_sound.c
@@ -0,0 +1,149 @@
+/*
+ * SDL_sound Decoder Helpers
+ *
+ * Copyright (c) 2013 by Chris Robinson <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/* This file contains routines for helping to decode audio using SDL_sound.
+ * There's very little OpenAL-specific code here.
+ */
+#include "sdl_sound.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <signal.h>
+#include <assert.h>
+
+#include <SDL_sound.h>
+
+#include "AL/al.h"
+#include "AL/alc.h"
+#include "AL/alext.h"
+
+#include "alhelpers.h"
+
+
+static int done_init = 0;
+
+FilePtr openAudioFile(const char *fname, size_t buftime_ms)
+{
+ FilePtr file;
+ ALuint rate;
+ Uint32 bufsize;
+ ALenum chans, type;
+
+ /* We need to make sure SDL_sound is initialized. */
+ if(!done_init)
+ {
+ Sound_Init();
+ done_init = 1;
+ }
+
+ file = Sound_NewSampleFromFile(fname, NULL, 0);
+ if(!file)
+ {
+ fprintf(stderr, "Failed to open %s: %s\n", fname, Sound_GetError());
+ return NULL;
+ }
+
+ if(getAudioInfo(file, &rate, &chans, &type) != 0)
+ {
+ Sound_FreeSample(file);
+ return NULL;
+ }
+
+ bufsize = FramesToBytes((ALsizei)(buftime_ms/1000.0*rate), chans, type);
+ if(Sound_SetBufferSize(file, bufsize) == 0)
+ {
+ fprintf(stderr, "Failed to set buffer size to %u bytes: %s\n", bufsize, Sound_GetError());
+ Sound_FreeSample(file);
+ return NULL;
+ }
+
+ return file;
+}
+
+void closeAudioFile(FilePtr file)
+{
+ if(file)
+ Sound_FreeSample(file);
+}
+
+
+int getAudioInfo(FilePtr file, ALuint *rate, ALenum *channels, ALenum *type)
+{
+ if(file->actual.channels == 1)
+ *channels = AL_MONO_SOFT;
+ else if(file->actual.channels == 2)
+ *channels = AL_STEREO_SOFT;
+ else
+ {
+ fprintf(stderr, "Unsupported channel count: %d\n", file->actual.channels);
+ return 1;
+ }
+
+ if(file->actual.format == AUDIO_U8)
+ *type = AL_UNSIGNED_BYTE_SOFT;
+ else if(file->actual.format == AUDIO_S8)
+ *type = AL_BYTE_SOFT;
+ else if(file->actual.format == AUDIO_U16SYS)
+ *type = AL_UNSIGNED_SHORT_SOFT;
+ else if(file->actual.format == AUDIO_S16SYS)
+ *type = AL_SHORT_SOFT;
+ else
+ {
+ fprintf(stderr, "Unsupported sample format: 0x%04x\n", file->actual.format);
+ return 1;
+ }
+
+ *rate = file->actual.rate;
+
+ return 0;
+}
+
+
+uint8_t *getAudioData(FilePtr file, size_t *length)
+{
+ *length = Sound_Decode(file);
+ if(*length == 0)
+ return NULL;
+ return file->buffer;
+}
+
+void *decodeAudioStream(FilePtr file, size_t *length)
+{
+ Uint32 got;
+ char *mem;
+
+ got = Sound_DecodeAll(file);
+ if(got == 0)
+ {
+ *length = 0;
+ return NULL;
+ }
+
+ mem = malloc(got);
+ memcpy(mem, file->buffer, got);
+
+ *length = got;
+ return mem;
+}
diff --git a/examples/common/sdl_sound.h b/examples/common/sdl_sound.h
new file mode 100644
index 00000000..e93ab92b
--- /dev/null
+++ b/examples/common/sdl_sound.h
@@ -0,0 +1,43 @@
+#ifndef EXAMPLES_SDL_SOUND_H
+#define EXAMPLES_SDL_SOUND_H
+
+#include "AL/al.h"
+
+#include <SDL_sound.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* Opaque handles to files and streams. Apps don't need to concern themselves
+ * with the internals */
+typedef Sound_Sample *FilePtr;
+
+/* Opens a file with SDL_sound, and specifies the size of the sample buffer in
+ * milliseconds. */
+FilePtr openAudioFile(const char *fname, size_t buftime_ms);
+
+/* Closes/frees an opened file */
+void closeAudioFile(FilePtr file);
+
+/* Returns information about the given audio stream. Returns 0 on success. */
+int getAudioInfo(FilePtr file, ALuint *rate, ALenum *channels, ALenum *type);
+
+/* Returns a pointer to the next available chunk of decoded audio. The size (in
+ * bytes) of the returned data buffer is stored in 'length', and the returned
+ * pointer is only valid until the next call to getAudioData. */
+uint8_t *getAudioData(FilePtr file, size_t *length);
+
+/* Decodes all remaining data from the stream and returns a buffer containing
+ * the audio data, with the size stored in 'length'. The returned pointer must
+ * be freed with a call to free(). Note that since this decodes the whole
+ * stream, using it on lengthy streams (eg, music) will use a lot of memory.
+ * Such streams are better handled using getAudioData to keep smaller chunks in
+ * memory at any given time. */
+void *decodeAudioStream(FilePtr, size_t *length);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* EXAMPLES_SDL_SOUND_H */