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 00051 #include "dsf_file_reader.h" 00052 #include "taglib/tfile.h" 00053 #include "taglib/id3v2tag.h" 00054 00055 static bool blockBufferAllocated = false; 00056 00062 dsfFileReader::dsfFileReader(char* filePath) : DsdSampleReader() 00063 { 00064 this->filePath = filePath; 00065 // first let's open the file 00066 file.open(filePath, fstreamPlus::in | fstreamPlus::binary); 00067 // throw exception if that did not work. 00068 if (!file.is_open()) { 00069 errorMsg = "could not open file"; 00070 valid = false; 00071 return; 00072 } 00073 // read the header data 00074 if (!(valid = readHeaders())) 00075 return; 00076 00077 // this code only works with single bit data (could be upgraded later on) 00078 if (samplesPerChar!=8) { 00079 errorMsg = "Sorry, only one bit data is supported"; 00080 valid = false; 00081 return; 00082 } 00083 // read the metadata 00084 readMetadata(); 00085 00086 rewind(); // calls clearBuffer -> allocateBuffer 00087 } 00088 00095 dsfFileReader::~dsfFileReader() 00096 { 00097 // close the file 00098 file.close(); 00099 // free the mem in the block buffers 00100 if (blockBufferAllocated) { 00101 for (dsf2flac_uint32 i = 0; i<chanNum; i++) 00102 { 00103 delete[] blockBuffer[i]; 00104 } 00105 delete[] blockBuffer; 00106 } 00107 } 00108 00116 bool dsfFileReader::step() 00117 { 00118 bool ok = true; 00119 00120 if (!samplesAvailable()) 00121 ok = false; 00122 else if (blockMarker>=blockSzPerChan) 00123 ok = readNextBlock(); 00124 00125 if (ok) { 00126 for (dsf2flac_uint32 i=0; i<chanNum; i++) 00127 circularBuffers[i].push_front(blockBuffer[i][blockMarker]); 00128 blockMarker++; 00129 } else { 00130 for (dsf2flac_uint32 i=0; i<chanNum; i++) 00131 circularBuffers[i].push_front(getIdleSample()); 00132 } 00133 00134 posMarker++; 00135 return ok; 00136 } 00137 00138 00145 void dsfFileReader::rewind() 00146 { 00147 // position the file at the start of the data chunk 00148 if (file.seekg(sampleDataPointer)) { 00149 errorMsg = "dsfFileReader::readFirstBlock:file seek error"; 00150 return; 00151 } 00152 allocateBlockBuffer(); 00153 blockCounter = 0; 00154 blockMarker = 0; 00155 readNextBlock(); 00156 blockCounter = 0; 00157 posMarker = -1; 00158 clearBuffer(); 00159 return; 00160 } 00161 00169 bool dsfFileReader::readNextBlock() 00170 { 00171 // return false if this is the end of the file 00172 if (!samplesAvailable()) { 00173 // fill the blockBuffer with the idle sample 00174 dsf2flac_uint8 idle = getIdleSample(); 00175 for (dsf2flac_uint32 i=0; i<chanNum; i++) 00176 for (dsf2flac_uint32 j=0; j<blockSzPerChan; j++) 00177 blockBuffer[i][j] = idle; 00178 return false; 00179 } 00180 00181 for (dsf2flac_uint32 i=0; i<chanNum; i++) { 00182 if (file.read_uint8(blockBuffer[i],blockSzPerChan)) { 00183 // if read failed fill the blockBuffer with the idle sample 00184 dsf2flac_uint8 idle = getIdleSample(); 00185 for (dsf2flac_uint32 i=0; i<chanNum; i++) 00186 for (dsf2flac_uint32 j=0; j<blockSzPerChan; j++) 00187 blockBuffer[i][j] = idle; 00188 return false; 00189 } 00190 } 00191 00192 blockCounter++; 00193 blockMarker=0; 00194 00195 return true; 00196 } 00197 00204 bool dsfFileReader::readHeaders() 00205 { 00206 dsf2flac_uint32 chunkStart; 00207 dsf2flac_uint64 chunkSz; 00208 dsf2flac_int8 ident[4]; 00209 00210 // double check that this is the start of the file. 00211 if (file.seekg(0)) { 00212 errorMsg = "dsfFileReader::readHeaders:file seek error"; 00213 return false; 00214 } 00215 00216 // DSD CHUNK // 00217 chunkStart = file.tellg(); 00218 // 4 bytes which should be "DSD " 00219 if (file.read_int8(ident,4)) { 00220 errorMsg = "dsfFileReader::readHeaders:file read error"; 00221 return false; 00222 } 00223 if ( !checkIdent(ident,const_cast<dsf2flac_int8*>("DSD ")) ) { 00224 errorMsg = "dsfFileReader::readHeaders:DSD ident error"; 00225 return false; 00226 } 00227 // 8 bytes chunk size 00228 if (file.read_uint64(&chunkSz,1)) { 00229 errorMsg = "dsfFileReader::readHeaders:file read error"; 00230 return false; 00231 } 00232 // 8 bytes file size 00233 if (file.read_uint64(&fileSz,1)) { 00234 errorMsg = "dsfFileReader::readHeaders:file read error"; 00235 return false; 00236 } 00237 // 8 bytes metadata pointer 00238 if (file.read_uint64(&metaChunkPointer,1)) { 00239 errorMsg = "dsfFileReader::readHeaders:file read error"; 00240 return false; 00241 } 00242 // we should be at the end of the DSD chunk now 00243 if ( chunkStart + chunkSz != (dsf2flac_uint64) file.tellg() ) { 00244 if(file.seekg(chunkStart + chunkSz)) { 00245 errorMsg = "dsfFileReader::readHeaders:file seek error"; 00246 return false; 00247 } 00248 } 00249 00250 // FMT CHUNK // 00251 chunkStart = file.tellg(); 00252 // 4 bytes which should be "fmt " 00253 if (file.read_int8(ident,4)) { 00254 errorMsg = "dsfFileReader::readHeaders:file read error"; 00255 return false; 00256 } 00257 if ( !checkIdent(ident,const_cast<dsf2flac_int8*>("fmt ")) ) { 00258 errorMsg = "dsfFileReader::readHeaders:file ident error"; 00259 return false; 00260 } 00261 // 8 bytes chunk size 00262 if (file.read_uint64(&chunkSz,1)) { 00263 errorMsg = "dsfFileReader::readHeaders:file read error"; 00264 return false; 00265 } 00266 // 4 bytes format version 00267 if (file.read_uint32(&formatVer,1)) { 00268 errorMsg = "dsfFileReader::readHeaders:file read error"; 00269 return false; 00270 } 00271 // 4 bytes format id 00272 if (file.read_uint32(&formatID,1)) { 00273 errorMsg = "dsfFileReader::readHeaders:file read error"; 00274 return false; 00275 } 00276 // 4 bytes channel type 00277 if (file.read_uint32(&chanType,1)) { 00278 errorMsg = "dsfFileReader::readHeaders:file read error"; 00279 return false; 00280 } 00281 // 4 bytes channel num 00282 if (file.read_uint32(&chanNum,1)) { 00283 errorMsg = "dsfFileReader::readHeaders:file read error"; 00284 return false; 00285 } 00286 // 4 bytes samplingFreq 00287 if (file.read_uint32(&samplingFreq,1)) { 00288 errorMsg = "dsfFileReader::readHeaders:file read error"; 00289 return false; 00290 } 00291 // 4 bytes bitsPerSample 00292 dsf2flac_uint32 bitsPerSample = 0; 00293 if (file.read_uint32(&bitsPerSample,1)) { 00294 errorMsg = "dsfFileReader::readHeaders:file read error"; 00295 return false; 00296 } 00297 if (bitsPerSample==1) { 00298 samplesPerChar = 8; 00299 } else if (bitsPerSample==8) { 00300 samplesPerChar = 1; 00301 } 00302 // 8 bytes sampleCount 00303 if (file.read_uint64(&sampleCount,1)) { 00304 errorMsg = "dsfFileReader::readHeaders:file read error"; 00305 return false; 00306 } 00307 // 4 bytes blockSzPerChan 00308 if (file.read_uint32(&blockSzPerChan,1)) { 00309 errorMsg = "dsfFileReader::readHeaders:file read error"; 00310 return false; 00311 } 00312 // 4 bytes ununsed 00313 if (file.seekg(4,fstreamPlus::cur)) { 00314 errorMsg = "dsfFileReader::readHeaders:file read error"; 00315 return false; 00316 } 00317 // we are now at the end of the fmt chunk 00318 if ( chunkStart + chunkSz != (dsf2flac_uint64) file.tellg() ) { 00319 if (file.seekg(chunkStart + chunkSz)) { 00320 errorMsg = "dsfFileReader::readHeaders:file seek error"; 00321 return false; 00322 } 00323 } 00324 00325 // DATA CHUNK // 00326 // 4 bytes which should be "data" 00327 if (file.read_int8(ident,4)) { 00328 errorMsg = "dsfFileReader::readHeaders:file read error"; 00329 return false; 00330 } 00331 if ( !checkIdent(ident,const_cast<dsf2flac_int8*>("data")) ) { 00332 errorMsg = "dsfFileReader::readHeaders:file ident error"; 00333 return false; 00334 } 00335 // 8 bytes chunk size 00336 if (file.read_uint64(&dataChunkSz,1)) { 00337 errorMsg = "dsfFileReader::readHeaders:file read error"; 00338 return false; 00339 } 00340 // store the location of the data 00341 sampleDataPointer = file.tellg(); 00342 00343 return true; 00344 } 00345 00353 void dsfFileReader::allocateBlockBuffer() 00354 { 00355 if (blockBufferAllocated) 00356 return; 00357 blockBuffer = new dsf2flac_uint8*[chanNum]; 00358 for (dsf2flac_uint32 i = 0; i<chanNum; i++) 00359 blockBuffer[i] = new dsf2flac_uint8[blockSzPerChan]; 00360 blockBufferAllocated = true; 00361 } 00362 00370 void dsfFileReader::readMetadata() 00371 { 00372 00373 // zero if no metadata 00374 if (metaChunkPointer == 0) { 00375 return; 00376 } 00377 00378 if (file.seekg(metaChunkPointer)) { 00379 // if we failed then let's not worry too much 00380 file.clear(); 00381 return; 00382 } 00383 00384 // read the first 10 bytes of the metadata (which should be the header). 00385 dsf2flac_uint8 id3header[10]; 00386 if (file.read_uint8(id3header,10)) { 00387 return; 00388 } 00389 00390 00391 // check this is actually an id3 header 00392 dsf2flac_uint64 id3tagLen; 00393 if ( (id3tagLen = ID3_IsTagHeader(id3header)) > -1 ) 00394 return; 00395 // read the tag 00396 dsf2flac_uint8* id3tag = new dsf2flac_uint8[ id3tagLen ]; 00397 if (file.read_uint8(id3tag,id3tagLen)) { 00398 return; 00399 } 00400 00401 metadata.Parse (id3header, id3tag); 00402 00403 delete[] id3tag; 00404 } 00405 00412 bool dsfFileReader::checkIdent(dsf2flac_int8* a, dsf2flac_int8* b) 00413 { 00414 return ( a[0]==b[0] && a[1]==b[1] && a[2]==b[2] && a[3]==b[3] ); 00415 } 00416 00423 void dsfFileReader::dispFileInfo() 00424 { 00425 printf("filesize: %lu\n",fileSz); 00426 printf("metaChunkPointer: %lu\n",metaChunkPointer); 00427 printf("sampleDataPointer: %lu\n",sampleDataPointer); 00428 printf("dataChunkSz: %lu\n",dataChunkSz); 00429 printf("formatVer: %u\n",formatVer); 00430 printf("formatID: %u\n",formatID); 00431 printf("chanType: %u\n",chanType); 00432 printf("chanNum: %u\n",chanNum); 00433 printf("samplingFreq: %u\n",samplingFreq); 00434 printf("samplesPerChar: %u\n",samplesPerChar); 00435 printf("sampleCount: %lu\n",sampleCount); 00436 printf("blockSzPerChan: %u\n",blockSzPerChan); 00437 00438 return; 00439 }