SDIFFile.cxx

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2004 MUSIC TECHNOLOGY GROUP (MTG)
00003  *                         UNIVERSITAT POMPEU FABRA
00004  *
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  */
00021 
00022 #include "SDIFFile.hxx"
00023 #include "ErrOpenFile.hxx"      // error handling on openfile error
00024 #include "ErrFormat.hxx"                // error handling on format error
00025 
00026 #ifdef WIN32
00027         #include <io.h>
00028         #include <fcntl.h>
00029 #else
00030         #include <unistd.h>
00031         #include <sys/types.h>
00032         #include <sys/stat.h>
00033         #include <fcntl.h>
00034 #endif
00035 
00036 
00037 namespace SDIF
00038 {
00039 
00040         File::File(const char* filename,Mode mode):
00041                 mSkipData(false),
00042                 mFirstAccess(true),
00043                 mMode(mode),
00044                 mFile(-1),
00045                 mSize(0)
00046         {
00047                 mpName = new char[ strlen(filename)+1 ];
00048                 strncpy( mpName, filename, strlen(filename)+1 );
00049         }
00050 
00051         File::~File()
00052         {
00053                 delete [] mpName;
00054         }
00055 
00056         void File::Open(void)
00057         {
00058                 int mode = 0;
00059                 if (mMode==eInput) mode = O_RDONLY;             // defined in <fcntl.h>
00060                 if (mMode==eOutput) mode = O_WRONLY|O_CREAT|O_TRUNC;
00061                 if (mMode==eFullDuplex) mode = O_RDWR;
00062 
00063         #ifdef WIN32
00064         mode |= O_BINARY;
00065         #endif
00066 
00067                 if (mFile==-1)
00068                 {
00069                         //Open the file only if unopened
00070                         mFile = open(mpName,mode,0644);
00071 
00072                         if (mFile==-1)
00073                         {
00074                                 // if open file error
00075                                 throw CLAM::ErrOpenFile(mpName);                        // throw filename
00076                         }
00077                 }
00078                 mSize = lseek(mFile,0,SEEK_END);
00079                 lseek(mFile,0,SEEK_SET);
00080         }
00081 
00082         /* close audio file */
00083         void File::Close(void)
00084         {
00085                 if (mFile!=-1)
00086                 {
00087                         //Close the file only if unopened
00088                         close(mFile);
00089                         mFile=-1;
00090                 }
00091         }
00092 
00093         void File::Read(Storage& storage)
00094         {
00095                 while (!Done()) {
00096                         Frame* frame = new Frame;
00097                         Read(*frame);
00098                         storage.Add(frame);
00099                 }
00100         }
00101 
00102         void File::Write(const Storage& storage)
00103         {
00104                 typedef std::list<Frame*>::const_iterator iterator;
00105 
00106                 iterator it = storage.Begin();
00107                 iterator end = storage.End();
00108 
00109                 while (it!=end)
00110                 {
00111                         Frame* frame = *it;
00112                         Write(*frame);
00113                         it++;
00114                 }
00115         }
00116 
00117         void File::Read(TypeId& type)
00118         {
00119                 Read(type.mData,4);
00120         }
00121 
00122         void File::Write(const TypeId& type)
00123         {
00124                 Write(type.mData,4);
00125         }
00126 
00127         void File::Read(FrameHeader& header)
00128         {
00129                 Read(header.mType);
00130                 TRead(header.mSize);
00131         }
00132 
00133         void File::Write(const FrameHeader& header)
00134         {
00135                 Write(header.mType);
00136                 TWrite(header.mSize);
00137         }
00138 
00139         void File::Read(DataFrameHeader& header)
00140         {
00141                 Read((FrameHeader&)header);
00142                 TRead(header.mTime);
00143                 TRead(header.mStreamId);
00144                 TRead(header.mnMatrices);
00145         }
00146 
00147         void File::Write(const DataFrameHeader& header)
00148         {
00149                 Write((FrameHeader&)header);
00150                 TWrite(header.mTime);
00151                 TWrite(header.mStreamId);
00152                 TWrite(header.mnMatrices);
00153         }
00154 
00155         void File::Read(Frame& frame)
00156         {
00157                 if (mFirstAccess)
00158                 {
00159                         mFirstAccess = false;
00160                         OpeningsFrame opening;
00161                         Read(opening);
00162                 }
00163 
00164                 CLAM::TInt32 p = Pos()+FrameHeader::SizeInFile();
00165 
00166                 Read(frame.mHeader);
00167 
00168                 CLAM::TInt32 readSize = frame.mHeader.mSize;
00169                 frame.mHeader.mSize = DataFrameHeader::SizeInFile();
00170 
00171                 int tmp = frame.mHeader.mnMatrices;
00172                 frame.mHeader.mnMatrices = 0; // frame.Add will increase this
00173                 for (int i=0;i<tmp;i++)
00174                 {
00175                         MatrixHeader header;
00176                         File::Read(header);
00177                         Matrix* pMatrix = 0;
00178                         switch (header.mDataType)
00179                         {
00180                         case eFloat32:
00181                                 pMatrix = new ConcreteMatrix<CLAM::TFloat32>(header); break;
00182                         case eFloat64:
00183                                 pMatrix = new ConcreteMatrix<CLAM::TFloat64>(header); break;
00184                         case eInt32:
00185                                 pMatrix = new ConcreteMatrix<CLAM::TInt32>(header); break;
00186                         case eInt64:
00187                                 pMatrix = new ConcreteMatrix<CLAM::TInt64>(header); break;
00188                         case eUTF8byte:
00189                                 pMatrix = new ConcreteMatrix<TUTF8byte>(header); break;
00190                         case eByte:
00191                                 pMatrix = new ConcreteMatrix<CLAM::TByte>(header); break;
00192                         default:
00193                         // +++ how do we handle unknown types ???
00194                                 std::cerr << "SDIFFile.Read(Frame). Received a matrix header with an unknown type: <" << header.mDataType << ">" << std::endl;
00195                                 pMatrix = new ConcreteMatrix<CLAM::TByte>(header); break;
00196                         };
00197                         File::ReadMatrixData(*pMatrix);
00198                         frame.Add(pMatrix);
00199                 }
00200 
00201                 if (readSize-frame.mHeader.mSize==8)
00202                 {
00203                         // This is a kludge to read SDIF files as generated by the
00204                         // SMSTools smscommandline application. The framesize as
00205                         // specified in the frame header of these files has been
00206                         // calculate incorrectly (the size of the frame type and
00207                         // frame size fields itself are included in the total size)
00208                         // This result in the frame size as read from the file
00209                         // (readSize) being the real (calculated during read) frame
00210                         // size frame.mHeader.mSize + 8. If we encounter this, and
00211                         // the following data a frame header as used in the SMS-SDIF
00212                         // files, then we silently accept and continue.
00213                         int tmp = Pos();
00214                         if (Done())
00215                         {
00216                                 readSize -= 8;
00217                         }
00218                         else
00219                         {
00220                                 TypeId t;
00221                                 Read(t);
00222                                 Pos(tmp);
00223                                 if (t=="1STF" || t=="1FQ0" || t=="1TRC")
00224                                 {
00225                                         readSize -= 8;
00226                                 }
00227                         }
00228                 }
00229                 CLAM_ASSERT(frame.mHeader.mSize == readSize,
00230                         "Reading Frame, calculated size does not match read size");
00231                 CLAM_ASSERT(Pos()-p == readSize,
00232                         "Reading Frame, size-in-file does not match read size");
00233         }
00234 
00235         void File::Write(const Frame& frame)
00236         {
00237                 if (mFirstAccess)
00238                 {
00239                         mFirstAccess = false;
00240                         OpeningsFrame opening;
00241                         Write(opening);
00242                 }
00243 
00244                 CLAM::TInt32 writeSize = frame.mHeader.mSize;
00245                 CLAM::TInt32 p = Pos()+FrameHeader::SizeInFile();
00246 
00247                 Write(frame.mHeader);
00248 
00249                 typedef std::list<Matrix*>::const_iterator iterator;
00250 
00251                 iterator it = frame.mMatrixList.begin();
00252                 iterator end = frame.mMatrixList.end();
00253 
00254                 while (it!=end)
00255                 {
00256                         Matrix* pMatrix = *it;
00257                         File::Write(*pMatrix);
00258                         it++;
00259                 }
00260 
00261                 CLAM_ASSERT(Pos()-p == writeSize,
00262                         "Incorrect framesize written in SDIF file");
00263         }
00264 
00265         void File::Read(OpeningsFrame& frame)
00266         {
00267                 Read(frame.mHeader);
00268                 TRead(frame.mSpecVersion);
00269                 TRead(frame.mStandardTypesVersion);
00270         }
00271 
00272         void File::Write(const OpeningsFrame& frame)
00273         {
00274                 Write(frame.mHeader);
00275                 TWrite(frame.mSpecVersion);
00276                 TWrite(frame.mStandardTypesVersion);
00277         }
00278 
00279         void File::Read(MatrixHeader& header)
00280         {
00281                 Read(header.mType);
00282                 CLAM::TInt32 tmp;
00283                 TRead(tmp);
00284                 header.mDataType = (DataType) tmp;
00285                 TRead(header.mnRows);
00286                 TRead(header.mnColumns);
00287         }
00288 
00289         void File::Write(const MatrixHeader& header)
00290         {
00291                 Write(header.mType);
00292                 CLAM::TInt32 tmp = header.mDataType;
00293                 TWrite(tmp);
00294                 TWrite(header.mnRows);
00295                 TWrite(header.mnColumns);
00296         }
00297 
00298         void File::Read(Matrix& matrix)
00299         {
00300                 Read(matrix.mHeader);
00301                 if (mSkipData)
00302                 {
00303                         SkipMatrixData(matrix);
00304                 } else {
00305                         ReadMatrixData(matrix);
00306                 }
00307         }
00308 
00309         void File::Write(const Matrix& matrix)
00310         {
00311                 Write(matrix.mHeader);
00312                 WriteMatrixData(matrix);
00313         }
00314 
00315         void File::SkipMatrixData(const Matrix& matrix)
00316         {
00317                 CLAM::TUInt32 size = matrix.mHeader.mnColumns*matrix.mHeader.mnRows*
00318                         ((matrix.mHeader.mDataType)&0xFF);
00319                 CLAM::TUInt32 padding = 8-size&7;
00320                 Pos(Pos()+size+padding);
00321         }
00322 
00323         #ifdef linux
00324         #include <byteswap.h>
00325         #endif
00326 
00327         #ifdef WIN32
00328         #include <stdlib.h>
00329         #endif
00330 
00331         CLAM::TUInt16 Swap(const CLAM::TUInt16& val)
00332         {
00333         #if defined linux
00334                 return bswap_16(val);
00335         /*#elif defined WIN32
00336                 CLAM::TUInt16 ret;
00337                 _swab((char*)(&val),(char*)(&ret),16);
00338                 return ret;*/
00339         #else
00340                 return (val>>8)|(val<<8);
00341         #endif
00342         }
00343 
00344         CLAM::TUInt32 Swap(const CLAM::TUInt32& val)
00345         {
00346         #if defined linux
00347                 return bswap_32(val);
00348         /*#elif defined WIN32
00349                 CLAM::TUInt32 ret;
00350                 _swab((char*)(&val),(char*)(&ret),32);
00351                 return ret;*/
00352         #else
00353                 CLAM::TUInt32 cp = val;
00354                 CLAM::TByte* ptr=(CLAM::TByte*) &cp;
00355                 static CLAM::TByte tmp;
00356                 tmp=ptr[0]; ptr[0]=ptr[3]; ptr[3]=tmp;
00357                 tmp=ptr[1]; ptr[1]=ptr[2]; ptr[2]=tmp;
00358         return cp;
00359         #endif
00360         }
00361 
00362         CLAM::TUInt64 Swap(const CLAM::TUInt64& val)
00363         {
00364         #if defined linux
00365                 return bswap_64(val);
00366         /*#elif defined WIN32
00367                 CLAM::TUInt64 ret;
00368                 _swab((char*)(&val),(char*)(&ret),64);
00369                 return ret;*/
00370         #else
00371                 CLAM::TUInt64 cp = val;
00372                 CLAM::TByte* ptr=(CLAM::TByte*) &cp;
00373                 static CLAM::TByte tmp;
00374                 tmp=ptr[0]; ptr[0]=ptr[7]; ptr[7]=tmp;
00375                 tmp=ptr[1]; ptr[1]=ptr[6]; ptr[6]=tmp;
00376                 tmp=ptr[2]; ptr[2]=ptr[5]; ptr[5]=tmp;
00377                 tmp=ptr[3]; ptr[3]=ptr[4]; ptr[4]=tmp;
00378         return cp;
00379         #endif
00380         }
00381 
00382         void File::_FixByteOrder(
00383                 CLAM::TByte* ptr,CLAM::TUInt32 nElems,CLAM::TUInt32 elemSize)
00384         {
00385                 switch (elemSize)
00386                 {
00387                         case 1: return;
00388                         case 2:
00389                         {
00390                                 CLAM::TUInt16* fptr = (CLAM::TUInt16*) ptr;
00391                                 for (CLAM::TUInt32 i=0;i<nElems;i++)
00392                                 {
00393                                         *fptr = Swap(*fptr);
00394                                         fptr++;
00395                                 }
00396                                 return;
00397                         }
00398                         case 4:
00399                         {
00400                                 CLAM::TUInt32* fptr = (CLAM::TUInt32*) ptr;
00401                                 for (CLAM::TUInt32 i=0;i<nElems;i++)
00402                                 {
00403                                         *fptr = Swap(*fptr);
00404                                         fptr++;
00405                                 }
00406                                 return;
00407                         }
00408                         case 8:
00409                         {
00410                                 CLAM::TUInt64* fptr = (CLAM::TUInt64*) ptr;
00411                                 for (CLAM::TUInt32 i=0;i<nElems;i++)
00412                                 {
00413                                         *fptr = Swap(*fptr);
00414                                         fptr++;
00415                                 }
00416                                 return;
00417                         }
00418                         default:
00419                                 std::cerr << "SDIFFile._FixByteOrder; Received an unsupported element size. size <" << elemSize << ">" << std::endl;
00420                                 throw;
00421                 }
00422         }
00423 
00424         void File::ReadMatrixData(Matrix& matrix)
00425         {
00426                 CLAM::TByte dum[8];
00427                 CLAM::TUInt32 nElems = matrix.mHeader.mnColumns*matrix.mHeader.mnRows;
00428                 CLAM::TUInt32 elemSize = matrix.mHeader.mDataType&0xFF;
00429                 CLAM::TUInt32 size = nElems*elemSize;
00430 
00431                 CLAM::TUInt32 padding = 8-size&7;
00432 
00433                 matrix.Resize(nElems);
00434                 matrix.SetSize(nElems);
00435 
00436                 Read((CLAM::TByte*) matrix.GetPtr(),size);
00437                 FixByteOrder((CLAM::TByte*) matrix.GetPtr(),nElems,elemSize);
00438 
00439                 Read(dum,padding);
00440         }
00441 
00442         void File::WriteMatrixData(const Matrix& matrix)
00443         {
00444         CLAM::TByte dum[8];
00445                 CLAM::TUInt32 nElems = matrix.mHeader.mnColumns*matrix.mHeader.mnRows;
00446                 CLAM::TUInt32 elemSize = matrix.mHeader.mDataType&0xFF;
00447                 CLAM::TUInt32 size = nElems*elemSize;
00448 
00449                 CLAM::TUInt32 padding = 8-size&7;
00450 
00451                 CLAM::TByte tmp[1024];
00452                 const CLAM::TByte *ptr = (const CLAM::TByte*) const_cast<Matrix&>(matrix).GetPtr();
00453                 while (size)
00454                 {
00455                         int blocksize = size;
00456                         if (blocksize>1024) blocksize = 1024;
00457                         memcpy(tmp,ptr,blocksize);
00458 
00459                         FixByteOrder(tmp,blocksize/elemSize,elemSize);
00460                         Write((CLAM::TByte*) tmp,blocksize);
00461 
00462                         ptr+=blocksize;
00463                         size-=blocksize;
00464                 }
00465 
00466                 Write(dum,padding);
00467         }
00468 
00469 }
00470 
Generated by  doxygen 1.6.3