Created separate Audiere sound input class

actorid
Nicolay Korslund 15 years ago
parent bbb44e07bf
commit dc0b736846

@ -0,0 +1,119 @@
#include "input_audiere.h"
#include <assert.h>
// Exception handling
class Audiere_Exception : public std::exception
{
std::string msg;
public:
Audiere_Exception(const std::string &m) : msg(m) {}
~Audiere_Exception() throw() {}
virtual const char* what() const throw() { return msg.c_str(); }
};
static void fail(const std::string &msg)
{
throw Audiere_Exception("Audiere exception: " + msg);
}
using namespace audiere;
using namespace Mangle::Sound;
// --- InputManager ---
InputSource *AudiereInput::load(const std::string &file)
{ return new AudiereSource(file); }
// --- InputSource ---
AudiereSource::AudiereSource(const std::string &file)
{
SampleSourcePtr sample = OpenSampleSource(file.c_str());
if(!sample)
fail("Couldn't load file " + file);
buf = CreateSampleBuffer(sample);
}
InputStream *AudiereSource::getStream()
{
return new AudiereStream(buf->openStream());
}
// --- InputStream ---
AudiereStream::AudiereStream(SampleSourcePtr _sample)
: sample(_sample), pullSize(0)
{
assert(sample);
SampleFormat fmt;
int channels, rate;
sample->getFormat(channels, rate, fmt);
// Calculate the size of one frame
frameSize = GetSampleSize(fmt) * channels;
// Make sure that our pullover hack will work. Increase this size if
// this doesn't work in all cases.
assert(frameSize <= PSIZE);
}
void AudiereStream::getInfo(int32_t *rate, int32_t *channels, int32_t *bits)
{
SampleFormat fmt;
sample->getFormat(*channels, *rate, fmt);
if(fmt == SF_U8)
*bits = 8;
else if(fmt == SF_S16)
*bits = 16;
else assert(0);
}
/*
Get data. Since Audiere operates with frames, not bytes, there's a
little conversion magic going on here. We need to make sure we're
reading a whole number of frames - if not, we need to store the
remainding part of the last frame and remember it for the next read
operation.
*/
uint32_t AudiereStream::getData(void *_data, uint32_t length)
{
char *data = (char*)_data;
// Move the remains from the last operation first
if(pullSize)
{
// pullSize is how much was stored the last time, so skip that.
memcpy(data, pullOver+pullSize, PSIZE-pullSize);
length -= pullSize;
data += pullSize;
}
// Determine the overshoot up front
pullSize = length % frameSize;
// Number of whole frames
int frames = length / frameSize;
// Read the data
int res = sample->read(frames, data);
// Are we missing data? If res<length and we're at the end of the
// stream, then this doesn't apply.
if(res == frames && pullSize &&
// Read one more sample
(sample->read(1, pullOver) != 0))
{
// Now, move as much of it as we can fit into the output
// data
memcpy(data+length-pullSize, pullOver, pullSize);
}
else pullSize = 0;
// Return the total number of bytes stored
return frameSize*res + pullSize;
}

@ -0,0 +1,52 @@
#ifndef MANGLE_SOUND_AUDIERE_INPUT_H
#define MANGLE_SOUND_AUDIERE_INPUT_H
#include "../input.h"
#include <audiere.h>
namespace Mangle {
namespace Sound {
/// Implementation of Sound::InputManager for Audiere
class AudiereInput : public InputManager
{
public:
InputSource *load(const std::string &file);
};
/// Audiere InputSource implementation
class AudiereSource : public InputSource
{
audiere::SampleBufferPtr buf;
public:
AudiereSource(const std::string &file);
InputStream *getStream();
void drop() { delete this; }
};
/// Audiere InputStream implementation
class AudiereStream : public InputStream
{
audiere::SampleSourcePtr sample;
int frameSize; // Size of one frame, in bytes
static const int PSIZE = 10;
// Temporary storage for unevenly read samples. See the comment for
// getData() in the .cpp file.
char pullOver[PSIZE];
// How much of the above buffer is in use
int pullSize;
public:
AudiereStream(audiere::SampleSourcePtr _sample);
void getInfo(int32_t *rate, int32_t *channels, int32_t *bits);
uint32_t getData(void *data, uint32_t length);
void drop() { delete this; }
};
}} // Namespace
#endif

@ -0,0 +1,29 @@
#ifndef MANGLE_FFMPEG_OPENAL_H
#define MANGLE_FFMPEG_OPENAL_H
#include "input_filter.h"
#include "input_audiere.h"
#include "output_openal.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
{
public:
OpenAL_Audiere_Manager()
{
set(new OpenAL_Manager,
new AudiereInput);
}
~OpenAL_Audiere_Manager()
{
delete snd;
delete inp;
}
};
}}
#endif

@ -8,7 +8,7 @@
namespace Mangle {
namespace Sound {
/// A PairManager filter that adds FFmpeg decoding to OpenAL
/// An InputFilter that adds FFmpeg decoding to OpenAL
class OpenAL_FFM_Manager : public InputFilter
{
public:

@ -1,15 +1,17 @@
GCC=g++ -I../ -I../imp/
all: audiere_test ffmpeg_openal_test
all: audiere_test ffmpeg_openal_test openal_audiere_test
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 ../imp/input_ffmpeg.cpp ../imp/output_openal.cpp
$(GCC) $^ -o $@ $(L_FFMPEG) $(L_OPENAL)
openal_audiere_test: openal_audiere_test.cpp ../imp/input_audiere.cpp ../imp/output_openal.cpp
$(GCC) $^ -o $@ $(L_AUDIERE) $(L_OPENAL)
audiere_test: audiere_test.cpp ../imp/audiere_imp.cpp
$(GCC) $^ -o $@ $(L_AUDIERE)

@ -0,0 +1,7 @@
#include "openal_audiere.h"
using namespace Mangle::Sound;
OpenAL_Audiere_Manager mg;
#include "common.cpp"
Loading…
Cancel
Save