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
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,

@ -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));
}
};

@ -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

@ -1,6 +1,8 @@
#include "openal_out.h"
#include <assert.h>
#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.

@ -2,7 +2,6 @@
#define MANGLE_SOUND_OPENAL_OUT_H
#include "../output.h"
#include "../../stream/filters/buffer_stream.h"
#include <AL/al.h>
#include <AL/alc.h>
@ -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,46 +49,16 @@ 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,
void setListenerPos(float x, float y, float z,
float fx, float fy, float fz,
float ux, float uy, float uz)
{

@ -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); }
};

@ -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);

@ -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"

@ -4,22 +4,24 @@
template <class SourceT, bool stream, bool file>
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));
}
};

@ -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

@ -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"
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;
}

@ -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<char> 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)
{

Loading…
Cancel
Save