DSF2FLAC
|
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 }