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:
@@ -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;
|
||||||
|
@@ -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);
|
||||||
|
|
||||||
|
@@ -38,7 +38,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "AUD_FileFactory.h"
|
#include "AUD_FileFactory.h"
|
||||||
#include "AUD_Buffer.h"
|
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
@@ -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
@@ -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:
|
||||||
/**
|
/**
|
||||||
|
29295
intern/audaspace/intern/AUD_JOSResampleReaderCoeff.cpp
Normal file
29295
intern/audaspace/intern/AUD_JOSResampleReaderCoeff.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||||
|
}
|
||||||
|
@@ -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
|
||||||
|
@@ -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()
|
||||||
|
@@ -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.
|
||||||
|
@@ -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
|
||||||
|
@@ -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);
|
||||||
|
@@ -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>
|
||||||
|
|
||||||
|
@@ -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>
|
||||||
|
|
||||||
|
@@ -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)
|
||||||
|
@@ -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]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user