Rewrote audiere to use new sample_reader

This commit is contained in:
Nicolay Korslund 2010-08-16 14:13:13 +02:00
parent 3db61c8bdd
commit a69938364f
5 changed files with 130 additions and 89 deletions

View file

@ -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 --- // --- Constructors ---
AudiereSource::AudiereSource(const std::string &file) AudiereSource::AudiereSource(const std::string &file)
@ -95,7 +36,7 @@ AudiereSource::AudiereSource(const std::string &file)
if(!sample) if(!sample)
fail("Couldn't load file " + file); fail("Couldn't load file " + file);
setup(); doSetup();
} }
AudiereSource::AudiereSource(StreamPtr input) AudiereSource::AudiereSource(StreamPtr input)
@ -106,15 +47,15 @@ AudiereSource::AudiereSource(StreamPtr input)
if(!sample) if(!sample)
fail("Couldn't load stream"); fail("Couldn't load stream");
setup(); doSetup();
} }
AudiereSource::AudiereSource(audiere::SampleSourcePtr src) AudiereSource::AudiereSource(audiere::SampleSourcePtr src)
: sample(src) : sample(src)
{ assert(sample); setup(); } { assert(sample); doSetup(); }
// Common function called from all constructors // Common function called from all constructors
void AudiereSource::setup() void AudiereSource::doSetup()
{ {
assert(sample); assert(sample);
@ -122,14 +63,8 @@ void AudiereSource::setup()
int channels, rate; int channels, rate;
sample->getFormat(channels, rate, fmt); sample->getFormat(channels, rate, fmt);
pullSize = 0; // Calculate the size of one frame, and pass it to SampleReader.
setup(GetSampleSize(fmt) * channels);
// 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);
isSeekable = sample->isSeekable(); isSeekable = sample->isSeekable();
hasPosition = true; hasPosition = true;

View file

@ -1,7 +1,7 @@
#ifndef MANGLE_SOUND_AUDIERE_SOURCE_H #ifndef MANGLE_SOUND_AUDIERE_SOURCE_H
#define MANGLE_SOUND_AUDIERE_SOURCE_H #define MANGLE_SOUND_AUDIERE_SOURCE_H
#include "../source.hpp" #include "sample_reader.hpp"
#include <audiere.h> #include <audiere.h>
@ -9,24 +9,14 @@ namespace Mangle {
namespace Sound { namespace Sound {
/// A sample source that decodes files using Audiere /// A sample source that decodes files using Audiere
class AudiereSource : public SampleSource class AudiereSource : public SampleReader
{ {
audiere::SampleSourcePtr sample; audiere::SampleSourcePtr sample;
// Number of bytes we cache between reads. This should correspond to size_t readSamples(void *data, size_t length)
// the maximum possible value of frameSize. { return sample->read(length, data); }
static const int PSIZE = 10;
// Size of one frame, in bytes void doSetup();
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();
public: public:
/// Decode the given sound file /// Decode the given sound file
@ -39,7 +29,6 @@ class AudiereSource : public SampleSource
AudiereSource(audiere::SampleSourcePtr src); AudiereSource(audiere::SampleSourcePtr src);
void getInfo(int32_t *rate, int32_t *channels, int32_t *bits); 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); } void seek(size_t pos) { sample->setPosition(pos/frameSize); }
size_t tell() const { return sample->getPosition()*frameSize; } size_t tell() const { return sample->getPosition()*frameSize; }

View 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;
}

View 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

View file

@ -7,7 +7,7 @@ I_FFMPEG=-I/usr/include/libavcodec -I/usr/include/libavformat
L_OPENAL=$(shell pkg-config --libs openal) L_OPENAL=$(shell pkg-config --libs openal)
L_AUDIERE=-laudiere 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) $(GCC) $^ -o $@ $(L_AUDIERE) $(L_OPENAL)
openal_ffmpeg_test: openal_ffmpeg_test.cpp ../sources/ffmpeg_source.cpp ../outputs/openal_out.cpp 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 openal_output_test: openal_output_test.cpp ../outputs/openal_out.cpp
$(GCC) $^ -o $@ $(L_OPENAL) $(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) $(GCC) $^ -o $@ $(L_AUDIERE)
ffmpeg_source_test: ffmpeg_source_test.cpp ../sources/ffmpeg_source.cpp ffmpeg_source_test: ffmpeg_source_test.cpp ../sources/ffmpeg_source.cpp