Combined OpenAL+Audiere sound test now compiles and runs, but segfaults

actorid
Nicolay Korslund 15 years ago
parent 9e332c4067
commit 56f9daed96

@ -40,7 +40,6 @@ class InputFilter : public SoundFactory
// Set capabilities // Set capabilities
needsUpdate = snd->needsUpdate; needsUpdate = snd->needsUpdate;
has3D = snd->has3D; has3D = snd->has3D;
canRepeatStream = snd->canRepeatStream;
canLoadStream = inp->canLoadStream; canLoadStream = inp->canLoadStream;
// Both these should be true, or the use of this class is pretty // 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) virtual SoundPtr load(const std::string &file)
{ return load(inp->load(file), stream); } { return loadRaw(inp->load(file)); }
virtual SoundPtr load(Stream::StreamPtr input) virtual SoundPtr load(Stream::StreamPtr input)
{ return load(inp->load(input), stream); } { return loadRaw(inp->load(input)); }
virtual SoundPtr load(SampleSourcePtr input) virtual SoundPtr loadRaw(SampleSourcePtr input)
{ return snd->load(input, stream); } { return snd->loadRaw(input); }
virtual void update() { snd->update(); } virtual void update() { snd->update(); }
virtual void setListenerPos(float x, float y, float z, virtual void setListenerPos(float x, float y, float z,

@ -15,8 +15,8 @@ class OpenAL_Audiere_Factory : public InputFilter
public: public:
OpenAL_Audiere_Factory() OpenAL_Audiere_Factory()
{ {
set(new OpenAL_Factory, set(SoundFactoryPtr(new OpenAL_Factory),
new AudiereLoader); SampleSourceLoaderPtr(new AudiereLoader));
} }
}; };

@ -39,7 +39,7 @@ class Sound
virtual void pause() = 0; virtual void pause() = 0;
/// Check if the sound is still playing /// 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. /// Set the volume. The parameter must be between 0.0 and 1.0.
virtual void setVolume(float) = 0; virtual void setVolume(float) = 0;
@ -120,7 +120,7 @@ class SoundFactory
large files, but they are not required to. large files, but they are not required to.
@return a new Sound object @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 @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 @param stream true if the file should be streamed
@see load(InputSource*,bool) @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 @brief Load a sound directly from file. Only valid if canLoadFile

@ -1,6 +1,8 @@
#include "openal_out.h" #include "openal_out.h"
#include <assert.h> #include <assert.h>
#include "../../stream/filters/buffer_stream.h"
using namespace Mangle::Sound; using namespace Mangle::Sound;
// ---- Helper functions and classes ---- // ---- Helper functions and classes ----
@ -28,7 +30,7 @@ static void checkALError(const std::string &msg)
fail("\"" + std::string(alGetString(err)) + "\" while " + 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; int ch, bits;
inp->getInfo(&rate, &ch, &bits); inp->getInfo(&rate, &ch, &bits);
@ -61,6 +63,41 @@ static void getALFormat(InputStream *inp, int &fmt, int &rate)
fail("Unsupported input format"); 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 ---- // ---- OpenAL_Sound ----
void OpenAL_Sound::play() void OpenAL_Sound::play()
@ -81,7 +118,7 @@ void OpenAL_Sound::pause()
checkALError("pausing"); checkALError("pausing");
} }
bool OpenAL_Sound::isPlaying() bool OpenAL_Sound::isPlaying() const
{ {
ALint state; ALint state;
alGetSourcei(inst, AL_SOURCE_STATE, &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) 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 // Constructor used for cloned sounds
@ -121,11 +163,12 @@ OpenAL_Sound::OpenAL_Sound(ALuint buf, int *ref)
alSourcei(inst, AL_BUFFER, bufferID); alSourcei(inst, AL_BUFFER, bufferID);
} }
// Constructor used for original (non-cloned) sounds
OpenAL_Sound::OpenAL_Sound(SampleSourcePtr input) OpenAL_Sound::OpenAL_Sound(SampleSourcePtr input)
{ {
// Get the format // Get the format
int fmt, rate; int fmt, rate;
getALFormat(inp, fmt, rate); getALFormat(input, fmt, rate);
// Set up the OpenAL buffer // Set up the OpenAL buffer
alGenBuffers(1, &bufferID); alGenBuffers(1, &bufferID);
@ -135,15 +178,15 @@ OpenAL_Sound::OpenAL_Sound(SampleSourcePtr input)
if(input->hasPtr) if(input->hasPtr)
{ {
// If so, we can read the data directly from the stream // 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 else
{ {
// Read the entire stream into a temporary buffer first // Read the entire stream into a temporary buffer first
BufferStream buf(input); Mangle::Stream::BufferStream buf(input);
// Then copy that into OpenAL // 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"); checkALError("loading sound buffer");
@ -165,8 +208,8 @@ OpenAL_Sound::~OpenAL_Sound()
// Return sound // Return sound
alDeleteSources(1, &inst); alDeleteSources(1, &inst);
// Decrease the reference // Decrease the reference counter
if(--(*refCnt)) if((-- *refCnt) == 0)
{ {
// We're the last owner. Delete the buffer and the counter // We're the last owner. Delete the buffer and the counter
// itself. // itself.

@ -2,7 +2,6 @@
#define MANGLE_SOUND_OPENAL_OUT_H #define MANGLE_SOUND_OPENAL_OUT_H
#include "../output.h" #include "../output.h"
#include "../../stream/filters/buffer_stream.h"
#include <AL/al.h> #include <AL/al.h>
#include <AL/alc.h> #include <AL/alc.h>
@ -34,7 +33,7 @@ class OpenAL_Sound : public Sound
void setPos(float x, float y, float z); void setPos(float x, float y, float z);
void setRepeat(bool); void setRepeat(bool);
void setStreaming(bool) {} // Not implemented yet void setStreaming(bool) {} // Not implemented yet
Sound* clone() const; SoundPtr clone() const;
/// Not implemented /// Not implemented
void setPan(float) {} void setPan(float) {}
@ -50,48 +49,18 @@ class OpenAL_Factory : public SoundFactory
/// Initialize object. Pass true (default) if you want the /// Initialize object. Pass true (default) if you want the
/// constructor to set up the current ALCdevice and ALCcontext for /// constructor to set up the current ALCdevice and ALCcontext for
/// you. /// you.
OpenAL_Factory(bool doSetup = true) OpenAL_Factory(bool doSetup = true);
: didSetup(doSetup) ~OpenAL_Factory();
{
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);
}
}
SoundPtr load(const std::string &file, bool stream=false) { assert(0); } SoundPtr load(const std::string &file) { assert(0); }
SoundPtr load(Stream::StreamPtr input, bool stream=false) { assert(0); } SoundPtr load(Stream::StreamPtr input) { assert(0); }
SoundPtr load(SampleSourcePtr input, bool stream=false) SoundPtr loadRaw(SampleSourcePtr input)
{ return SoundPtr(new OpenAL_Sound(input)); } { return SoundPtr(new OpenAL_Sound(input)); }
void update() {} void update() {}
setListenerPos(float x, float y, float z, void setListenerPos(float x, float y, float z,
float fx, float fy, float fz, float fx, float fy, float fz,
float ux, float uy, float uz) float ux, float uy, float uz)
{ {
ALfloat orient[6]; ALfloat orient[6];
orient[0] = fx; orient[0] = fx;

@ -21,13 +21,13 @@ class SampleSource : public Stream::Stream
/// Get the sample rate, number of channels, and bits per /// Get the sample rate, number of channels, and bits per
/// sample. NULL parameters are ignored. /// 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; } bool eof() const { return isEof; }
// Disabled functions by default. You can still override them in // Disabled functions by default. You can still override them in
// subclasses. // subclasses.
void seek(size_t pos) const { assert(0); } void seek(size_t pos) { assert(0); }
size_t tell() const { assert(0); } size_t tell() const { assert(0); }
size_t size() const { assert(0); } size_t size() const { assert(0); }
}; };

@ -2,6 +2,8 @@
#include "../../stream/clients/audiere_file.h" #include "../../stream/clients/audiere_file.h"
using namespace Mangle::Stream;
// Exception handling // Exception handling
class Audiere_Exception : public std::exception class Audiere_Exception : public std::exception
{ {
@ -109,11 +111,11 @@ AudiereSource::AudiereSource(const std::string &file)
setup(); setup();
} }
AudiereSource::AudiereSource(Stream::StreamPtr input) AudiereSource::AudiereSource(StreamPtr input)
{ {
// Use our Stream::AudiereFile implementation to convert a Mangle // Use our Stream::AudiereFile implementation to convert a Mangle
// 'Stream' to an Audiere 'File' // 'Stream' to an Audiere 'File'
sample = OpenSampleSource(new Stream::AudiereFile(input)); sample = OpenSampleSource(new AudiereFile(input));
if(!sample) if(!sample)
fail("Couldn't load stream"); fail("Couldn't load stream");
@ -125,7 +127,7 @@ AudiereSource::AudiereSource(audiere::SampleSourcePtr src)
{ assert(sample); setup(); } { assert(sample); setup(); }
// Common function called from all constructors // Common function called from all constructors
AudiereSource::setup() void AudiereSource::setup()
{ {
assert(sample); assert(sample);

@ -26,14 +26,14 @@ class AudiereSource : public SampleSource
// How much of the above buffer is in use // How much of the above buffer is in use
int pullSize; int pullSize;
void getFormat(); void setup();
public: public:
/// Decode the given sound file /// Decode the given sound file
AudiereSource(const std::string &file); AudiereSource(const std::string &file);
/// Decode the given sound stream /// Decode the given sound stream
AudiereSource(Stream::StreamPtr src); AudiereSource(Mangle::Stream::StreamPtr src);
/// Read directly from an existing audiere::SampleSource /// Read directly from an existing audiere::SampleSource
AudiereSource(audiere::SampleSourcePtr src); AudiereSource(audiere::SampleSourcePtr src);
@ -41,9 +41,9 @@ class AudiereSource : public SampleSource
void getInfo(int32_t *rate, int32_t *channels, int32_t *bits); void getInfo(int32_t *rate, int32_t *channels, int32_t *bits);
size_t read(void *data, size_t length); size_t read(void *data, size_t length);
void seek(size_t pos) const { sample->setPosition(pos); } void seek(size_t pos) { sample->setPosition(pos/frameSize); }
size_t tell() const { return sample->getPosition(); } size_t tell() const { return sample->getPosition()*frameSize; }
size_t size() const { return sample->getLength(); } size_t size() const { return sample->getLength()*frameSize; }
}; };
#include "loadertemplate.h" #include "loadertemplate.h"

@ -4,22 +4,24 @@
template <class SourceT, bool stream, bool file> template <class SourceT, bool stream, bool file>
class SSL_Template : public SampleSourceLoader class SSL_Template : public SampleSourceLoader
{ {
public:
SSL_Template() SSL_Template()
{ {
canLoadStream = stream; canLoadStream = stream;
canLoadFile = file; canLoadFile = file;
} }
SampleSource *load(const std::string &file) SampleSourcePtr load(const std::string &filename)
{ {
assert(canLoadFile); assert(canLoadFile);
return new SourceT(file); return SampleSourcePtr(new SourceT(filename));
} }
SampleSource *load(Stream::StreamPtr input) SampleSourcePtr load(Stream::StreamPtr input)
{ {
assert(canLoadStream); assert(canLoadStream);
return new SourceT(input); return SampleSourcePtr(new SourceT(input));
} }
}; };

@ -1,19 +1,13 @@
GCC=g++ -I../ 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_OPENAL=$(shell pkg-config --libs openal)
L_AUDIERE=-laudiere L_AUDIERE=-laudiere
ffmpeg_openal_test: ffmpeg_openal_test.cpp ../servers/input_ffmpeg.cpp ../servers/output_openal.cpp openal_audiere_test: openal_audiere_test.cpp ../sources/audiere_source.cpp ../outputs/openal_out.cpp ../../stream/clients/audiere_file.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
$(GCC) $^ -o $@ $(L_AUDIERE) $(L_OPENAL) $(GCC) $^ -o $@ $(L_AUDIERE) $(L_OPENAL)
audiere_test: audiere_test.cpp ../servers/audiere_imp.cpp
$(GCC) $^ -o $@ $(L_AUDIERE)
clean: clean:
rm *_test rm *_test

@ -1,89 +0,0 @@
// This file is included directly into the test programs
#include <iostream>
#include <fstream>
#include <exception>
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;
}

@ -1,7 +1,54 @@
#include <iostream>
#include <fstream>
#include <exception>
#include "../../stream/servers/file_stream.h"
#include "../../stream/filters/buffer_stream.h"
#include "../filters/openal_audiere.h" #include "../filters/openal_audiere.h"
using namespace std;
using namespace Mangle::Stream;
using namespace Mangle::Sound; using namespace Mangle::Sound;
OpenAL_Audiere_Factory mg; 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;
}

@ -10,6 +10,7 @@ namespace Stream {
/** A Stream that reads another Stream into a buffer, and serves it as /** A Stream that reads another Stream into a buffer, and serves it as
a MemoryStream. Might be expanded with other capabilities later. a MemoryStream. Might be expanded with other capabilities later.
*/ */
class BufferStream : public MemoryStream class BufferStream : public MemoryStream
{ {
std::vector<char> buffer; std::vector<char> buffer;
@ -17,6 +18,8 @@ class BufferStream : public MemoryStream
public: public:
BufferStream(StreamPtr input) BufferStream(StreamPtr input)
{ {
assert(input);
// Allocate memory, read the stream into it. Then call set() // Allocate memory, read the stream into it. Then call set()
if(input->hasSize) if(input->hasSize)
{ {

Loading…
Cancel
Save