From 56f9daed9685e2b6f36b15c300f61cfc006030fd Mon Sep 17 00:00:00 2001 From: Nicolay Korslund Date: Fri, 1 Jan 2010 18:42:35 +0100 Subject: [PATCH] Combined OpenAL+Audiere sound test now compiles and runs, but segfaults --- sound/filters/input_filter.h | 9 ++- sound/filters/openal_audiere.h | 4 +- sound/output.h | 6 +- sound/outputs/openal_out.cpp | 61 +++++++++++++++++--- sound/outputs/openal_out.h | 49 +++------------- sound/source.h | 4 +- sound/sources/audiere_source.cpp | 8 ++- sound/sources/audiere_source.h | 10 ++-- sound/sources/loadertemplate.h | 10 ++-- sound/tests/Makefile | 12 +--- sound/tests/common.cpp | 89 ----------------------------- sound/tests/openal_audiere_test.cpp | 49 +++++++++++++++- stream/filters/buffer_stream.h | 3 + 13 files changed, 142 insertions(+), 172 deletions(-) delete mode 100644 sound/tests/common.cpp diff --git a/sound/filters/input_filter.h b/sound/filters/input_filter.h index 17dda5534..2b4486b75 100644 --- a/sound/filters/input_filter.h +++ b/sound/filters/input_filter.h @@ -40,7 +40,6 @@ class InputFilter : public SoundFactory // Set capabilities needsUpdate = snd->needsUpdate; has3D = snd->has3D; - canRepeatStream = snd->canRepeatStream; canLoadStream = inp->canLoadStream; // Both these should be true, or the use of this class is pretty @@ -51,13 +50,13 @@ class InputFilter : public SoundFactory } virtual SoundPtr load(const std::string &file) - { return load(inp->load(file), stream); } + { return loadRaw(inp->load(file)); } virtual SoundPtr load(Stream::StreamPtr input) - { return load(inp->load(input), stream); } + { return loadRaw(inp->load(input)); } - virtual SoundPtr load(SampleSourcePtr input) - { return snd->load(input, stream); } + virtual SoundPtr loadRaw(SampleSourcePtr input) + { return snd->loadRaw(input); } virtual void update() { snd->update(); } virtual void setListenerPos(float x, float y, float z, diff --git a/sound/filters/openal_audiere.h b/sound/filters/openal_audiere.h index 9a2bfcf8c..a1b2e6b64 100644 --- a/sound/filters/openal_audiere.h +++ b/sound/filters/openal_audiere.h @@ -15,8 +15,8 @@ class OpenAL_Audiere_Factory : public InputFilter public: OpenAL_Audiere_Factory() { - set(new OpenAL_Factory, - new AudiereLoader); + set(SoundFactoryPtr(new OpenAL_Factory), + SampleSourceLoaderPtr(new AudiereLoader)); } }; diff --git a/sound/output.h b/sound/output.h index dfd190241..6bcd93237 100644 --- a/sound/output.h +++ b/sound/output.h @@ -39,7 +39,7 @@ class Sound virtual void pause() = 0; /// Check if the sound is still playing - virtual bool isPlaying() = 0 const; + virtual bool isPlaying() const = 0; /// Set the volume. The parameter must be between 0.0 and 1.0. virtual void setVolume(float) = 0; @@ -120,7 +120,7 @@ class SoundFactory large files, but they are not required to. @return a new Sound object */ - virtual SoundPtr load(SampleSource *input) = 0; + virtual SoundPtr loadRaw(SampleSourcePtr input) = 0; /** @brief Load a sound file from stream. Only valid if canLoadStream @@ -130,7 +130,7 @@ class SoundFactory @param stream true if the file should be streamed @see load(InputSource*,bool) */ - virtual SoundPtr load(Stream::Stream *input) = 0; + virtual SoundPtr load(Stream::StreamPtr input) = 0; /** @brief Load a sound directly from file. Only valid if canLoadFile diff --git a/sound/outputs/openal_out.cpp b/sound/outputs/openal_out.cpp index 910690156..99b976bc9 100644 --- a/sound/outputs/openal_out.cpp +++ b/sound/outputs/openal_out.cpp @@ -1,6 +1,8 @@ #include "openal_out.h" #include +#include "../../stream/filters/buffer_stream.h" + using namespace Mangle::Sound; // ---- Helper functions and classes ---- @@ -28,7 +30,7 @@ static void checkALError(const std::string &msg) fail("\"" + std::string(alGetString(err)) + "\" while " + msg); } -static void getALFormat(InputStream *inp, int &fmt, int &rate) +static void getALFormat(SampleSourcePtr inp, int &fmt, int &rate) { int ch, bits; inp->getInfo(&rate, &ch, &bits); @@ -61,6 +63,41 @@ static void getALFormat(InputStream *inp, int &fmt, int &rate) fail("Unsupported input format"); } +// ---- OpenAL_Factory ---- + +OpenAL_Factory::OpenAL_Factory(bool doSetup) + : didSetup(doSetup) +{ + needsUpdate = false; + has3D = true; + canLoadFile = false; + canLoadStream = false; + canLoadSource = true; + + if(doSetup) + { + // Set up sound system + Device = alcOpenDevice(NULL); + Context = alcCreateContext(Device, NULL); + + if(!Device || !Context) + fail("Failed to initialize context or device"); + + alcMakeContextCurrent(Context); + } +} + +OpenAL_Factory::~OpenAL_Factory() +{ + // Deinitialize sound system + if(didSetup) + { + alcMakeContextCurrent(NULL); + if(Context) alcDestroyContext(Context); + if(Device) alcCloseDevice(Device); + } +} + // ---- OpenAL_Sound ---- void OpenAL_Sound::play() @@ -81,7 +118,7 @@ void OpenAL_Sound::pause() checkALError("pausing"); } -bool OpenAL_Sound::isPlaying() +bool OpenAL_Sound::isPlaying() const { ALint state; alGetSourcei(inst, AL_SOURCE_STATE, &state); @@ -105,7 +142,12 @@ void OpenAL_Sound::setPos(float x, float y, float z) void OpenAL_Sound::setRepeat(bool rep) { - alSourcei(Source, AL_LOOPING, rep?AL_TRUE:AL_FALSE); + alSourcei(inst, AL_LOOPING, rep?AL_TRUE:AL_FALSE); +} + +SoundPtr OpenAL_Sound::clone() const +{ + return SoundPtr(new OpenAL_Sound(bufferID, refCnt)); } // Constructor used for cloned sounds @@ -121,11 +163,12 @@ OpenAL_Sound::OpenAL_Sound(ALuint buf, int *ref) alSourcei(inst, AL_BUFFER, bufferID); } +// Constructor used for original (non-cloned) sounds OpenAL_Sound::OpenAL_Sound(SampleSourcePtr input) { // Get the format int fmt, rate; - getALFormat(inp, fmt, rate); + getALFormat(input, fmt, rate); // Set up the OpenAL buffer alGenBuffers(1, &bufferID); @@ -135,15 +178,15 @@ OpenAL_Sound::OpenAL_Sound(SampleSourcePtr input) if(input->hasPtr) { // If so, we can read the data directly from the stream - alBufferData(bufferID, fmt, &input.getPtr(), input.size(), rate); + alBufferData(bufferID, fmt, input->getPtr(), input->size(), rate); } else { // Read the entire stream into a temporary buffer first - BufferStream buf(input); + Mangle::Stream::BufferStream buf(input); // Then copy that into OpenAL - alBufferData(bufferID, fmt, &buf.getPtr(), buf.size(), rate); + alBufferData(bufferID, fmt, buf.getPtr(), buf.size(), rate); } checkALError("loading sound buffer"); @@ -165,8 +208,8 @@ OpenAL_Sound::~OpenAL_Sound() // Return sound alDeleteSources(1, &inst); - // Decrease the reference - if(--(*refCnt)) + // Decrease the reference counter + if((-- *refCnt) == 0) { // We're the last owner. Delete the buffer and the counter // itself. diff --git a/sound/outputs/openal_out.h b/sound/outputs/openal_out.h index 115c3c13e..335880cda 100644 --- a/sound/outputs/openal_out.h +++ b/sound/outputs/openal_out.h @@ -2,7 +2,6 @@ #define MANGLE_SOUND_OPENAL_OUT_H #include "../output.h" -#include "../../stream/filters/buffer_stream.h" #include #include @@ -34,7 +33,7 @@ class OpenAL_Sound : public Sound void setPos(float x, float y, float z); void setRepeat(bool); void setStreaming(bool) {} // Not implemented yet - Sound* clone() const; + SoundPtr clone() const; /// Not implemented void setPan(float) {} @@ -50,48 +49,18 @@ class OpenAL_Factory : public SoundFactory /// Initialize object. Pass true (default) if you want the /// constructor to set up the current ALCdevice and ALCcontext for /// you. - OpenAL_Factory(bool doSetup = true) - : didSetup(doSetup) - { - needsUpdate = false; - has3D = true; - canLoadFile = false; - canLoadStream = false; - canLoadSource = true; - - if(doSetup) - { - // Set up sound system - Device = alcOpenDevice(NULL); - Context = alcCreateContext(Device, NULL); - - if(!Device || !Context) - fail("Failed to initialize context or device"); - - alcMakeContextCurrent(Context); - } - } - - ~OpenAL_Factory() - { - // Deinitialize sound system - if(didSetup) - { - alcMakeContextCurrent(NULL); - if(Context) alcDestroyContext(Context); - if(Device) alcCloseDevice(Device); - } - } + OpenAL_Factory(bool doSetup = true); + ~OpenAL_Factory(); - SoundPtr load(const std::string &file, bool stream=false) { assert(0); } - SoundPtr load(Stream::StreamPtr input, bool stream=false) { assert(0); } - SoundPtr load(SampleSourcePtr input, bool stream=false) + SoundPtr load(const std::string &file) { assert(0); } + SoundPtr load(Stream::StreamPtr input) { assert(0); } + SoundPtr loadRaw(SampleSourcePtr input) { return SoundPtr(new OpenAL_Sound(input)); } void update() {} - setListenerPos(float x, float y, float z, - float fx, float fy, float fz, - float ux, float uy, float uz) + void setListenerPos(float x, float y, float z, + float fx, float fy, float fz, + float ux, float uy, float uz) { ALfloat orient[6]; orient[0] = fx; diff --git a/sound/source.h b/sound/source.h index f987dfe4f..d5468b518 100644 --- a/sound/source.h +++ b/sound/source.h @@ -21,13 +21,13 @@ class SampleSource : public Stream::Stream /// Get the sample rate, number of channels, and bits per /// sample. NULL parameters are ignored. - virtual void getInfo(int32_t *rate, int32_t *channels, int32_t *bits) const = 0; + virtual void getInfo(int32_t *rate, int32_t *channels, int32_t *bits) = 0; bool eof() const { return isEof; } // Disabled functions by default. You can still override them in // subclasses. - void seek(size_t pos) const { assert(0); } + void seek(size_t pos) { assert(0); } size_t tell() const { assert(0); } size_t size() const { assert(0); } }; diff --git a/sound/sources/audiere_source.cpp b/sound/sources/audiere_source.cpp index 1a0dfe8dc..8da4fe3c7 100644 --- a/sound/sources/audiere_source.cpp +++ b/sound/sources/audiere_source.cpp @@ -2,6 +2,8 @@ #include "../../stream/clients/audiere_file.h" +using namespace Mangle::Stream; + // Exception handling class Audiere_Exception : public std::exception { @@ -109,11 +111,11 @@ AudiereSource::AudiereSource(const std::string &file) setup(); } -AudiereSource::AudiereSource(Stream::StreamPtr input) +AudiereSource::AudiereSource(StreamPtr input) { // Use our Stream::AudiereFile implementation to convert a Mangle // 'Stream' to an Audiere 'File' - sample = OpenSampleSource(new Stream::AudiereFile(input)); + sample = OpenSampleSource(new AudiereFile(input)); if(!sample) fail("Couldn't load stream"); @@ -125,7 +127,7 @@ AudiereSource::AudiereSource(audiere::SampleSourcePtr src) { assert(sample); setup(); } // Common function called from all constructors -AudiereSource::setup() +void AudiereSource::setup() { assert(sample); diff --git a/sound/sources/audiere_source.h b/sound/sources/audiere_source.h index 671595a1a..e2d09d006 100644 --- a/sound/sources/audiere_source.h +++ b/sound/sources/audiere_source.h @@ -26,14 +26,14 @@ class AudiereSource : public SampleSource // How much of the above buffer is in use int pullSize; - void getFormat(); + void setup(); public: /// Decode the given sound file AudiereSource(const std::string &file); /// Decode the given sound stream - AudiereSource(Stream::StreamPtr src); + AudiereSource(Mangle::Stream::StreamPtr src); /// Read directly from an existing audiere::SampleSource AudiereSource(audiere::SampleSourcePtr src); @@ -41,9 +41,9 @@ class AudiereSource : public SampleSource void getInfo(int32_t *rate, int32_t *channels, int32_t *bits); size_t read(void *data, size_t length); - void seek(size_t pos) const { sample->setPosition(pos); } - size_t tell() const { return sample->getPosition(); } - size_t size() const { return sample->getLength(); } + void seek(size_t pos) { sample->setPosition(pos/frameSize); } + size_t tell() const { return sample->getPosition()*frameSize; } + size_t size() const { return sample->getLength()*frameSize; } }; #include "loadertemplate.h" diff --git a/sound/sources/loadertemplate.h b/sound/sources/loadertemplate.h index f1ebea2d5..a27a77d10 100644 --- a/sound/sources/loadertemplate.h +++ b/sound/sources/loadertemplate.h @@ -4,22 +4,24 @@ template class SSL_Template : public SampleSourceLoader { + public: + SSL_Template() { canLoadStream = stream; canLoadFile = file; } - SampleSource *load(const std::string &file) + SampleSourcePtr load(const std::string &filename) { assert(canLoadFile); - return new SourceT(file); + return SampleSourcePtr(new SourceT(filename)); } - SampleSource *load(Stream::StreamPtr input) + SampleSourcePtr load(Stream::StreamPtr input) { assert(canLoadStream); - return new SourceT(input); + return SampleSourcePtr(new SourceT(input)); } }; diff --git a/sound/tests/Makefile b/sound/tests/Makefile index 8a9c74812..ca7a933c6 100644 --- a/sound/tests/Makefile +++ b/sound/tests/Makefile @@ -1,19 +1,13 @@ GCC=g++ -I../ -all: audiere_test ffmpeg_openal_test openal_audiere_test +all: openal_audiere_test -L_FFMPEG=$(shell pkg-config --libs libavcodec libavformat) +#L_FFMPEG=$(shell pkg-config --libs libavcodec libavformat) L_OPENAL=$(shell pkg-config --libs openal) L_AUDIERE=-laudiere -ffmpeg_openal_test: ffmpeg_openal_test.cpp ../servers/input_ffmpeg.cpp ../servers/output_openal.cpp - $(GCC) $^ -o $@ $(L_FFMPEG) $(L_OPENAL) - -openal_audiere_test: openal_audiere_test.cpp ../servers/input_audiere.cpp ../servers/output_openal.cpp ../../stream/clients/audiere_file.cpp +openal_audiere_test: openal_audiere_test.cpp ../sources/audiere_source.cpp ../outputs/openal_out.cpp ../../stream/clients/audiere_file.cpp $(GCC) $^ -o $@ $(L_AUDIERE) $(L_OPENAL) -audiere_test: audiere_test.cpp ../servers/audiere_imp.cpp - $(GCC) $^ -o $@ $(L_AUDIERE) - clean: rm *_test diff --git a/sound/tests/common.cpp b/sound/tests/common.cpp deleted file mode 100644 index 818d1645f..000000000 --- a/sound/tests/common.cpp +++ /dev/null @@ -1,89 +0,0 @@ -// This file is included directly into the test programs - -#include -#include -#include - -using namespace std; - -class TestStream : public Mangle::Stream::Stream -{ - ifstream io; - -public: - - TestStream(const char* name) - { - io.open(name, ios::binary); - isSeekable = true; - hasPosition = true; - hasSize = false; - } - - size_t read(void* buf, size_t len) - { - io.read((char*)buf, len); - return io.gcount(); - } - - void seek(size_t pos) - { - io.seekg(pos); - } - - size_t tell() const - { return ((TestStream*)this)->io.tellg(); } - - size_t size() const - { return 0; } - - bool eof() const - { return io.eof(); } -}; - -void play(const char* name, bool music=false, bool stream=false) -{ - // Only load streams if the backend supports it - if(stream && !mg.canLoadStream) - return; - - cout << "Playing " << name; - if(stream) cout << " (from stream)"; - cout << "\n"; - - Sound *snd = NULL; - Instance *s = NULL; - - try - { - if(stream) - snd = mg.load(new TestStream(name), music); - else - snd = mg.load(name, music); - - - s = snd->getInstance(false, false); - s->play(); - - while(s->isPlaying()) - { - usleep(10000); - if(mg.needsUpdate) mg.update(); - } - } - catch(exception &e) - { - cout << " ERROR: " << e.what() << "\n"; - } - - if(s) s->drop(); - if(snd) snd->drop(); -} - -int main() -{ - play("cow.wav"); - play("owl.ogg", true); - play("cow.wav", false, true); - return 0; -} diff --git a/sound/tests/openal_audiere_test.cpp b/sound/tests/openal_audiere_test.cpp index 3036e02a2..a39ae3d98 100644 --- a/sound/tests/openal_audiere_test.cpp +++ b/sound/tests/openal_audiere_test.cpp @@ -1,7 +1,54 @@ +#include +#include +#include + +#include "../../stream/servers/file_stream.h" +#include "../../stream/filters/buffer_stream.h" #include "../filters/openal_audiere.h" +using namespace std; +using namespace Mangle::Stream; using namespace Mangle::Sound; OpenAL_Audiere_Factory mg; -#include "common.cpp" +void play(const char* name, bool stream=false) +{ + // Only load streams if the backend supports it + if(stream && !mg.canLoadStream) + return; + + cout << "Playing " << name; + if(stream) cout << " (from stream)"; + cout << "\n"; + + SoundPtr snd; + + try + { + if(stream) + snd = mg.load(StreamPtr(new FileStream(name))); + else + snd = mg.load(name); + + snd->play(); + + while(snd->isPlaying()) + { + usleep(10000); + if(mg.needsUpdate) mg.update(); + } + } + catch(exception &e) + { + cout << " ERROR: " << e.what() << "\n"; + } +} + +int main() +{ + play("cow.wav"); + play("owl.ogg"); + play("cow.wav", true); + return 0; +} diff --git a/stream/filters/buffer_stream.h b/stream/filters/buffer_stream.h index f04411f98..d1af09a8c 100644 --- a/stream/filters/buffer_stream.h +++ b/stream/filters/buffer_stream.h @@ -10,6 +10,7 @@ namespace Stream { /** A Stream that reads another Stream into a buffer, and serves it as a MemoryStream. Might be expanded with other capabilities later. */ + class BufferStream : public MemoryStream { std::vector buffer; @@ -17,6 +18,8 @@ class BufferStream : public MemoryStream public: BufferStream(StreamPtr input) { + assert(input); + // Allocate memory, read the stream into it. Then call set() if(input->hasSize) {