CLAM-Development
1.1
|
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