forked from teamnwah/openmw-tes3coop
Combined OpenAL+Audiere sound test now compiles and runs, but segfaults
This commit is contained in:
parent
9e332c4067
commit
56f9daed96
13 changed files with 142 additions and 172 deletions
|
@ -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,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;
|
||||
OpenAL_Factory(bool doSetup = true);
|
||||
~OpenAL_Factory();
|
||||
|
||||
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(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;
|
||||
|
|
|
@ -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…
Reference in a new issue