Finished first rewrite draft. Not done or tested, but good enough for now.

actorid
Nicolay Korslund 15 years ago
parent aafe01dccc
commit d60f0fa900

@ -1,7 +1,7 @@
#ifndef MANGLE_INPUT_FILTER_H
#define MANGLE_INPUT_FILTER_H
#include "../sound.h"
#include "../output.h"
#include <assert.h>
@ -10,39 +10,29 @@ namespace Sound {
/**
@brief This filter class adds file loading capabilities to a
Sound::Manager class, by associating an InputManager with it.
Sound::SoundFactory class, by associating an SampleSourceLoader
with it.
The class takes an existing Manager able to load streams, and
associates an InputManager with it. The combined class is able to
load files directly.
Example:
\code
// Add FFmpeg input to an OpenAL soud output manager. OpenAL cannot
// decode sound files on its own.
InputFilter mg(new OpenAL_Manager, new FFM_InputManager);
// We can now load filenames directly.
mg.load("file1.mp3");
\endcode
The class takes an existing SoundFactory able to load streams, and
associates an SampleSourceLoader with it. The combined class is
able to load files directly.
*/
class InputFilter : public Manager
class InputFilter : public SoundFactory
{
protected:
Manager *snd;
InputManager *inp;
SoundFactory *snd;
SampleSourceLoader *inp;
public:
/// Empty constructor
InputFilter() {}
/// Assign an input manager and a sound manager to this object
InputFilter(Manager *_snd, InputManager *_inp)
InputFilter(SoundFactory *_snd, SampleSourceLoader *_inp)
{ set(_snd, _inp); }
/// Assign an input manager and a sound manager to this object
void set(Manager *_snd, InputManager *_inp)
void set(SoundFactory *_snd, SampleSourceLoader *_inp)
{
inp = _inp;
snd = _snd;

@ -2,23 +2,23 @@
#define MANGLE_FFMPEG_OPENAL_H
#include "input_filter.h"
#include "input_audiere.h"
#include "output_openal.h"
#include "../sources/audiere_source.h"
#include "../outputs/openal_out.h"
namespace Mangle {
namespace Sound {
/// A InputFilter that adds audiere decoding to OpenAL. Audiere has
/// it's own output, but OpenAL sports 3D and other advanced features.
class OpenAL_Audiere_Manager : public InputFilter
class OpenAL_Audiere_Factory : public InputFilter
{
public:
OpenAL_Audiere_Manager()
OpenAL_Audiere_Factory()
{
set(new OpenAL_Manager,
new AudiereInput);
set(new OpenAL_Factory,
new AudiereLoader);
}
~OpenAL_Audiere_Manager()
~OpenAL_Audiere_Factory()
{
delete snd;
delete inp;

@ -1,8 +1,6 @@
#include "openal_out.h"
#include <assert.h>
// ALuint bufferID;
using namespace Mangle::Sound;
// ---- Helper functions and classes ----
@ -65,11 +63,6 @@ static void getALFormat(InputStream *inp, int &fmt, int &rate)
// ---- OpenAL_Sound ----
OpenAL_Sound::OpenAL_Sound(SampleSource *input)
{
}
void OpenAL_Sound::play()
{
alSourcePlay(inst);
@ -110,174 +103,34 @@ void OpenAL_Sound::setPos(float x, float y, float z)
checkALError("setting position");
}
Instance *OpenAL_Sound::getInstance(bool is3d, bool repeat)
OpenAL_Sound::OpenAL_Sound(SampleSource *input)
{
assert((!repeat || !stream) && "OpenAL implementation does not support looping streams");
if(stream)
return new OpenAL_Stream_Instance(source->getStream(), owner);
// Load the buffer if it hasn't been done already
if(bufferID == 0)
{
// Get an input stream and load the file from it
InputStream *inp = source->getStream();
std::vector<unsigned char> buffer;
// Get the format
int fmt, rate;
getALFormat(inp, fmt, rate);
// Add 32 kb at each increment
const int ADD = 32*1024;
// Read the entire stream into a buffer
BufferStream buf(input);
// Fill the buffer. We increase the buffer until it's large
// enough to fit all the data.
while(true)
{
// Increase the buffer
int oldlen = buffer.size();
buffer.resize(oldlen+ADD);
// Read the data
size_t len = inp->getData(&buffer[oldlen], ADD);
// If we read less than requested, we're done.
if(len < ADD)
{
// Downsize the buffer to the right size
buffer.resize(oldlen+len);
break;
}
}
// Get the format
int fmt, rate;
getALFormat(inp, fmt, rate);
// We don't need the file anymore
inp->drop();
source->drop();
source = NULL;
// Move the data into OpenAL
alGenBuffers(1, &bufferID);
alBufferData(bufferID, fmt, &buffer[0], buffer.size(), rate);
checkALError("loading sound buffer");
} // End of buffer loading
// At this point, the file data has been loaded into the buffer
// in 'bufferID', and we should be ready to go.
// Move the data into OpenAL
alGenBuffers(1, &bufferID);
assert(bufferID != 0);
alBufferData(bufferID, fmt, &buf.getPtr(), buf.size(), rate);
checkALError("loading sound buffer");
return new OpenAL_Simple_Instance(bufferID);
}
// ---- OpenAL_Simple_Instance ----
OpenAL_Simple_Instance::OpenAL_Simple_Instance(ALuint buf)
{
// Create instance and associate buffer
// Create a source
alGenSources(1, &inst);
alSourcei(inst, AL_BUFFER, buf);
}
OpenAL_Simple_Instance::~OpenAL_Simple_Instance()
OpenAL_Sound::~OpenAL_Sound()
{
// Stop
alSourceStop(inst);
// Return sound
alDeleteSources(1, &inst);
}
// ---- OpenAL_Stream_Instance ----
OpenAL_Stream_Instance::OpenAL_Stream_Instance(InputStream *_stream,
OpenAL_Manager *_owner)
: stream(_stream), owner(_owner)
{
// Deduce the file format from the stream info
getALFormat(stream, fmt, rate);
// Create the buffers and the sound instance
alGenBuffers(BUFS, bufs);
alGenSources(1, &inst);
checkALError("initializing");
// Fill the buffers and que them
for(int i=0; i<BUFS; i++)
queueBuffer(bufs[i]);
checkALError("buffering initial data");
// Add ourselves to the stream list
lit = owner->add_stream(this);
}
void OpenAL_Stream_Instance::queueBuffer(ALuint bId)
{
char buf[SIZE];
// Get the data
int len = stream->getData(buf, SIZE);
if(len == 0)
return;
// .. and stash it
alBufferData(bId, fmt, buf, len, rate);
alSourceQueueBuffers(inst, 1, &bId);
}
OpenAL_Stream_Instance::~OpenAL_Stream_Instance()
{
// Remove ourselves from streaming list
owner->remove_stream(lit);
// Stop
alSourceStop(inst);
// Kill the input stream
stream->drop();
// Return sound
alDeleteSources(1, &inst);
// Delete buffers
alDeleteBuffers(BUFS, bufs);
}
void OpenAL_Stream_Instance::update()
{
ALint count;
alGetSourcei(inst, AL_BUFFERS_PROCESSED, &count);
for(int i = 0;i < count;i++)
{
// Unque a finished buffer
ALuint bId;
alSourceUnqueueBuffers(inst, 1, &bId);
// Queue a new buffer
queueBuffer(bId);
}
// Delete buffer
alDeleteBuffers(1, &bufferID);
}

@ -2,6 +2,7 @@
#define MANGLE_SOUND_OPENAL_OUT_H
#include "../output.h"
#include "../../stream/filters/buffer_stream.h"
#include <AL/al.h>
#include <AL/alc.h>
@ -15,6 +16,7 @@ class OpenAL_Sound : public Sound
{
protected:
ALuint inst;
ALuint bufferID;
public:
OpenAL_Sound(SampleSource *input);
@ -39,7 +41,7 @@ class OpenAL_Sound : public Sound
void setPos(float x, float y, float z);
};
class OpenALFactory : public SoundFactory
class OpenAL_Factory : public SoundFactory
{
ALCdevice *Device;
ALCcontext *Context;
@ -49,7 +51,7 @@ class OpenALFactory : public SoundFactory
/// Initialize object. Pass true (default) if you want the
/// constructor to set up the current ALCdevice and ALCcontext for
/// you.
OpenALFactory(bool doSetup = true)
OpenAL_Factory(bool doSetup = true)
: didSetup(doSetup)
{
needsUpdate = false;
@ -72,7 +74,7 @@ class OpenALFactory : public SoundFactory
}
}
~OpenALFactory()
~OpenAL_Factory()
{
// Deinitialize sound system
if(didSetup)

@ -1,7 +0,0 @@
#include "audiere_imp.h"
using namespace Mangle::Sound;
AudiereManager mg;
#include "common.cpp"

@ -1,7 +0,0 @@
#include "openal_ffmpeg.h"
using namespace Mangle::Sound;
OpenAL_FFM_Manager mg;
#include "common.cpp"

@ -1,7 +1,7 @@
#include "openal_audiere.h"
#include "../filters/openal_audiere.h"
using namespace Mangle::Sound;
OpenAL_Audiere_Manager mg;
OpenAL_Audiere_Factory mg;
#include "common.cpp"

Loading…
Cancel
Save