Revision: 39427
          
http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=39427
Author:   nexyon
Date:     2011-08-15 21:50:09 +0000 (Mon, 15 Aug 2011)
Log Message:
-----------
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.

Modified Paths:
--------------
    branches/soc-2011-pepper/intern/audaspace/intern/AUD_C-API.cpp
    branches/soc-2011-pepper/intern/audaspace/intern/AUD_C-API.h
    branches/soc-2011-pepper/intern/audaspace/intern/AUD_FileFactory.cpp
    branches/soc-2011-pepper/intern/audaspace/intern/AUD_FileFactory.h
    branches/soc-2011-pepper/intern/audaspace/intern/AUD_JOSResampleReader.cpp
    branches/soc-2011-pepper/intern/audaspace/intern/AUD_JOSResampleReader.h
    branches/soc-2011-pepper/intern/audaspace/intern/AUD_SequencerFactory.cpp
    branches/soc-2011-pepper/intern/audaspace/intern/AUD_SequencerFactory.h
    branches/soc-2011-pepper/intern/audaspace/intern/AUD_SequencerReader.cpp
    branches/soc-2011-pepper/intern/audaspace/intern/AUD_SequencerReader.h
    branches/soc-2011-pepper/intern/audaspace/intern/AUD_SoftwareDevice.cpp
    branches/soc-2011-pepper/intern/audaspace/intern/AUD_SoftwareDevice.h
    branches/soc-2011-pepper/intern/audaspace/sndfile/AUD_SndFileFactory.cpp
    branches/soc-2011-pepper/intern/audaspace/sndfile/AUD_SndFileFactory.h
    branches/soc-2011-pepper/source/blender/blenkernel/intern/sound.c
    branches/soc-2011-pepper/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
    branches/soc-2011-pepper/source/gameengine/Ketsji/KX_SoundActuator.cpp

Added Paths:
-----------
    
branches/soc-2011-pepper/intern/audaspace/intern/AUD_JOSResampleReaderCoeff.cpp

Modified: branches/soc-2011-pepper/intern/audaspace/intern/AUD_C-API.cpp
===================================================================
--- branches/soc-2011-pepper/intern/audaspace/intern/AUD_C-API.cpp      
2011-08-15 19:30:24 UTC (rev 39426)
+++ branches/soc-2011-pepper/intern/audaspace/intern/AUD_C-API.cpp      
2011-08-15 21:50:09 UTC (rev 39427)
@@ -1182,7 +1182,7 @@
                AUD_SequencerFactory* f = 
dynamic_cast<AUD_SequencerFactory*>(sound->get());
 
                f->setSpecs(specs.specs);
-               AUD_Reference<AUD_IReader> reader = f->createReader();
+               AUD_Reference<AUD_IReader> reader = f->createQualityReader();
                reader->seek(start);
                AUD_Reference<AUD_IWriter> writer = 
AUD_FileWriter::createWriter(filename, specs, format, codec, bitrate);
                AUD_FileWriter::writeReader(reader, writer, length, buffersize);
@@ -1195,6 +1195,28 @@
        }
 }
 
+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()
 {
        return AUD_device;

Modified: branches/soc-2011-pepper/intern/audaspace/intern/AUD_C-API.h
===================================================================
--- branches/soc-2011-pepper/intern/audaspace/intern/AUD_C-API.h        
2011-08-15 19:30:24 UTC (rev 39426)
+++ branches/soc-2011-pepper/intern/audaspace/intern/AUD_C-API.h        
2011-08-15 21:50:09 UTC (rev 39427)
@@ -527,6 +527,8 @@
 
 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
 extern PyObject* AUD_getPythonFactory(AUD_Sound* sound);
 

Modified: branches/soc-2011-pepper/intern/audaspace/intern/AUD_FileFactory.cpp
===================================================================
--- branches/soc-2011-pepper/intern/audaspace/intern/AUD_FileFactory.cpp        
2011-08-15 19:30:24 UTC (rev 39426)
+++ branches/soc-2011-pepper/intern/audaspace/intern/AUD_FileFactory.cpp        
2011-08-15 21:50:09 UTC (rev 39427)
@@ -38,7 +38,6 @@
 #endif
 
 #include "AUD_FileFactory.h"
-#include "AUD_Buffer.h"
 
 #include <cstring>
 

Modified: branches/soc-2011-pepper/intern/audaspace/intern/AUD_FileFactory.h
===================================================================
--- branches/soc-2011-pepper/intern/audaspace/intern/AUD_FileFactory.h  
2011-08-15 19:30:24 UTC (rev 39426)
+++ branches/soc-2011-pepper/intern/audaspace/intern/AUD_FileFactory.h  
2011-08-15 21:50:09 UTC (rev 39427)
@@ -34,7 +34,7 @@
 
 #include "AUD_IFactory.h"
 #include "AUD_Reference.h"
-class AUD_Buffer;
+#include "AUD_Buffer.h"
 
 #include <string>
 

Modified: 
branches/soc-2011-pepper/intern/audaspace/intern/AUD_JOSResampleReader.cpp
===================================================================
--- branches/soc-2011-pepper/intern/audaspace/intern/AUD_JOSResampleReader.cpp  
2011-08-15 19:30:24 UTC (rev 39426)
+++ branches/soc-2011-pepper/intern/audaspace/intern/AUD_JOSResampleReader.cpp  
2011-08-15 21:50:09 UTC (rev 39427)
@@ -30,20 +30,30 @@
 
 #include "AUD_JOSResampleReader.h"
 
+#include "AUD_JOSResampleReaderCoeff.cpp"
+
 #include <cmath>
 #include <cstring>
+#include <iostream>
 
 #define CC m_channels + channel
 
-#define AUD_RATE_MAX 10
+#define AUD_RATE_MAX 256
+#define SHIFT_BITS 12
+#define double_to_fp(x) (lrint(x * double(1 << SHIFT_BITS)))
+#define int_to_fp(x) (x << SHIFT_BITS)
+#define fp_to_int(x) (x >> SHIFT_BITS)
+#define fp_to_double(x) (x * 1.0/(1 << SHIFT_BITS))
+#define fp_rest(x) (x & ((1 << SHIFT_BITS) - 1))
+#define fp_rest_to_double(x) fp_to_double(fp_rest(x))
 
-AUD_JOSResampleReader::AUD_JOSResampleReader(AUD_Reference<AUD_IReader> reader,
-                                                                               
                   AUD_Specs specs) :
+AUD_JOSResampleReader::AUD_JOSResampleReader(AUD_Reference<AUD_IReader> 
reader, AUD_Specs specs) :
        AUD_ResampleReader(reader, specs.rate),
-       m_channels(reader->getSpecs().channels),
+       m_channels(AUD_CHANNELS_INVALID),
        m_n(0),
        m_P(0),
-       m_cache_valid(0)
+       m_cache_valid(0),
+       m_last_factor(0)
 {
 }
 
@@ -52,20 +62,22 @@
        m_cache_valid = 0;
        m_n = 0;
        m_P = 0;
+       m_last_factor = 0;
 }
 
-void AUD_JOSResampleReader::updateBuffer(int size, float factor, int 
samplesize)
+void AUD_JOSResampleReader::updateBuffer(int size, double factor, int 
samplesize)
 {
        unsigned int len;
+       double num_samples = double(m_len) / double(m_L);
        // first calculate what length we need right now
        if(factor >= 1)
-               len = m_Nz;
+               len = ceil(num_samples);
        else
-               len = (unsigned int)(ceil(m_Nz / factor));
+               len = (unsigned int)(ceil(num_samples / factor));
 
        // then check if afterwards the length is enough for the maximum rate
-       if(len + size < m_Nz * AUD_RATE_MAX)
-               len = size - m_Nz * AUD_RATE_MAX;
+       if(len + size < num_samples * AUD_RATE_MAX)
+               len = size - num_samples * AUD_RATE_MAX;
 
        if(m_n > len)
        {
@@ -79,6 +91,125 @@
        m_buffer.assureSize((m_cache_valid + size) * samplesize, true);
 }
 
+#define RESAMPLE_METHOD(name, left, right) void 
AUD_JOSResampleReader::name(double target_factor, int length, sample_t* buffer)\
+{\
+       sample_t* buf = m_buffer.getBuffer();\
+\
+       int P, l, end, channel, i;\
+       double eta, v, f_increment, factor;\
+\
+       m_sums.assureSize(m_channels * sizeof(double));\
+       double* sums = reinterpret_cast<double*>(m_sums.getBuffer());\
+       sample_t* data;\
+       const float* coeff = m_coeff;\
+\
+       unsigned int P_increment;\
+\
+       for(unsigned int t = 0; t < length; t++)\
+       {\
+               factor = (m_last_factor * (length - t) + target_factor * t) / 
length;\
+\
+               if(factor >= 1)\
+                       f_increment = m_L;\
+               else\
+                       f_increment = factor * m_L;\
+\
+               P_increment = double_to_fp(f_increment);\
+               P = double_to_fp(m_P * f_increment);\
+\
+               end = (int_to_fp(m_len) - P) / P_increment - 1;\
+               if(m_n < end)\
+                       end = m_n;\
+\
+               memset(sums, 0, sizeof(double) * m_channels);\
+\
+               P += P_increment * end;\
+               data = buf + (m_n - end) * m_channels;\
+               l = fp_to_int(P);\
+\
+               for(i = 0; i <= end; i++)\
+               {\
+                       eta = fp_rest_to_double(P);\
+                       v = coeff[l] + eta * (coeff[l+1] - coeff[l]);\
+                       P -= P_increment;\
+                       l = fp_to_int(P);\
+                       left\
+               }\
+\
+               P = -P;\
+\
+               end = (int_to_fp(m_len) - P) / P_increment - 1;\
+               if(m_cache_valid - m_n - 2 < end)\
+                       end = m_cache_valid - m_n - 2;\
+\
+               P += P_increment * end;\
+               data = buf + (m_n + 2 + end) * m_channels - 1;\
+               l = fp_to_int(P);\
+\
+               for(i = 0; i <= end; i++)\
+               {\
+                       eta = fp_rest_to_double(P);\
+                       v = coeff[l] + eta * (coeff[l+1] - coeff[l]);\
+                       P -= P_increment;\
+                       l = fp_to_int(P);\
+                       right\
+               }\
+\
+               for(channel = 0; channel < m_channels; channel++)\
+               {\
+                       *buffer = f_increment / m_L * sums[channel];\
+                       buffer++;\
+               }\
+\
+               m_P += fmod(1.0 / factor, 1.0);\
+               m_n += floor(1.0 / factor);\
+\
+               if(m_P >= 1.0)\
+               {\
+                       m_P -= 1.0;\
+                       m_n++;\
+               }\
+       }\
+}
+
+RESAMPLE_METHOD(resample, {
+                               channel = 0;
+                               do
+                               {
+                                       sums[channel] += *data * v;
+                                       channel++;
+                                       data++;
+                               }
+                               while(channel < m_channels);
+}, {
+                               channel = m_channels;
+                               do
+                               {
+                                       channel--;
+                                       sums[channel] += *data * v;
+                                       data--;
+                               }
+                               while(channel);
+})
+
+RESAMPLE_METHOD(resample_mono, {
+                               *sums += *data * v;
+                               data++;
+}, {
+                               *sums += *data * v;
+                               data--;
+})
+
+RESAMPLE_METHOD(resample_stereo, {
+                               sums[0] += data[0] * v;
+                               sums[1] += data[1] * v;
+                               data+=2;
+}, {
+                               data-=2;
+                               sums[0] += data[1] * v;
+                               sums[1] += data[2] * v;
+})
+
 void AUD_JOSResampleReader::seek(int position)
 {
        position = floor(position * double(m_reader->getSpecs().rate) / 
double(m_rate));
@@ -93,7 +224,7 @@
 
 int AUD_JOSResampleReader::getPosition() const
 {
-       return floor((m_reader->getPosition() + double(m_P) / 4294967296.0) // 
2^32
+       return floor((m_reader->getPosition() + double(m_P))
                                 * m_rate / m_reader->getSpecs().rate);
 }
 
@@ -112,27 +243,42 @@
        AUD_Specs specs = m_reader->getSpecs();
 
        int samplesize = AUD_SAMPLE_SIZE(specs);
-       float factor = float(m_rate) / float(m_reader->getSpecs().rate);
+       double target_factor = double(m_rate) / double(specs.rate);
        eos = false;
        int len;
-       sample_t* buf;
+       double num_samples = double(m_len) / double(m_L);
 
        // check for channels changed
-
        if(specs.channels != m_channels)
        {
                m_channels = specs.channels;
                reset();
+
+               switch(m_channels)
+               {
+               case AUD_CHANNELS_MONO:
+                       m_resample = &AUD_JOSResampleReader::resample_mono;
+                       break;
+               case AUD_CHANNELS_STEREO:
+                       m_resample = &AUD_JOSResampleReader::resample_stereo;
+                       break;
+               default:
+                       m_resample = &AUD_JOSResampleReader::resample;
+                       break;
+               }
        }
 
-       if(factor == 1 && (m_P == 1))
+       if(m_last_factor == 0)
+               m_last_factor = target_factor;
+
+       if(target_factor == 1 && m_last_factor == 1 && (m_P == 0))
        {
                // can read directly!
 
                len = length - (m_cache_valid - m_n);
 
-               updateBuffer(len, factor, samplesize);
-               buf = m_buffer.getBuffer();
+               updateBuffer(len, target_factor, samplesize);
+               sample_t* buf = m_buffer.getBuffer();
 
                m_reader->read(len, eos, buf + m_cache_valid * m_channels);
                m_cache_valid += len;
@@ -148,159 +294,57 @@
                return;
        }
 
+       // use minimum for the following calculations
+       double factor = AUD_MIN(target_factor, m_last_factor);
 
        if(factor >= 1)
-               len = (m_n - m_cache_valid) + int(ceil(length / factor)) + m_Nz;
+               len = (m_n - m_cache_valid) + int(ceil(length / factor)) + 
ceil(num_samples);
        else
-               len = (m_n - m_cache_valid) + int(ceil(length / factor) + 
ceil(m_Nz / factor));
+               len = (m_n - m_cache_valid) + int(ceil(length / factor) + 
ceil(num_samples / factor));
 
        if(len > 0)
        {
                int should = len;
 
                updateBuffer(len, factor, samplesize);
-               buf = m_buffer.getBuffer();
 
-               m_reader->read(len, eos, buf + m_cache_valid * m_channels);
+               m_reader->read(len, eos, m_buffer.getBuffer() + m_cache_valid * 
m_channels);
                m_cache_valid += len;
 
                if(len < should)
                {
-                       if(eos)
-                       {
-                               // end of stream, let's check how many more 
samples we can produce
-                               if(factor >= 1)
-                                       len = floor((len - (m_n - 
m_cache_valid)) * factor);
-                               else

@@ Diff output truncated at 10240 characters. @@
_______________________________________________
Bf-blender-cvs mailing list
Bf-blender-cvs@blender.org
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to