Blender V2.61 - r43446

AUD_JOSResampleReader.cpp

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * Copyright 2009-2011 Jörg Hermann Müller
00005  *
00006  * This file is part of AudaSpace.
00007  *
00008  * Audaspace is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * AudaSpace is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with Audaspace; if not, write to the Free Software Foundation,
00020  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00021  *
00022  * ***** END GPL LICENSE BLOCK *****
00023  */
00024 
00029 #include "AUD_JOSResampleReader.h"
00030 
00031 #include "AUD_JOSResampleReaderCoeff.cpp"
00032 
00033 #include <cmath>
00034 #include <cstring>
00035 #include <iostream>
00036 
00037 /* MSVC does not have lrint */
00038 #ifdef _MSC_VER
00039 #ifdef _M_X64
00040 #include <emmintrin.h>
00041 static inline int lrint(double d)
00042 {
00043         return _mm_cvtsd_si32(_mm_load_sd(&d));
00044 }
00045 #else
00046 static inline int lrint(double d)
00047 {
00048     int i;
00049 
00050     _asm{
00051         fld d
00052         fistp i
00053     };
00054 
00055     return i;
00056 }
00057 #endif
00058 #endif
00059 
00060 #define CC m_channels + channel
00061 
00062 #define AUD_RATE_MAX 256
00063 #define SHIFT_BITS 12
00064 #define double_to_fp(x) (lrint(x * double(1 << SHIFT_BITS)))
00065 #define int_to_fp(x) (x << SHIFT_BITS)
00066 #define fp_to_int(x) (x >> SHIFT_BITS)
00067 #define fp_to_double(x) (x * 1.0/(1 << SHIFT_BITS))
00068 #define fp_rest(x) (x & ((1 << SHIFT_BITS) - 1))
00069 #define fp_rest_to_double(x) fp_to_double(fp_rest(x))
00070 
00071 AUD_JOSResampleReader::AUD_JOSResampleReader(AUD_Reference<AUD_IReader> reader, AUD_Specs specs) :
00072     AUD_ResampleReader(reader, specs.rate),
00073     m_channels(AUD_CHANNELS_INVALID),
00074     m_n(0),
00075     m_P(0),
00076     m_cache_valid(0),
00077     m_last_factor(0)
00078 {
00079 }
00080 
00081 void AUD_JOSResampleReader::reset()
00082 {
00083     m_cache_valid = 0;
00084     m_n = 0;
00085     m_P = 0;
00086     m_last_factor = 0;
00087 }
00088 
00089 void AUD_JOSResampleReader::updateBuffer(int size, double factor, int samplesize)
00090 {
00091     unsigned int len;
00092     double num_samples = double(m_len) / double(m_L);
00093     // first calculate what length we need right now
00094     if(factor >= 1)
00095         len = ceil(num_samples);
00096     else
00097         len = (unsigned int)(ceil(num_samples / factor));
00098 
00099     // then check if afterwards the length is enough for the maximum rate
00100     if(len + size < num_samples * AUD_RATE_MAX)
00101         len = num_samples * AUD_RATE_MAX - size;
00102 
00103     if(m_n > len)
00104     {
00105         sample_t* buf = m_buffer.getBuffer();
00106         len = m_n - len;
00107         memmove(buf, buf + len * m_channels, (m_cache_valid - len) * samplesize);
00108         m_n -= len;
00109         m_cache_valid -= len;
00110     }
00111 
00112     m_buffer.assureSize((m_cache_valid + size) * samplesize, true);
00113 }
00114 
00115 #define RESAMPLE_METHOD(name, left, right) void AUD_JOSResampleReader::name(double target_factor, int length, sample_t* buffer)\
00116 {\
00117     sample_t* buf = m_buffer.getBuffer();\
00118 \
00119     unsigned int P, l;\
00120     int end, channel, i;\
00121     double eta, v, f_increment, factor;\
00122 \
00123     m_sums.assureSize(m_channels * sizeof(double));\
00124     double* sums = reinterpret_cast<double*>(m_sums.getBuffer());\
00125     sample_t* data;\
00126     const float* coeff = m_coeff;\
00127 \
00128     unsigned int P_increment;\
00129 \
00130     for(unsigned int t = 0; t < length; t++)\
00131     {\
00132         factor = (m_last_factor * (length - t - 1) + target_factor * (t + 1)) / length;\
00133 \
00134         memset(sums, 0, sizeof(double) * m_channels);\
00135 \
00136         if(factor >= 1)\
00137         {\
00138             P = double_to_fp(m_P * m_L);\
00139 \
00140             end = floor(m_len / double(m_L) - m_P) - 1;\
00141             if(m_n < end)\
00142                 end = m_n;\
00143 \
00144             data = buf + (m_n - end) * m_channels;\
00145             l = fp_to_int(P);\
00146             eta = fp_rest_to_double(P);\
00147             l += m_L * end;\
00148 \
00149             for(i = 0; i <= end; i++)\
00150             {\
00151                 v = coeff[l] + eta * (coeff[l+1] - coeff[l]);\
00152                 l -= m_L;\
00153                 left\
00154             }\
00155 \
00156             P = int_to_fp(m_L) - P;\
00157 \
00158             end = floor((m_len - 1) / double(m_L) + m_P) - 1;\
00159             if(m_cache_valid - m_n - 2 < end)\
00160                 end = m_cache_valid - m_n - 2;\
00161 \
00162             data = buf + (m_n + 2 + end) * m_channels - 1;\
00163             l = fp_to_int(P);\
00164             eta = fp_rest_to_double(P);\
00165             l += m_L * end;\
00166 \
00167             for(i = 0; i <= end; i++)\
00168             {\
00169                 v = coeff[l] + eta * (coeff[l+1] - coeff[l]);\
00170                 l -= m_L;\
00171                 right\
00172             }\
00173 \
00174             for(channel = 0; channel < m_channels; channel++)\
00175             {\
00176                 *buffer = sums[channel];\
00177                 buffer++;\
00178             }\
00179         }\
00180         else\
00181         {\
00182             f_increment = factor * m_L;\
00183             P_increment = double_to_fp(f_increment);\
00184             P = double_to_fp(m_P * f_increment);\
00185 \
00186             end = (int_to_fp(m_len) - P) / P_increment - 1;\
00187             if(m_n < end)\
00188                 end = m_n;\
00189 \
00190             P += P_increment * end;\
00191             data = buf + (m_n - end) * m_channels;\
00192             l = fp_to_int(P);\
00193 \
00194             for(i = 0; i <= end; i++)\
00195             {\
00196                 eta = fp_rest_to_double(P);\
00197                 v = coeff[l] + eta * (coeff[l+1] - coeff[l]);\
00198                 P -= P_increment;\
00199                 l = fp_to_int(P);\
00200                 left\
00201             }\
00202 \
00203             P = -P;\
00204 \
00205             end = (int_to_fp(m_len) - P) / P_increment - 1;\
00206             if(m_cache_valid - m_n - 2 < end)\
00207                 end = m_cache_valid - m_n - 2;\
00208 \
00209             P += P_increment * end;\
00210             data = buf + (m_n + 2 + end) * m_channels - 1;\
00211             l = fp_to_int(P);\
00212 \
00213             for(i = 0; i <= end; i++)\
00214             {\
00215                 eta = fp_rest_to_double(P);\
00216                 v = coeff[l] + eta * (coeff[l+1] - coeff[l]);\
00217                 P -= P_increment;\
00218                 l = fp_to_int(P);\
00219                 right\
00220             }\
00221 \
00222             for(channel = 0; channel < m_channels; channel++)\
00223             {\
00224                                 *buffer = factor * sums[channel];\
00225                 buffer++;\
00226             }\
00227         }\
00228 \
00229         m_P += fmod(1.0 / factor, 1.0);\
00230         m_n += floor(1.0 / factor);\
00231 \
00232         while(m_P >= 1.0)\
00233         {\
00234             m_P -= 1.0;\
00235             m_n++;\
00236         }\
00237     }\
00238 }
00239 
00240 RESAMPLE_METHOD(resample, {
00241                 channel = 0;
00242                 do
00243                 {
00244                     sums[channel] += *data * v;
00245                     channel++;
00246                     data++;
00247                 }
00248                 while(channel < m_channels);
00249 }, {
00250                 channel = m_channels;
00251                 do
00252                 {
00253                     channel--;
00254                     sums[channel] += *data * v;
00255                     data--;
00256                 }
00257                 while(channel);
00258 })
00259 
00260 RESAMPLE_METHOD(resample_mono, {
00261                 *sums += *data * v;
00262                 data++;
00263 }, {
00264                 *sums += *data * v;
00265                 data--;
00266 })
00267 
00268 RESAMPLE_METHOD(resample_stereo, {
00269                 sums[0] += data[0] * v;
00270                 sums[1] += data[1] * v;
00271                 data+=2;
00272 }, {
00273                 data-=2;
00274                 sums[0] += data[1] * v;
00275                 sums[1] += data[2] * v;
00276 })
00277 
00278 void AUD_JOSResampleReader::seek(int position)
00279 {
00280     position = floor(position * double(m_reader->getSpecs().rate) / double(m_rate));
00281     m_reader->seek(position);
00282     reset();
00283 }
00284 
00285 int AUD_JOSResampleReader::getLength() const
00286 {
00287     return floor(m_reader->getLength() * double(m_rate) / double(m_reader->getSpecs().rate));
00288 }
00289 
00290 int AUD_JOSResampleReader::getPosition() const
00291 {
00292     return floor((m_reader->getPosition() + double(m_P))
00293                  * m_rate / m_reader->getSpecs().rate);
00294 }
00295 
00296 AUD_Specs AUD_JOSResampleReader::getSpecs() const
00297 {
00298     AUD_Specs specs = m_reader->getSpecs();
00299     specs.rate = m_rate;
00300     return specs;
00301 }
00302 
00303 void AUD_JOSResampleReader::read(int& length, bool& eos, sample_t* buffer)
00304 {
00305     if(length == 0)
00306         return;
00307 
00308     AUD_Specs specs = m_reader->getSpecs();
00309 
00310     int samplesize = AUD_SAMPLE_SIZE(specs);
00311     double target_factor = double(m_rate) / double(specs.rate);
00312     eos = false;
00313     int len;
00314     double num_samples = double(m_len) / double(m_L);
00315 
00316     // check for channels changed
00317     if(specs.channels != m_channels)
00318     {
00319         m_channels = specs.channels;
00320         reset();
00321 
00322         switch(m_channels)
00323         {
00324         case AUD_CHANNELS_MONO:
00325             m_resample = &AUD_JOSResampleReader::resample_mono;
00326             break;
00327         case AUD_CHANNELS_STEREO:
00328             m_resample = &AUD_JOSResampleReader::resample_stereo;
00329             break;
00330         default:
00331             m_resample = &AUD_JOSResampleReader::resample;
00332             break;
00333         }
00334     }
00335 
00336     if(m_last_factor == 0)
00337         m_last_factor = target_factor;
00338 
00339     if(target_factor == 1 && m_last_factor == 1 && (m_P == 0))
00340     {
00341         // can read directly!
00342 
00343         len = length - (m_cache_valid - m_n);
00344 
00345         updateBuffer(len, target_factor, samplesize);
00346         sample_t* buf = m_buffer.getBuffer();
00347 
00348         m_reader->read(len, eos, buf + m_cache_valid * m_channels);
00349         m_cache_valid += len;
00350 
00351         length = m_cache_valid - m_n;
00352 
00353         if(length > 0)
00354         {
00355             memcpy(buffer, buf + m_n * m_channels, length * samplesize);
00356             m_n += length;
00357         }
00358 
00359         return;
00360     }
00361 
00362     // use minimum for the following calculations
00363     double factor = AUD_MIN(target_factor, m_last_factor);
00364 
00365     if(factor >= 1)
00366         len = (int(m_n) - m_cache_valid) + int(ceil(length / factor)) + ceil(num_samples);
00367     else
00368         len = (int(m_n) - m_cache_valid) + int(ceil(length / factor) + ceil(num_samples / factor));
00369 
00370     if(len > 0)
00371     {
00372         int should = len;
00373 
00374         updateBuffer(len, factor, samplesize);
00375 
00376         m_reader->read(len, eos, m_buffer.getBuffer() + m_cache_valid * m_channels);
00377         m_cache_valid += len;
00378 
00379         if(len < should)
00380         {
00381             if(len == 0 && eos)
00382                 length = 0;
00383             else
00384             {
00385                 // use maximum for the following calculations
00386                 factor = AUD_MAX(target_factor, m_last_factor);
00387 
00388                 if(eos)
00389                 {
00390                     // end of stream, let's check how many more samples we can produce
00391                     len = floor((m_cache_valid - m_n) * factor);
00392                     if(len < length)
00393                         length = len;
00394                 }
00395                 else
00396                 {
00397                     // not enough data available yet, so we recalculate how many samples we can calculate
00398                     if(factor >= 1)
00399                         len = floor((num_samples + m_cache_valid - m_n) * factor);
00400                     else
00401                         len = floor((num_samples * factor + m_cache_valid - m_n) * factor);
00402                     if(len < length)
00403                         length = len;
00404                 }
00405             }
00406         }
00407     }
00408 
00409     (this->*m_resample)(target_factor, length, buffer);
00410 
00411     m_last_factor = target_factor;
00412 
00413     if(m_n > m_cache_valid)
00414     {
00415         m_n = m_cache_valid;
00416     }
00417 
00418     eos = eos && ((m_n == m_cache_valid) || (length == 0));
00419 }