1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-02-02 10:45:32 +00:00

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

View file

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

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_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