forked from mirror/openmw-tes3mp
Rewrote audiere to use new sample_reader
This commit is contained in:
parent
3db61c8bdd
commit
a69938364f
5 changed files with 130 additions and 89 deletions
|
@ -27,65 +27,6 @@ void AudiereSource::getInfo(int32_t *rate, int32_t *channels, int32_t *bits)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
size_t AudiereSource::read(void *_data, size_t length)
|
||||
{
|
||||
if(isEof) return 0;
|
||||
|
||||
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);
|
||||
|
||||
if(res < frames)
|
||||
isEof = true;
|
||||
|
||||
// Are we missing data? If we're at the end of the stream, then this
|
||||
// doesn't apply.
|
||||
if(!isEof && pullSize)
|
||||
{
|
||||
// Read one more sample
|
||||
if(sample->read(1, pullOver) != 0)
|
||||
{
|
||||
// Then, move as much of it as we can fit into the output
|
||||
// data
|
||||
memcpy(data+length-pullSize, pullOver, pullSize);
|
||||
}
|
||||
else
|
||||
// Failed reading, we're out of data
|
||||
isEof = true;
|
||||
}
|
||||
|
||||
// If we're at the end of the stream, then no data remains to be
|
||||
// pulled over
|
||||
if(isEof)
|
||||
pullSize = 0;
|
||||
|
||||
// Return the total number of bytes stored
|
||||
return frameSize*res + pullSize;
|
||||
}
|
||||
|
||||
// --- Constructors ---
|
||||
|
||||
AudiereSource::AudiereSource(const std::string &file)
|
||||
|
@ -95,7 +36,7 @@ AudiereSource::AudiereSource(const std::string &file)
|
|||
if(!sample)
|
||||
fail("Couldn't load file " + file);
|
||||
|
||||
setup();
|
||||
doSetup();
|
||||
}
|
||||
|
||||
AudiereSource::AudiereSource(StreamPtr input)
|
||||
|
@ -106,15 +47,15 @@ AudiereSource::AudiereSource(StreamPtr input)
|
|||
if(!sample)
|
||||
fail("Couldn't load stream");
|
||||
|
||||
setup();
|
||||
doSetup();
|
||||
}
|
||||
|
||||
AudiereSource::AudiereSource(audiere::SampleSourcePtr src)
|
||||
: sample(src)
|
||||
{ assert(sample); setup(); }
|
||||
{ assert(sample); doSetup(); }
|
||||
|
||||
// Common function called from all constructors
|
||||
void AudiereSource::setup()
|
||||
void AudiereSource::doSetup()
|
||||
{
|
||||
assert(sample);
|
||||
|
||||
|
@ -122,14 +63,8 @@ void AudiereSource::setup()
|
|||
int channels, rate;
|
||||
sample->getFormat(channels, rate, fmt);
|
||||
|
||||
pullSize = 0;
|
||||
|
||||
// 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);
|
||||
// Calculate the size of one frame, and pass it to SampleReader.
|
||||
setup(GetSampleSize(fmt) * channels);
|
||||
|
||||
isSeekable = sample->isSeekable();
|
||||
hasPosition = true;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef MANGLE_SOUND_AUDIERE_SOURCE_H
|
||||
#define MANGLE_SOUND_AUDIERE_SOURCE_H
|
||||
|
||||
#include "../source.hpp"
|
||||
#include "sample_reader.hpp"
|
||||
|
||||
#include <audiere.h>
|
||||
|
||||
|
@ -9,24 +9,14 @@ namespace Mangle {
|
|||
namespace Sound {
|
||||
|
||||
/// A sample source that decodes files using Audiere
|
||||
class AudiereSource : public SampleSource
|
||||
class AudiereSource : public SampleReader
|
||||
{
|
||||
audiere::SampleSourcePtr sample;
|
||||
|
||||
// Number of bytes we cache between reads. This should correspond to
|
||||
// the maximum possible value of frameSize.
|
||||
static const int PSIZE = 10;
|
||||
size_t readSamples(void *data, size_t length)
|
||||
{ return sample->read(length, data); }
|
||||
|
||||
// Size of one frame, in bytes
|
||||
int frameSize;
|
||||
|
||||
// Temporary storage for unevenly read samples. See the comment for
|
||||
// read() in the .cpp file.
|
||||
char pullOver[PSIZE];
|
||||
// How much of the above buffer is in use
|
||||
int pullSize;
|
||||
|
||||
void setup();
|
||||
void doSetup();
|
||||
|
||||
public:
|
||||
/// Decode the given sound file
|
||||
|
@ -39,7 +29,6 @@ class AudiereSource : public SampleSource
|
|||
AudiereSource(audiere::SampleSourcePtr src);
|
||||
|
||||
void getInfo(int32_t *rate, int32_t *channels, int32_t *bits);
|
||||
size_t read(void *data, size_t length);
|
||||
|
||||
void seek(size_t pos) { sample->setPosition(pos/frameSize); }
|
||||
size_t tell() const { return sample->getPosition()*frameSize; }
|
||||
|
|
75
sound/sources/sample_reader.cpp
Normal file
75
sound/sources/sample_reader.cpp
Normal file
|
@ -0,0 +1,75 @@
|
|||
#include "sample_reader.hpp"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
using namespace Mangle::Sound;
|
||||
|
||||
void SampleReader::setup(int size)
|
||||
{
|
||||
pullSize = 0;
|
||||
frameSize = size;
|
||||
pullOver = new char[size];
|
||||
}
|
||||
|
||||
SampleReader::~SampleReader()
|
||||
{
|
||||
if(pullOver)
|
||||
delete[] pullOver;
|
||||
}
|
||||
|
||||
size_t SampleReader::read(void *_data, size_t length)
|
||||
{
|
||||
if(isEof) return 0;
|
||||
char *data = (char*)_data;
|
||||
|
||||
// Move the remains from the last operation first
|
||||
if(pullSize)
|
||||
{
|
||||
// pullSize is how much was stored the last time. The data is
|
||||
// stored at the end of the buffer.
|
||||
memcpy(data, pullOver+(frameSize-pullSize), pullSize);
|
||||
length -= pullSize;
|
||||
data += pullSize;
|
||||
pullSize = 0;
|
||||
}
|
||||
|
||||
// Number of whole frames
|
||||
size_t frames = length / frameSize;
|
||||
|
||||
// Read the data
|
||||
size_t res = readSamples(data, frames);
|
||||
|
||||
// Total bytes read
|
||||
size_t num = res*frameSize;
|
||||
data += num;
|
||||
|
||||
if(res < frames)
|
||||
{
|
||||
// End of stream.
|
||||
isEof = true;
|
||||
// Determine how much we read
|
||||
return data-(char*)_data;
|
||||
}
|
||||
|
||||
// Determine the overshoot
|
||||
pullSize = length - num;
|
||||
|
||||
// Are we missing data?
|
||||
if(pullSize)
|
||||
{
|
||||
// Fill in one sample
|
||||
res = readSamples(pullOver,1);
|
||||
if(res)
|
||||
{
|
||||
// Move as much as we can into the output buffer
|
||||
memcpy(data, pullOver, pullSize);
|
||||
data += pullSize;
|
||||
}
|
||||
else
|
||||
// Failed reading, we're out of data
|
||||
isEof = true;
|
||||
}
|
||||
|
||||
// Return the total number of bytes stored
|
||||
return data-(char*)_data;
|
||||
}
|
42
sound/sources/sample_reader.hpp
Normal file
42
sound/sources/sample_reader.hpp
Normal file
|
@ -0,0 +1,42 @@
|
|||
#ifndef MANGLE_SOUND_SAMPLE_READER_H
|
||||
#define MANGLE_SOUND_SAMPLE_READER_H
|
||||
|
||||
#include "../source.hpp"
|
||||
|
||||
namespace Mangle {
|
||||
namespace Sound {
|
||||
|
||||
/* This is a helper base class for other SampleSource
|
||||
implementations. Certain sources (like Audiere and libsndfile)
|
||||
insist on reading whole samples rather than bytes. This class
|
||||
compensates for that, and allows you to read bytes rather than
|
||||
samples.
|
||||
*/
|
||||
class SampleReader : public SampleSource
|
||||
{
|
||||
// Pullover buffer
|
||||
char* pullOver;
|
||||
|
||||
// How much of the above buffer is in use.
|
||||
int pullSize;
|
||||
|
||||
protected:
|
||||
// Size of one frame, in bytes. This is also the size of the
|
||||
// pullOver buffer.
|
||||
int frameSize;
|
||||
|
||||
// MUST be called by base class constructor. The parameter gives the
|
||||
// size of one sample/frame, in bytes.
|
||||
void setup(int);
|
||||
|
||||
// Read the given number of samples, in multiples of frameSize. Does
|
||||
// not have to set or respect isEof.
|
||||
virtual size_t readSamples(void *data, size_t num) = 0;
|
||||
|
||||
public:
|
||||
SampleReader() : pullOver(NULL) {}
|
||||
~SampleReader();
|
||||
size_t read(void *data, size_t length);
|
||||
};
|
||||
}} // Namespace
|
||||
#endif
|
|
@ -7,7 +7,7 @@ I_FFMPEG=-I/usr/include/libavcodec -I/usr/include/libavformat
|
|||
L_OPENAL=$(shell pkg-config --libs openal)
|
||||
L_AUDIERE=-laudiere
|
||||
|
||||
openal_audiere_test: openal_audiere_test.cpp ../sources/audiere_source.cpp ../outputs/openal_out.cpp ../../stream/clients/audiere_file.cpp
|
||||
openal_audiere_test: openal_audiere_test.cpp ../sources/audiere_source.cpp ../sources/sample_reader.cpp ../outputs/openal_out.cpp ../../stream/clients/audiere_file.cpp
|
||||
$(GCC) $^ -o $@ $(L_AUDIERE) $(L_OPENAL)
|
||||
|
||||
openal_ffmpeg_test: openal_ffmpeg_test.cpp ../sources/ffmpeg_source.cpp ../outputs/openal_out.cpp
|
||||
|
@ -19,7 +19,7 @@ openal_mpg123_test: openal_mpg123_test.cpp ../sources/mpg123_source.cpp ../outpu
|
|||
openal_output_test: openal_output_test.cpp ../outputs/openal_out.cpp
|
||||
$(GCC) $^ -o $@ $(L_OPENAL)
|
||||
|
||||
audiere_source_test: audiere_source_test.cpp ../sources/audiere_source.cpp ../../stream/clients/audiere_file.cpp
|
||||
audiere_source_test: audiere_source_test.cpp ../sources/audiere_source.cpp ../../stream/clients/audiere_file.cpp ../sources/sample_reader.cpp
|
||||
$(GCC) $^ -o $@ $(L_AUDIERE)
|
||||
|
||||
ffmpeg_source_test: ffmpeg_source_test.cpp ../sources/ffmpeg_source.cpp
|
||||
|
|
Loading…
Reference in a new issue