DSF2FLAC
dsf_file_reader.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 
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 }
 All Classes Files Functions Variables