Audaspace:
[blender.git] / intern / audaspace / intern / AUD_JOSResampleReader.cpp
index fd811d617c613494cfc35782a14c20b1e4b56a5a..62fab48272bf1fff4c0d5836b8cf402a5482870a 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
  * Copyright 2009-2011 Jörg Hermann Müller
 #include <cstring>
 #include <iostream>
 
+/* MSVC does not have lrint */
+#ifdef _MSC_VER
+#ifdef _M_X64
+#include <emmintrin.h>
+static inline int lrint(double d)
+{
+               return _mm_cvtsd_si32(_mm_load_sd(&d));
+}
+#else
+static inline int lrint(double d)
+{
+       int i;
+
+       _asm{
+               fld d
+               fistp i
+       };
+
+       return i;
+}
+#endif
+#endif
+
 #define CC m_channels + channel
 
 #define AUD_RATE_MAX 256
@@ -47,7 +68,7 @@
 #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(boost::shared_ptr<AUD_IReader> reader, AUD_Specs specs) :
        AUD_ResampleReader(reader, specs.rate),
        m_channels(AUD_CHANNELS_INVALID),
        m_n(0),
@@ -77,7 +98,7 @@ void AUD_JOSResampleReader::updateBuffer(int size, double factor, int samplesize
 
        // then check if afterwards the length is enough for the maximum rate
        if(len + size < num_samples * AUD_RATE_MAX)
-               len = size - num_samples * AUD_RATE_MAX;
+               len = num_samples * AUD_RATE_MAX - size;
 
        if(m_n > len)
        {
@@ -95,7 +116,8 @@ void AUD_JOSResampleReader::updateBuffer(int size, double factor, int samplesize
 {\
        sample_t* buf = m_buffer.getBuffer();\
 \
-       int P, l, end, channel, i;\
+       unsigned int P, l;\
+       int end, channel, i;\
        double eta, v, f_increment, factor;\
 \
        m_sums.assureSize(m_channels * sizeof(double));\
@@ -107,64 +129,107 @@ void AUD_JOSResampleReader::updateBuffer(int size, double factor, int samplesize
 \
        for(unsigned int t = 0; t < length; t++)\
        {\
-               factor = (m_last_factor * (length - t) + target_factor * t) / length;\
+               factor = (m_last_factor * (length - t - 1) + target_factor * (t + 1)) / length;\
+\
+               memset(sums, 0, sizeof(double) * m_channels);\
 \
                if(factor >= 1)\
-                       f_increment = m_L;\
-               else\
-                       f_increment = factor * m_L;\
+               {\
+                       P = double_to_fp(m_P * m_L);\
 \
-               P_increment = double_to_fp(f_increment);\
-               P = double_to_fp(m_P * f_increment);\
+                       end = floor(m_len / double(m_L) - m_P) - 1;\
+                       if(m_n < end)\
+                               end = m_n;\
 \
-               end = (int_to_fp(m_len) - P) / P_increment - 1;\
-               if(m_n < end)\
-                       end = m_n;\
+                       data = buf + (m_n - end) * m_channels;\
+                       l = fp_to_int(P);\
+                       eta = fp_rest_to_double(P);\
+                       l += m_L * end;\
 \
-               memset(sums, 0, sizeof(double) * m_channels);\
+                       for(i = 0; i <= end; i++)\
+                       {\
+                               v = coeff[l] + eta * (coeff[l+1] - coeff[l]);\
+                               l -= m_L;\
+                               left\
+                       }\
 \
-               P += P_increment * end;\
-               data = buf + (m_n - end) * m_channels;\
-               l = fp_to_int(P);\
+                       P = int_to_fp(m_L) - 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;\
+                       end = floor((m_len - 1) / double(m_L) + m_P) - 1;\
+                       if(m_cache_valid - m_n - 2 < end)\
+                               end = m_cache_valid - m_n - 2;\
+\
+                       data = buf + (m_n + 2 + end) * m_channels - 1;\
                        l = fp_to_int(P);\
-                       left\
+                       eta = fp_rest_to_double(P);\
+                       l += m_L * end;\
+\
+                       for(i = 0; i <= end; i++)\
+                       {\
+                               v = coeff[l] + eta * (coeff[l+1] - coeff[l]);\
+                               l -= m_L;\
+                               right\
+                       }\
+\
+                       for(channel = 0; channel < m_channels; channel++)\
+                       {\
+                               *buffer = sums[channel];\
+                               buffer++;\
+                       }\
                }\
+               else\
+               {\
+                       f_increment = factor * m_L;\
+                       P_increment = double_to_fp(f_increment);\
+                       P = double_to_fp(m_P * f_increment);\
 \
-               P = -P;\
+                       end = (int_to_fp(m_len) - P) / P_increment - 1;\
+                       if(m_n < end)\
+                               end = m_n;\
 \
-               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 - end) * m_channels;\
+                       l = fp_to_int(P);\
 \
-               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);\
+                               left\
+                       }\
 \
-               for(i = 0; i <= end; i++)\
-               {\
-                       eta = fp_rest_to_double(P);\
-                       v = coeff[l] + eta * (coeff[l+1] - coeff[l]);\
-                       P -= P_increment;\
+                       P = 0 - 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);\
-                       right\
-               }\
 \
-               for(channel = 0; channel < m_channels; channel++)\
-               {\
-                       *buffer = f_increment / m_L * sums[channel];\
-                       buffer++;\
+                       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 = factor * sums[channel];\
+                               buffer++;\
+                       }\
                }\
 \
                m_P += fmod(1.0 / factor, 1.0);\
                m_n += floor(1.0 / factor);\
 \
-               if(m_P >= 1.0)\
+               while(m_P >= 1.0)\
                {\
                        m_P -= 1.0;\
                        m_n++;\
@@ -298,9 +363,9 @@ void AUD_JOSResampleReader::read(int& length, bool& eos, sample_t* buffer)
        double factor = AUD_MIN(target_factor, m_last_factor);
 
        if(factor >= 1)
-               len = (m_n - m_cache_valid) + int(ceil(length / factor)) + ceil(num_samples);
+               len = (int(m_n) - m_cache_valid) + int(ceil(length / factor)) + ceil(num_samples);
        else
-               len = (m_n - m_cache_valid) + int(ceil(length / factor) + ceil(num_samples / factor));
+               len = (int(m_n) - m_cache_valid) + int(ceil(length / factor) + ceil(num_samples / factor));
 
        if(len > 0)
        {