Use SDL_sound for the alstream example

This commit is contained in:
Chris Robinson
2013-06-05 19:44:42 -07:00
parent fe5428dc49
commit 056fa2a474
5 changed files with 239 additions and 48 deletions
+21 -5
View File
@@ -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}"
+22 -43
View File
@@ -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)
+4
View File
@@ -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 */
+149
View File
@@ -0,0 +1,149 @@
/*
* SDL_sound Decoder Helpers
*
* Copyright (c) 2013 by Chris Robinson <chris.kcat@gmail.com>
*
* 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;
}
+43
View File
@@ -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 */