3D Audio GSoC:

- Converting AUD_SampleRate to a double
- Removing AUD_DefaultMixer
- Introducing AUD_ResampleReader as base class for all resampling readers.
This commit is contained in:
Joerg Mueller
2011-06-21 20:29:02 +00:00
parent d5eaffda23
commit fba07308bf
17 changed files with 83 additions and 92 deletions

View File

@@ -82,8 +82,6 @@ set(SRC
intern/AUD_ConverterFunctions.h intern/AUD_ConverterFunctions.h
intern/AUD_ConverterReader.cpp intern/AUD_ConverterReader.cpp
intern/AUD_ConverterReader.h intern/AUD_ConverterReader.h
intern/AUD_DefaultMixer.cpp
intern/AUD_DefaultMixer.h
intern/AUD_FileFactory.cpp intern/AUD_FileFactory.cpp
intern/AUD_FileFactory.h intern/AUD_FileFactory.h
intern/AUD_I3DDevice.h intern/AUD_I3DDevice.h
@@ -108,6 +106,8 @@ set(SRC
intern/AUD_Reference.h intern/AUD_Reference.h
intern/AUD_ReferenceHandler.cpp intern/AUD_ReferenceHandler.cpp
intern/AUD_ResampleFactory.h intern/AUD_ResampleFactory.h
intern/AUD_ResampleReader.cpp
intern/AUD_ResampleReader.h
intern/AUD_SequencerFactory.cpp intern/AUD_SequencerFactory.cpp
intern/AUD_SequencerFactory.h intern/AUD_SequencerFactory.h
intern/AUD_SequencerReader.cpp intern/AUD_SequencerReader.cpp

View File

@@ -39,6 +39,6 @@ AUD_PitchReader::AUD_PitchReader(AUD_Reference<AUD_IReader> reader, float pitch)
AUD_Specs AUD_PitchReader::getSpecs() const AUD_Specs AUD_PitchReader::getSpecs() const
{ {
AUD_Specs specs = m_reader->getSpecs(); AUD_Specs specs = m_reader->getSpecs();
specs.rate = (AUD_SampleRate)((int)(specs.rate * m_pitch)); specs.rate *= m_pitch;
return specs; return specs;
} }

View File

@@ -2111,13 +2111,13 @@ Device_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
static const char *kwlist[] = {"type", "rate", "channels", "format", "buffer_size", "name", NULL}; static const char *kwlist[] = {"type", "rate", "channels", "format", "buffer_size", "name", NULL};
int device; int device;
int rate = AUD_RATE_44100; double rate = AUD_RATE_44100;
int channels = AUD_CHANNELS_STEREO; int channels = AUD_CHANNELS_STEREO;
int format = AUD_FORMAT_FLOAT32; int format = AUD_FORMAT_FLOAT32;
int buffersize = AUD_DEFAULT_BUFFER_SIZE; int buffersize = AUD_DEFAULT_BUFFER_SIZE;
const char* name = "Audaspace"; const char* name = "Audaspace";
if(!PyArg_ParseTupleAndKeywords(args, kwds, "i|iiiis:Device", const_cast<char**>(kwlist), if(!PyArg_ParseTupleAndKeywords(args, kwds, "i|diiis:Device", const_cast<char**>(kwlist),
&device, &rate, &channels, &format, &buffersize, &name)) &device, &rate, &channels, &format, &buffersize, &name))
return NULL; return NULL;

View File

@@ -45,8 +45,7 @@ static const char* state_error = "AUD_SRCResampleReader: SRC State couldn't be "
AUD_SRCResampleReader::AUD_SRCResampleReader(AUD_Reference<AUD_IReader> reader, AUD_SRCResampleReader::AUD_SRCResampleReader(AUD_Reference<AUD_IReader> reader,
AUD_Specs specs) : AUD_Specs specs) :
AUD_EffectReader(reader), AUD_ResampleReader(reader, specs.rate),
m_rate(specs.rate),
m_channels(reader->getSpecs().channels), m_channels(reader->getSpecs().channels),
m_position(0) m_position(0)
{ {

View File

@@ -32,7 +32,7 @@
#ifndef AUD_SRCRESAMPLEREADER #ifndef AUD_SRCRESAMPLEREADER
#define AUD_SRCRESAMPLEREADER #define AUD_SRCRESAMPLEREADER
#include "AUD_EffectReader.h" #include "AUD_ResampleReader.h"
#include "AUD_Buffer.h" #include "AUD_Buffer.h"
#include <samplerate.h> #include <samplerate.h>
@@ -40,7 +40,7 @@
/** /**
* This resampling reader uses libsamplerate for resampling. * This resampling reader uses libsamplerate for resampling.
*/ */
class AUD_SRCResampleReader : public AUD_EffectReader class AUD_SRCResampleReader : public AUD_ResampleReader
{ {
private: private:
/** /**
@@ -48,11 +48,6 @@ private:
*/ */
AUD_Buffer m_buffer; AUD_Buffer m_buffer;
/**
* The target sampling rate.
*/
AUD_SampleRate m_rate;
/** /**
* The reader channels. * The reader channels.
*/ */

View File

@@ -795,7 +795,7 @@ void AUD_closeReadDevice(AUD_Device* device)
float* AUD_readSoundBuffer(const char* filename, float low, float high, float* AUD_readSoundBuffer(const char* filename, float low, float high,
float attack, float release, float threshold, float attack, float release, float threshold,
int accumulate, int additive, int square, int accumulate, int additive, int square,
float sthreshold, int samplerate, int* length) float sthreshold, double samplerate, int* length)
{ {
AUD_Buffer buffer; AUD_Buffer buffer;
AUD_DeviceSpecs specs; AUD_DeviceSpecs specs;

View File

@@ -441,7 +441,7 @@ extern void AUD_closeReadDevice(AUD_Device* device);
extern float* AUD_readSoundBuffer(const char* filename, float low, float high, extern float* AUD_readSoundBuffer(const char* filename, float low, float high,
float attack, float release, float threshold, float attack, float release, float threshold,
int accumulate, int additive, int square, int accumulate, int additive, int square,
float sthreshold, int samplerate, float sthreshold, double samplerate,
int* length); int* length);
/** /**

View File

@@ -38,8 +38,7 @@
AUD_LinearResampleReader::AUD_LinearResampleReader(AUD_Reference<AUD_IReader> reader, AUD_LinearResampleReader::AUD_LinearResampleReader(AUD_Reference<AUD_IReader> reader,
AUD_Specs specs) : AUD_Specs specs) :
AUD_EffectReader(reader), AUD_ResampleReader(reader, specs.rate),
m_rate(specs.rate),
m_channels(reader->getSpecs().channels), m_channels(reader->getSpecs().channels),
m_position(0), m_position(0),
m_cache_pos(0), m_cache_pos(0),

View File

@@ -32,20 +32,15 @@
#ifndef AUD_LINEARRESAMPLEREADER #ifndef AUD_LINEARRESAMPLEREADER
#define AUD_LINEARRESAMPLEREADER #define AUD_LINEARRESAMPLEREADER
#include "AUD_EffectReader.h" #include "AUD_ResampleReader.h"
#include "AUD_Buffer.h" #include "AUD_Buffer.h"
/** /**
* This resampling reader uses libsamplerate for resampling. * This resampling reader uses libsamplerate for resampling.
*/ */
class AUD_LinearResampleReader : public AUD_EffectReader class AUD_LinearResampleReader : public AUD_ResampleReader
{ {
private: private:
/**
* The target specification.
*/
AUD_SampleRate m_rate;
/** /**
* The reader channels. * The reader channels.
*/ */

View File

@@ -81,13 +81,6 @@ public:
*/ */
AUD_DeviceSpecs getSpecs() const; AUD_DeviceSpecs getSpecs() const;
/**
* This funuction prepares a reader for playback.
* \param reader The reader to prepare.
* \return The reader that should be used for playback.
*/
virtual AUD_Reference<AUD_IReader> prepare(AUD_Reference<AUD_IReader> reader)=0;
/** /**
* Mixes a buffer. * Mixes a buffer.
* \param buffer The buffer to superpose. * \param buffer The buffer to superpose.
@@ -95,20 +88,20 @@ public:
* \param length The length of the buffer in samples. * \param length The length of the buffer in samples.
* \param volume The mixing volume. Must be a value between 0.0 and 1.0. * \param volume The mixing volume. Must be a value between 0.0 and 1.0.
*/ */
virtual void mix(sample_t* buffer, int start, int length, float volume); void mix(sample_t* buffer, int start, int length, float volume);
/** /**
* Writes the mixing buffer into an output buffer. * Writes the mixing buffer into an output buffer.
* \param buffer The target buffer for superposing. * \param buffer The target buffer for superposing.
* \param volume The mixing volume. Must be a value between 0.0 and 1.0. * \param volume The mixing volume. Must be a value between 0.0 and 1.0.
*/ */
virtual void read(data_t* buffer, float volume); void read(data_t* buffer, float volume);
/** /**
* Clears the mixing buffer. * Clears the mixing buffer.
* \param length The length of the buffer in samples. * \param length The length of the buffer in samples.
*/ */
virtual void clear(int length); void clear(int length);
}; };
#endif //AUD_MIXER #endif //AUD_MIXER

View File

@@ -29,7 +29,6 @@
*/ */
#include "AUD_DefaultMixer.h"
#include "AUD_ReadDevice.h" #include "AUD_ReadDevice.h"
#include "AUD_IReader.h" #include "AUD_IReader.h"

View File

@@ -24,38 +24,24 @@
* ***** END GPL LICENSE BLOCK ***** * ***** END GPL LICENSE BLOCK *****
*/ */
/** \file audaspace/intern/AUD_DefaultMixer.cpp /** \file audaspace/intern/AUD_ResampleReader.cpp
* \ingroup audaspaceintern * \ingroup audaspaceintern
*/ */
#include "AUD_DefaultMixer.h" #include "AUD_ResampleReader.h"
#ifdef WITH_SAMPLERATE
#include "AUD_SRCResampleReader.h"
#else
#include "AUD_LinearResampleReader.h"
#endif
#include "AUD_ChannelMapperReader.h"
#include "AUD_ChannelMapperFactory.h"
#include <cstring> AUD_ResampleReader::AUD_ResampleReader(AUD_Reference<AUD_IReader> reader, AUD_SampleRate rate) :
AUD_EffectReader(reader), m_rate(rate)
AUD_DefaultMixer::AUD_DefaultMixer(AUD_DeviceSpecs specs) :
AUD_Mixer(specs)
{ {
} }
AUD_Reference<AUD_IReader> AUD_DefaultMixer::prepare(AUD_Reference<AUD_IReader> reader) void AUD_ResampleReader::setRate(AUD_SampleRate rate)
{ {
// resample m_rate = rate;
#ifdef WITH_SAMPLERATE }
reader = new AUD_SRCResampleReader(reader, m_specs.specs);
#else AUD_SampleRate AUD_ResampleReader::getRate()
reader = new AUD_LinearResampleReader(reader, m_specs.specs); {
#endif return m_rate;
// rechannel
reader = new AUD_ChannelMapperReader(reader, m_specs.channels);
return reader;
} }

View File

@@ -24,36 +24,28 @@
* ***** END GPL LICENSE BLOCK ***** * ***** END GPL LICENSE BLOCK *****
*/ */
/** \file audaspace/intern/AUD_DefaultMixer.h /** \file audaspace/intern/AUD_ResampleReader.h
* \ingroup audaspaceintern * \ingroup audaspaceintern
*/ */
#ifndef AUD_RESAMPLEREADER
#define AUD_RESAMPLEREADER
#ifndef AUD_DEFAULTMIXER #include "AUD_EffectReader.h"
#define AUD_DEFAULTMIXER
#include "AUD_Mixer.h" class AUD_ResampleReader : public AUD_EffectReader
/**
* This class is able to mix audiosignals of different channel count and sample
* rate and convert it to a specific output format.
* It uses a default ChannelMapperFactory and a SRCResampleFactory for
* the perparation.
*/
class AUD_DefaultMixer : public AUD_Mixer
{ {
public: protected:
/** /**
* Creates the mixer. * The target sampling rate.
*/ */
AUD_DefaultMixer(AUD_DeviceSpecs specs); AUD_SampleRate m_rate;
/** AUD_ResampleReader(AUD_Reference<AUD_IReader> reader, AUD_SampleRate rate);
* This funuction prepares a reader for playback.
* \param reader The reader to prepare. public:
* \return The reader that should be used for playback. virtual void setRate(AUD_SampleRate rate);
*/ AUD_SampleRate getRate();
virtual AUD_Reference<AUD_IReader> prepare(AUD_Reference<AUD_IReader> reader);
}; };
#endif //AUD_DEFAULTMIXER #endif // AUD_RESAMPLEREADER

View File

@@ -30,7 +30,14 @@
#include "AUD_SequencerReader.h" #include "AUD_SequencerReader.h"
#include "AUD_DefaultMixer.h" #include "AUD_Mixer.h"
#ifdef WITH_SAMPLERATE
#include "AUD_SRCResampleReader.h"
#else
#include "AUD_LinearResampleReader.h"
#endif
#include "AUD_ChannelMapperReader.h"
#include <math.h> #include <math.h>
@@ -46,7 +53,7 @@ AUD_SequencerReader::AUD_SequencerReader(AUD_Reference<AUD_SequencerFactory> fac
dspecs.specs = specs; dspecs.specs = specs;
dspecs.format = AUD_FORMAT_FLOAT32; dspecs.format = AUD_FORMAT_FLOAT32;
m_mixer = new AUD_DefaultMixer(dspecs); m_mixer = new AUD_Mixer(dspecs);
AUD_Reference<AUD_SequencerStrip> strip; AUD_Reference<AUD_SequencerStrip> strip;
@@ -139,7 +146,16 @@ void AUD_SequencerReader::read(int& length, bool& eos, sample_t* buffer)
{ {
try try
{ {
strip->reader = m_mixer->prepare((*strip->old_sound)->createReader()); strip->reader = (*strip->old_sound)->createReader();
// resample
#ifdef WITH_SAMPLERATE
strip->reader = new AUD_SRCResampleReader(strip->reader, m_mixer->getSpecs().specs);
#else
strip->reader = new AUD_LinearResampleReader(strip->reader, m_mixer->getSpecs().specs);
#endif
// rechannel
strip->reader = new AUD_ChannelMapperReader(strip->reader, m_mixer->getSpecs().channels);
} }
catch(AUD_Exception) catch(AUD_Exception)
{ {

View File

@@ -77,8 +77,7 @@ void AUD_SinusReader::read(int& length, bool& eos, sample_t* buffer)
// fill with sine data // fill with sine data
for(int i = 0; i < length; i++) for(int i = 0; i < length; i++)
{ {
buffer[i] = sin((m_position + i) * 2 * M_PI * m_frequency / buffer[i] = sin((m_position + i) * 2 * M_PI * m_frequency / m_sampleRate);
(float)m_sampleRate);
} }
m_position += length; m_position += length;

View File

@@ -31,8 +31,14 @@
#include "AUD_SoftwareDevice.h" #include "AUD_SoftwareDevice.h"
#include "AUD_IReader.h" #include "AUD_IReader.h"
#include "AUD_DefaultMixer.h" #include "AUD_Mixer.h"
#include "AUD_IFactory.h" #include "AUD_IFactory.h"
#ifdef WITH_SAMPLERATE
#include "AUD_SRCResampleReader.h"
#else
#include "AUD_LinearResampleReader.h"
#endif
#include "AUD_ChannelMapperReader.h"
#include <cstring> #include <cstring>
#include <limits> #include <limits>
@@ -238,7 +244,7 @@ void AUD_SoftwareDevice::create()
{ {
m_playback = false; m_playback = false;
m_volume = 1.0f; m_volume = 1.0f;
m_mixer = new AUD_DefaultMixer(m_specs); m_mixer = new AUD_Mixer(m_specs);
pthread_mutexattr_t attr; pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr); pthread_mutexattr_init(&attr);
@@ -352,7 +358,16 @@ AUD_DeviceSpecs AUD_SoftwareDevice::getSpecs() const
AUD_Reference<AUD_IHandle> AUD_SoftwareDevice::play(AUD_Reference<AUD_IReader> reader, bool keep) AUD_Reference<AUD_IHandle> AUD_SoftwareDevice::play(AUD_Reference<AUD_IReader> reader, bool keep)
{ {
// prepare the reader // prepare the reader
reader = m_mixer->prepare(reader); // resample
#ifdef WITH_SAMPLERATE
reader = new AUD_SRCResampleReader(reader, m_specs.specs);
#else
reader = new AUD_LinearResampleReader(reader, m_specs.specs);
#endif
// rechannel
reader = new AUD_ChannelMapperReader(reader, m_specs.channels);
if(reader.isNull()) if(reader.isNull())
return NULL; return NULL;

View File

@@ -117,7 +117,7 @@ typedef enum
AUD_RATE_88200 = 88200, /// 88200 Hz. AUD_RATE_88200 = 88200, /// 88200 Hz.
AUD_RATE_96000 = 96000, /// 96000 Hz. AUD_RATE_96000 = 96000, /// 96000 Hz.
AUD_RATE_192000 = 192000 /// 192000 Hz. AUD_RATE_192000 = 192000 /// 192000 Hz.
} AUD_SampleRate; } AUD_DefaultSampleRate;
/// Status of a playback handle. /// Status of a playback handle.
typedef enum typedef enum
@@ -166,6 +166,9 @@ typedef float sample_t;
/// Sample data type (format samples) /// Sample data type (format samples)
typedef unsigned char data_t; typedef unsigned char data_t;
/// Sample rate type.
typedef double AUD_SampleRate;
/// Specification of a sound source. /// Specification of a sound source.
typedef struct typedef struct
{ {