3D Audio GSoC:

High quality resampling on mixdown, linear for playback.

* Lots of improvements and fixes for the JOS resampler, now it works fine!
* High quality filter coefficients for the JOS resampler (sorry for the 5 MB source file).
* Fix for GE orientation bug. Note: moto uses x,y,z,w quaternion storage, while rest of blender uses w,x,y,z.
* Minor changes/fixes.
This commit is contained in:
2011-08-15 21:50:09 +00:00
parent cbbbf31315
commit a458de88b6
18 changed files with 29580 additions and 3471 deletions

View File

@@ -1182,7 +1182,7 @@ const char* AUD_mixdown(AUD_Sound* sound, unsigned int start, unsigned int lengt
AUD_SequencerFactory* f = dynamic_cast<AUD_SequencerFactory*>(sound->get()); AUD_SequencerFactory* f = dynamic_cast<AUD_SequencerFactory*>(sound->get());
f->setSpecs(specs.specs); f->setSpecs(specs.specs);
AUD_Reference<AUD_IReader> reader = f->createReader(); AUD_Reference<AUD_IReader> reader = f->createQualityReader();
reader->seek(start); reader->seek(start);
AUD_Reference<AUD_IWriter> writer = AUD_FileWriter::createWriter(filename, specs, format, codec, bitrate); AUD_Reference<AUD_IWriter> writer = AUD_FileWriter::createWriter(filename, specs, format, codec, bitrate);
AUD_FileWriter::writeReader(reader, writer, length, buffersize); AUD_FileWriter::writeReader(reader, writer, length, buffersize);
@@ -1195,6 +1195,28 @@ const char* AUD_mixdown(AUD_Sound* sound, unsigned int start, unsigned int lengt
} }
} }
AUD_Device* AUD_openMixdownDevice(AUD_DeviceSpecs specs, AUD_Sound* sequencer, float volume, float start)
{
try
{
AUD_ReadDevice* device = new AUD_ReadDevice(specs);
device->setQuality(true);
device->setVolume(volume);
dynamic_cast<AUD_SequencerFactory*>(sequencer->get())->setSpecs(specs.specs);
AUD_Handle handle = device->play(*sequencer);
if(!handle.isNull())
handle->seek(start);
return new AUD_Device(device);
}
catch(AUD_Exception&)
{
return NULL;
}
}
AUD_Reference<AUD_IDevice> AUD_getDevice() AUD_Reference<AUD_IDevice> AUD_getDevice()
{ {
return AUD_device; return AUD_device;

View File

@@ -527,6 +527,8 @@ extern void* AUD_getSet(void* set);
extern const char* AUD_mixdown(AUD_Sound* sound, unsigned int start, unsigned int length, unsigned int buffersize, const char* filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate); extern const char* AUD_mixdown(AUD_Sound* sound, unsigned int start, unsigned int length, unsigned int buffersize, const char* filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate);
extern AUD_Device* AUD_openMixdownDevice(AUD_DeviceSpecs specs, AUD_Sound* sequencer, float volume, float start);
#ifdef WITH_PYTHON #ifdef WITH_PYTHON
extern PyObject* AUD_getPythonFactory(AUD_Sound* sound); extern PyObject* AUD_getPythonFactory(AUD_Sound* sound);

View File

@@ -38,7 +38,6 @@
#endif #endif
#include "AUD_FileFactory.h" #include "AUD_FileFactory.h"
#include "AUD_Buffer.h"
#include <cstring> #include <cstring>

View File

@@ -34,7 +34,7 @@
#include "AUD_IFactory.h" #include "AUD_IFactory.h"
#include "AUD_Reference.h" #include "AUD_Reference.h"
class AUD_Buffer; #include "AUD_Buffer.h"
#include <string> #include <string>

File diff suppressed because it is too large Load Diff

View File

@@ -41,13 +41,11 @@
class AUD_JOSResampleReader : public AUD_ResampleReader class AUD_JOSResampleReader : public AUD_ResampleReader
{ {
private: private:
static const unsigned int m_nL = 9; typedef void (AUD_JOSResampleReader::*AUD_resample_f)(double target_factor, int length, sample_t* buffer);
static const unsigned int m_nN = 23;
static const unsigned int m_Nz = 32; static const int m_len = 292874;
static const unsigned int m_L = 1 << m_nL; static const int m_L = 2048;
static const unsigned int m_NN = 1 << m_nN;
static const float m_coeff[]; static const float m_coeff[];
static const float m_diff[];
/** /**
* The reader channels. * The reader channels.
@@ -62,25 +60,44 @@ private:
/** /**
* The subsample position in the cache. * The subsample position in the cache.
*/ */
unsigned int m_P; double m_P;
/** /**
* The input data buffer. * The input data buffer.
*/ */
AUD_Buffer m_buffer; AUD_Buffer m_buffer;
/**
* Double buffer for the sums.
*/
AUD_Buffer m_sums;
/** /**
* How many samples in the cache are valid. * How many samples in the cache are valid.
*/ */
int m_cache_valid; int m_cache_valid;
/**
* Resample function.
*/
AUD_resample_f m_resample;
/**
* Last resampling factor.
*/
double m_last_factor;
// hide copy constructor and operator= // hide copy constructor and operator=
AUD_JOSResampleReader(const AUD_JOSResampleReader&); AUD_JOSResampleReader(const AUD_JOSResampleReader&);
AUD_JOSResampleReader& operator=(const AUD_JOSResampleReader&); AUD_JOSResampleReader& operator=(const AUD_JOSResampleReader&);
void reset(); void reset();
void updateBuffer(int size, float factor, int samplesize); void updateBuffer(int size, double factor, int samplesize);
void resample(double target_factor, int length, sample_t* buffer);
void resample_mono(double target_factor, int length, sample_t* buffer);
void resample_stereo(double target_factor, int length, sample_t* buffer);
public: public:
/** /**

File diff suppressed because it is too large Load Diff

View File

@@ -196,3 +196,8 @@ AUD_Reference<AUD_IReader> AUD_SequencerFactory::createReader()
{ {
return new AUD_SequencerReader(this); return new AUD_SequencerReader(this);
} }
AUD_Reference<AUD_IReader> AUD_SequencerFactory::createQualityReader()
{
return new AUD_SequencerReader(this, true);
}

View File

@@ -110,6 +110,8 @@ public:
void remove(AUD_Reference<AUD_SequencerEntry> entry); void remove(AUD_Reference<AUD_SequencerEntry> entry);
virtual AUD_Reference<AUD_IReader> createReader(); virtual AUD_Reference<AUD_IReader> createReader();
AUD_Reference<AUD_IReader> createQualityReader();
}; };
#endif //AUD_SEQUENCERFACTORY #endif //AUD_SEQUENCERFACTORY

View File

@@ -34,9 +34,10 @@
typedef std::list<AUD_Reference<AUD_SequencerHandle> >::iterator AUD_HandleIterator; typedef std::list<AUD_Reference<AUD_SequencerHandle> >::iterator AUD_HandleIterator;
typedef std::list<AUD_Reference<AUD_SequencerEntry> >::iterator AUD_EntryIterator; typedef std::list<AUD_Reference<AUD_SequencerEntry> >::iterator AUD_EntryIterator;
AUD_SequencerReader::AUD_SequencerReader(AUD_Reference<AUD_SequencerFactory> factory) : AUD_SequencerReader::AUD_SequencerReader(AUD_Reference<AUD_SequencerFactory> factory, bool quality) :
m_position(0), m_device(factory->m_specs), m_factory(factory), m_status(0), m_entry_status(0) m_position(0), m_device(factory->m_specs), m_factory(factory), m_status(0), m_entry_status(0)
{ {
m_device.setQuality(quality);
} }
AUD_SequencerReader::~AUD_SequencerReader() AUD_SequencerReader::~AUD_SequencerReader()

View File

@@ -73,7 +73,7 @@ public:
* \param reader The reader to mix. * \param reader The reader to mix.
* \param specs The target specification. * \param specs The target specification.
*/ */
AUD_SequencerReader(AUD_Reference<AUD_SequencerFactory> factory); AUD_SequencerReader(AUD_Reference<AUD_SequencerFactory> factory, bool quality = false);
/** /**
* Destroys the reader. * Destroys the reader.

View File

@@ -33,11 +33,8 @@
#include "AUD_IReader.h" #include "AUD_IReader.h"
#include "AUD_Mixer.h" #include "AUD_Mixer.h"
#include "AUD_IFactory.h" #include "AUD_IFactory.h"
#ifdef WITH_SAMPLERATE #include "AUD_JOSResampleReader.h"
#include "AUD_SRCResampleReader.h"
#else
#include "AUD_LinearResampleReader.h" #include "AUD_LinearResampleReader.h"
#endif
#include <cstring> #include <cstring>
#include <cmath> #include <cmath>
@@ -665,6 +662,7 @@ void AUD_SoftwareDevice::create()
m_doppler_factor = 1.0f; m_doppler_factor = 1.0f;
m_distance_model = AUD_DISTANCE_MODEL_INVERSE_CLAMPED; m_distance_model = AUD_DISTANCE_MODEL_INVERSE_CLAMPED;
m_flags = 0; m_flags = 0;
m_quality = false;
pthread_mutexattr_t attr; pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr); pthread_mutexattr_init(&attr);
@@ -701,6 +699,7 @@ void AUD_SoftwareDevice::mix(data_t* buffer, int length)
int pos; int pos;
bool eos; bool eos;
std::list<AUD_Reference<AUD_SoftwareDevice::AUD_SoftwareHandle> > stopSounds; std::list<AUD_Reference<AUD_SoftwareDevice::AUD_SoftwareHandle> > stopSounds;
std::list<AUD_Reference<AUD_SoftwareDevice::AUD_SoftwareHandle> > pauseSounds;
sample_t* buf = m_buffer.getBuffer(); sample_t* buf = m_buffer.getBuffer();
m_mixer->clear(length); m_mixer->clear(length);
@@ -752,7 +751,7 @@ void AUD_SoftwareDevice::mix(data_t* buffer, int length)
sound->m_stop(sound->m_stop_data); sound->m_stop(sound->m_stop_data);
if(sound->m_keep) if(sound->m_keep)
sound->pause(); pauseSounds.push_back(sound);
else else
stopSounds.push_back(sound); stopSounds.push_back(sound);
} }
@@ -768,6 +767,13 @@ void AUD_SoftwareDevice::mix(data_t* buffer, int length)
stopSounds.pop_front(); stopSounds.pop_front();
sound->stop(); sound->stop();
} }
while(!pauseSounds.empty())
{
sound = pauseSounds.front();
pauseSounds.pop_front();
sound->pause();
}
} }
unlock(); unlock();
@@ -779,6 +785,11 @@ void AUD_SoftwareDevice::setPanning(AUD_IHandle* handle, float pan)
h->m_user_pan = pan; h->m_user_pan = pan;
} }
void AUD_SoftwareDevice::setQuality(bool quality)
{
m_quality = quality;
}
void AUD_SoftwareDevice::setSpecs(AUD_Specs specs) void AUD_SoftwareDevice::setSpecs(AUD_Specs specs)
{ {
m_specs.specs = specs; m_specs.specs = specs;
@@ -806,11 +817,10 @@ AUD_Reference<AUD_IHandle> AUD_SoftwareDevice::play(AUD_Reference<AUD_IReader> r
AUD_Reference<AUD_ResampleReader> resampler; AUD_Reference<AUD_ResampleReader> resampler;
// resample // resample
#ifdef WITH_SAMPLERATE if(m_quality)
resampler = new AUD_SRCResampleReader(reader, m_specs.specs); resampler = new AUD_JOSResampleReader(reader, m_specs.specs);
#else else
resampler = new AUD_LinearResampleReader(reader, m_specs.specs); resampler = new AUD_LinearResampleReader(reader, m_specs.specs);
#endif
reader = AUD_Reference<AUD_IReader>(resampler); reader = AUD_Reference<AUD_IReader>(resampler);
// rechannel // rechannel

View File

@@ -203,6 +203,11 @@ protected:
*/ */
AUD_Reference<AUD_Mixer> m_mixer; AUD_Reference<AUD_Mixer> m_mixer;
/**
* Whether to do high or low quality resampling.
*/
bool m_quality;
/** /**
* Initializes member variables. * Initializes member variables.
*/ */
@@ -283,6 +288,7 @@ private:
public: public:
static void setPanning(AUD_IHandle* handle, float pan); static void setPanning(AUD_IHandle* handle, float pan);
void setQuality(bool quality);
virtual AUD_DeviceSpecs getSpecs() const; virtual AUD_DeviceSpecs getSpecs() const;
virtual AUD_Reference<AUD_IHandle> play(AUD_Reference<AUD_IReader> reader, bool keep = false); virtual AUD_Reference<AUD_IHandle> play(AUD_Reference<AUD_IReader> reader, bool keep = false);

View File

@@ -31,7 +31,6 @@
#include "AUD_SndFileFactory.h" #include "AUD_SndFileFactory.h"
#include "AUD_SndFileReader.h" #include "AUD_SndFileReader.h"
#include "AUD_Buffer.h"
#include <cstring> #include <cstring>

View File

@@ -34,7 +34,7 @@
#include "AUD_IFactory.h" #include "AUD_IFactory.h"
#include "AUD_Reference.h" #include "AUD_Reference.h"
class AUD_Buffer; #include "AUD_Buffer.h"
#include <string> #include <string>

View File

@@ -372,14 +372,7 @@ void sound_load(struct Main *bmain, struct bSound* sound)
AUD_Device* sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start, float volume) AUD_Device* sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start, float volume)
{ {
AUD_Device* mixdown = AUD_openReadDevice(specs); return AUD_openMixdownDevice(specs, scene->sound_scene, volume, start / FPS);
AUD_setDeviceVolume(mixdown, volume);
AUD_setSequencerSpecs(scene->sound_scene, specs.specs);
AUD_freeHandle(AUD_playDevice(mixdown, scene->sound_scene, start / FPS));
return mixdown;
} }
void sound_create_scene(struct Scene *scene) void sound_create_scene(struct Scene *scene)

View File

@@ -1016,15 +1016,15 @@ void KX_KetsjiEngine::DoSound(KX_Scene* scene)
if(dev) if(dev)
{ {
AUD_Vector3 v; AUD_Vector3 v;
AUD_Quaternion q; float q[4];
cam->NodeGetWorldPosition().getValue(v.get()); cam->NodeGetWorldPosition().getValue(v.get());
dev->setListenerLocation(v); dev->setListenerLocation(v);
cam->GetLinearVelocity().getValue(v.get()); cam->GetLinearVelocity().getValue(v.get());
dev->setListenerVelocity(v); dev->setListenerVelocity(v);
cam->NodeGetWorldOrientation().getRotation().getValue(q.get()); cam->NodeGetWorldOrientation().getRotation().getValue(q);
dev->setListenerOrientation(q); dev->setListenerOrientation(AUD_Quaternion(q[3], q[0], q[1], q[2]));
} }
} }

View File

@@ -224,14 +224,14 @@ bool KX_SoundActuator::Update(double curtime, bool frame)
{ {
KX_GameObject* obj = (KX_GameObject*)this->GetParent(); KX_GameObject* obj = (KX_GameObject*)this->GetParent();
AUD_Vector3 v; AUD_Vector3 v;
AUD_Quaternion q; float q[4];
obj->NodeGetWorldPosition().getValue(v.get()); obj->NodeGetWorldPosition().getValue(v.get());
handle3d->setSourceLocation(v); handle3d->setSourceLocation(v);
obj->GetLinearVelocity().getValue(v.get()); obj->GetLinearVelocity().getValue(v.get());
handle3d->setSourceVelocity(v); handle3d->setSourceVelocity(v);
obj->NodeGetWorldOrientation().getRotation().getValue(q.get()); obj->NodeGetWorldOrientation().getRotation().getValue(q);
handle3d->setSourceOrientation(q); handle3d->setSourceOrientation(AUD_Quaternion(q[3], q[0], q[1], q[2]));
} }
result = true; result = true;
} }