1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-03-27 04:10:24 +00:00

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

This commit is contained in:
Nicolay Korslund 2009-12-30 12:29:24 +01:00
parent aafe01dccc
commit d60f0fa900
7 changed files with 40 additions and 209 deletions

View file

@ -1,7 +1,7 @@
#ifndef MANGLE_INPUT_FILTER_H #ifndef MANGLE_INPUT_FILTER_H
#define MANGLE_INPUT_FILTER_H #define MANGLE_INPUT_FILTER_H
#include "../sound.h" #include "../output.h"
#include <assert.h> #include <assert.h>
@ -10,39 +10,29 @@ namespace Sound {
/** /**
@brief This filter class adds file loading capabilities to a @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 The class takes an existing SoundFactory able to load streams, and
associates an InputManager with it. The combined class is able to associates an SampleSourceLoader with it. The combined class is
load files directly. 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
*/ */
class InputFilter : public Manager class InputFilter : public SoundFactory
{ {
protected: protected:
Manager *snd; SoundFactory *snd;
InputManager *inp; SampleSourceLoader *inp;
public: public:
/// Empty constructor /// Empty constructor
InputFilter() {} InputFilter() {}
/// Assign an input manager and a sound manager to this object /// Assign an input manager and a sound manager to this object
InputFilter(Manager *_snd, InputManager *_inp) InputFilter(SoundFactory *_snd, SampleSourceLoader *_inp)
{ set(_snd, _inp); } { set(_snd, _inp); }
/// Assign an input manager and a sound manager to this object /// 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; inp = _inp;
snd = _snd; snd = _snd;

View file

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

View file

@ -1,8 +1,6 @@
#include "openal_out.h" #include "openal_out.h"
#include <assert.h> #include <assert.h>
// ALuint bufferID;
using namespace Mangle::Sound; using namespace Mangle::Sound;
// ---- Helper functions and classes ---- // ---- Helper functions and classes ----
@ -65,11 +63,6 @@ static void getALFormat(InputStream *inp, int &fmt, int &rate)
// ---- OpenAL_Sound ---- // ---- OpenAL_Sound ----
OpenAL_Sound::OpenAL_Sound(SampleSource *input)
{
}
void OpenAL_Sound::play() void OpenAL_Sound::play()
{ {
alSourcePlay(inst); alSourcePlay(inst);
@ -110,174 +103,34 @@ void OpenAL_Sound::setPos(float x, float y, float z)
checkALError("setting position"); checkALError("setting position");
} }
OpenAL_Sound::OpenAL_Sound(SampleSource *input)
Instance *OpenAL_Sound::getInstance(bool is3d, bool repeat)
{ {
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;
// Add 32 kb at each increment
const int ADD = 32*1024;
// 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 // Get the format
int fmt, rate; int fmt, rate;
getALFormat(inp, fmt, rate); getALFormat(inp, fmt, rate);
// We don't need the file anymore // Read the entire stream into a buffer
inp->drop(); BufferStream buf(input);
source->drop();
source = NULL;
// Move the data into OpenAL // Move the data into OpenAL
alGenBuffers(1, &bufferID); 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.
assert(bufferID != 0); assert(bufferID != 0);
alBufferData(bufferID, fmt, &buf.getPtr(), buf.size(), rate);
checkALError("loading sound buffer");
return new OpenAL_Simple_Instance(bufferID); // Create a source
}
// ---- OpenAL_Simple_Instance ----
OpenAL_Simple_Instance::OpenAL_Simple_Instance(ALuint buf)
{
// Create instance and associate buffer
alGenSources(1, &inst); alGenSources(1, &inst);
alSourcei(inst, AL_BUFFER, buf); alSourcei(inst, AL_BUFFER, buf);
} }
OpenAL_Simple_Instance::~OpenAL_Simple_Instance() OpenAL_Sound::~OpenAL_Sound()
{ {
// Stop // Stop
alSourceStop(inst); alSourceStop(inst);
// Return sound // Return sound
alDeleteSources(1, &inst); alDeleteSources(1, &inst);
}
// Delete buffer
alDeleteBuffers(1, &bufferID);
// ---- 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);
}
} }

View file

@ -2,6 +2,7 @@
#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>
@ -15,6 +16,7 @@ class OpenAL_Sound : public Sound
{ {
protected: protected:
ALuint inst; ALuint inst;
ALuint bufferID;
public: public:
OpenAL_Sound(SampleSource *input); OpenAL_Sound(SampleSource *input);
@ -39,7 +41,7 @@ class OpenAL_Sound : public Sound
void setPos(float x, float y, float z); void setPos(float x, float y, float z);
}; };
class OpenALFactory : public SoundFactory class OpenAL_Factory : public SoundFactory
{ {
ALCdevice *Device; ALCdevice *Device;
ALCcontext *Context; ALCcontext *Context;
@ -49,7 +51,7 @@ class OpenALFactory : 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.
OpenALFactory(bool doSetup = true) OpenAL_Factory(bool doSetup = true)
: didSetup(doSetup) : didSetup(doSetup)
{ {
needsUpdate = false; needsUpdate = false;
@ -72,7 +74,7 @@ class OpenALFactory : public SoundFactory
} }
} }
~OpenALFactory() ~OpenAL_Factory()
{ {
// Deinitialize sound system // Deinitialize sound system
if(didSetup) if(didSetup)

View file

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

View file

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

View file

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