DSF2FLAC
dsd_decimator.cpp
00001 /*
00002  * dsf2flac - http://code.google.com/p/dsf2flac/
00003  * 
00004  * A file conversion tool for translating dsf dsd audio files into
00005  * flac pcm audio files.
00006  *
00007  * Copyright (c) 2013 by respective authors.
00008  *
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022  *
00023  * 
00024  * Acknowledgements
00025  * 
00026  * Many thanks to the following authors and projects whose work has greatly
00027  * helped the development of this tool.
00028  * 
00029  * 
00030  * Sebastian Gesemann - dsd2pcm (http://code.google.com/p/dsd2pcm/)
00031  * SACD Ripper (http://code.google.com/p/sacd-ripper/)
00032  * Maxim V.Anisiutkin - foo_input_sacd (http://sourceforge.net/projects/sacddecoder/files/)
00033  * Vladislav Goncharov - foo_input_sacd_hq (http://vladgsound.wordpress.com)
00034  * Jesus R - www.sonore.us
00035  * 
00036  */
00037  
00049 #include "dsd_decimator.h"
00050 #include <math.h>
00051 #include "filters.cpp"
00052 
00053 static bool lookupTableAllocated = false;
00054 
00063 dsdDecimator::dsdDecimator(DsdSampleReader *r, dsf2flac_uint32 rate)
00064 {
00065         reader = r;
00066         outputSampleRate = rate;
00067         valid = true;;
00068         errorMsg = "";
00069         
00070         // ratio of out to in sampling rates
00071         ratio = r->getSamplingFreq() / outputSampleRate;
00072         // how many bytes to skip after each out sample calc.
00073         nStep = ratio/8; 
00074         
00075         // load the required filter into the lookuptable based on in and out sample rate
00076         if (ratio == 8)
00077                 initLookupTable(nCoefs_352,coefs_352,tzero_352);
00078         else if (ratio == 16)
00079                 initLookupTable(nCoefs_176,coefs_176,tzero_176);
00080         else if (ratio == 32)
00081                 initLookupTable(nCoefs_88,coefs_88,tzero_88);
00082         else
00083         {
00084                 valid = false;
00085                 errorMsg = "Sorry, incompatible sample rate combination";
00086                 return;
00087         }
00088         // set the buffer to the length of the table if not long enough
00089         if (nLookupTable > reader->getBufferLength())
00090                 reader->setBufferLength(nLookupTable);
00091 }
00092 
00099 dsdDecimator::~dsdDecimator()
00100 {
00101         if (lookupTableAllocated) {
00102                 for (dsf2flac_uint32 n=0; n<nLookupTable; n++)
00103                 {
00104                         delete[] lookupTable[n];
00105                 }
00106                 delete[] lookupTable;
00107         }
00108 }
00109 
00116 dsf2flac_int64 dsdDecimator::getLength()
00117 {
00118         return reader->getLength()/ratio;
00119 }
00126 dsf2flac_float64 dsdDecimator::getPosition()
00127 {
00128         return (dsf2flac_float64)reader->getPosition(tzero)/ratio;
00129 }
00135 dsf2flac_float64 dsdDecimator::dsdDecimator::getFirstValidSample() {
00136         return (dsf2flac_float64)nLookupTable / nStep - (dsf2flac_float64)tzero / ratio;
00137 }
00143 dsf2flac_float64 dsdDecimator::dsdDecimator::getLastValidSample() {
00144         return (dsf2flac_float64)getLength() - (dsf2flac_float64)tzero / ratio;
00145 }
00152 dsf2flac_uint32 dsdDecimator::getOutputSampleRate()
00153 {
00154         return outputSampleRate;
00155 }
00156 
00163 bool dsdDecimator::isValid()
00164 {
00165         return valid;
00166 }
00167 
00174 std::string dsdDecimator::getErrorMsg() {
00175         return errorMsg;
00176 }
00177 
00184 void dsdDecimator::initLookupTable(const int nCoefs,const dsf2flac_float64* coefs,const int tz)
00185 {
00186         tzero = tz;
00187         // calc how big the lookup table is.
00188         nLookupTable = (nCoefs+7)/8;
00189         // allocate the table
00190         lookupTable = new calc_type*[nLookupTable];
00191         for (dsf2flac_uint32 n=0; n<nLookupTable; n++)
00192         {
00193                 lookupTable[n] = new calc_type[256];
00194                 for (int m=0; m<256; m++)
00195                         lookupTable[n][m] = 0;
00196         }
00197         // loop over each entry in the lookup table
00198         for (dsf2flac_uint32 t=0; t<nLookupTable; t++) {
00199                 // how many samples from the filter are spanned in this entry
00200                 int k = nCoefs - t*8;
00201                 if (k>8) k=8;
00202                 // loop over all possible 8bit dsd sequences
00203                 for (int dsdSeq=0; dsdSeq<256; ++dsdSeq) {
00204                         dsf2flac_float64 acc = 0.0;
00205                         for (int bit=0; bit<k; bit++) {
00206                                 dsf2flac_float64 val;
00207                                 if (reader->msbIsPlayedFirst()) {
00208                                         val = -1 + 2*(dsf2flac_float64) !!( dsdSeq & (1<<(7-bit)) );
00209                                 } else {
00210                                         val = -1 + 2*(dsf2flac_float64) !!( dsdSeq & (1<<(bit)) );
00211                                 }
00212                                 acc += val * coefs[t*8+bit];
00213                         }
00214                         lookupTable[t][dsdSeq] = (calc_type) acc;
00215                 }
00216         }
00217         lookupTableAllocated = true;
00218 }
00219 
00220 
00242 template<> void dsdDecimator::getSamples(short int *buffer, dsf2flac_uint32 bufferLen, dsf2flac_float64 scale, dsf2flac_float64 tpdfDitherPeakAmplitude)
00243 {
00244         getSamplesInternal(buffer,bufferLen,scale,tpdfDitherPeakAmplitude,true);
00245 }
00246 template<> void dsdDecimator::getSamples(int *buffer, dsf2flac_uint32 bufferLen, dsf2flac_float64 scale, dsf2flac_float64 tpdfDitherPeakAmplitude)
00247 {
00248         getSamplesInternal(buffer,bufferLen,scale,tpdfDitherPeakAmplitude,true);
00249 }
00250 template<> void dsdDecimator::getSamples(long int *buffer, dsf2flac_uint32 bufferLen, dsf2flac_float64 scale, dsf2flac_float64 tpdfDitherPeakAmplitude)
00251 {
00252         getSamplesInternal(buffer,bufferLen,scale,tpdfDitherPeakAmplitude,true);
00253 }
00254 template<> void dsdDecimator::getSamples(float *buffer, dsf2flac_uint32 bufferLen, dsf2flac_float64 scale, dsf2flac_float64 tpdfDitherPeakAmplitude)
00255 {
00256         getSamplesInternal(buffer,bufferLen,scale,tpdfDitherPeakAmplitude,false);
00257 }
00258 template<> void dsdDecimator::getSamples(double *buffer, dsf2flac_uint32 bufferLen, dsf2flac_float64 scale, dsf2flac_float64 tpdfDitherPeakAmplitude)
00259 {
00260         getSamplesInternal(buffer,bufferLen,scale,tpdfDitherPeakAmplitude,false);
00261 }
00262 
00270 template <typename sampleType> void dsdDecimator::getSamplesInternal(sampleType *buffer, dsf2flac_uint32 bufferLen, dsf2flac_float64 scale, dsf2flac_float64 tpdfDitherPeakAmplitude, bool roundToInt)
00271 {
00272         // check the buffer seems sensible
00273         div_t d = div(bufferLen,getNumChannels());
00274         if (d.rem) {
00275                 fputs("Buffer length is not a multiple of getNumChannels()",stderr);
00276                 exit(EXIT_FAILURE);
00277         }
00278         // get the sample buffer
00279         boost::circular_buffer<dsf2flac_uint8>* buff = reader->getBuffer();
00280         for (int i=0; i<d.quot ; i++) {
00281                 // filter each chan in turn
00282                 for (dsf2flac_uint32 c=0; c<getNumChannels(); c++) {
00283                         calc_type sum = 0.0;
00284                         for (dsf2flac_uint32 t=0; t<nLookupTable; t++) {
00285                                 dsf2flac_uint32 byte = (dsf2flac_uint32) buff[c][t] & 0xFF;
00286                                 sum += lookupTable[t][byte];
00287                         }
00288                         sum = sum*scale;
00289                         // dither before rounding/truncating
00290                         if (tpdfDitherPeakAmplitude > 0) {
00291                                 // TPDF dither
00292                                 calc_type rand1 = ((calc_type) rand()) / ((calc_type) RAND_MAX); // rand value between 0 and 1
00293                                 calc_type rand2 = ((calc_type) rand()) / ((calc_type) RAND_MAX); // rand value between 0 and 1
00294                                 sum = sum + (rand1-rand2)*tpdfDitherPeakAmplitude;
00295                         }
00296                         if (roundToInt)
00297                                 buffer[i*getNumChannels()+c] = static_cast<sampleType>(round(sum));
00298                         else
00299                                 buffer[i*getNumChannels()+c] = static_cast<sampleType>(sum);
00300                 }
00301                 // step the buffer
00302                 for (dsf2flac_uint32 m=0; m<nStep; m++)
00303                         reader->step();
00304         }
00305 }
 All Classes Files Functions Variables