CLAM-Development
1.1
|
00001 #include "BufferedSDIFFileReader.hxx" 00002 #include "DataUtil.hxx" 00003 #include <limits.h> 00004 00005 namespace CLAM 00006 { 00007 00008 BufferedSDIFFileReader::BufferedSDIFFileReader(const SDIFInConfig& argSDIFInConfig) : 00009 mSDIFFileReader(argSDIFInConfig), 00010 frameBufferPosition(1), 00011 mFrameLoadChunkSize( DEFAULT_FRAME_LOAD_CHUNK_SIZE ), 00012 mThreshholdForPreloading( DEFAULT_THRESHHOLD_FOR_PRELOADING ), 00013 mThreshholdForPreloadingOnThread( DEFAULT_THRESHHOLD_FOR_PRELOADING_ON_THREAD ), 00014 mReaderHasMoreFrames( true ), 00015 dequeMutex(), 00016 readSDIFMutex() 00017 { 00018 mFunctor = makeMemberFunctor0( *this, BufferedSDIFFileReader, Run ); 00019 00020 Configure(argSDIFInConfig); 00021 } 00022 00023 BufferedSDIFFileReader::~BufferedSDIFFileReader() 00024 { 00025 for (unsigned int counter = 0; counter < frameBuffer.size(); counter++) 00026 { 00027 delete frameBuffer[counter]; 00028 } 00029 } 00030 00031 bool BufferedSDIFFileReader::Configure(const SDIFInConfig& config) 00032 { 00033 bool response; 00034 if ( response = mSDIFFileReader.Configure(config) ) 00035 { 00036 // if the metadata has defined the number of milliseconds to preload 00037 // preload the corresponding number of frames. 00038 if ( config.HasNumberOfFramesToPreload() ) 00039 { 00040 //std::cout << "Preloading " << config.GetNumberOfFramesToPreload()+1 << " frames" << std::endl; 00041 LoadFramesIntoBuffer( config.GetNumberOfFramesToPreload()+1 ); 00042 } 00043 else 00044 { 00045 LoadFramesIntoBuffer( DEFAULT_INITIAL_NUMBER_OF_FRAMES_TO_BUFFER ); 00046 } 00047 00048 if ( config.HasNumberOfFramesToLoad() ) 00049 { 00050 totalNumberOfFramesToLoad = config.GetNumberOfFramesToLoad(); 00051 } 00052 else 00053 { 00054 if (config.HasNumberOfFramesToPreload()) 00055 totalNumberOfFramesToLoad = config.GetNumberOfFramesToPreload()+1; 00056 else 00057 totalNumberOfFramesToLoad = INT_MAX; 00058 } 00059 } 00060 00061 return response; 00062 } 00063 00064 const SDIFInConfig BufferedSDIFFileReader::GetConfig() 00065 { 00066 return dynamic_cast<const SDIFInConfig&>(mSDIFFileReader.GetConfig()); 00067 } 00068 00069 int BufferedSDIFFileReader::GetFrameBufferPosition() 00070 { 00071 return frameBufferPosition; 00072 } 00073 00074 void BufferedSDIFFileReader::SetFrameBufferPosition(int argFrameBufferPosition) 00075 { 00076 frameBufferPosition = argFrameBufferPosition; 00077 } 00078 00079 Frame* BufferedSDIFFileReader::GetFrame( int frameBufferPosition ) 00080 { 00081 Mutex::ScopedLock lock( dequeMutex ); 00082 00083 Frame* requestedFrame = frameBuffer.at(frameBufferPosition); 00084 00085 return requestedFrame; 00086 } 00087 00088 Frame* BufferedSDIFFileReader::ReadFrame() 00089 { 00090 int framesTillTheEnd = frameBuffer.size() - frameBufferPosition; 00091 if ((mReaderHasMoreFrames == true) && (framesTillTheEnd < mThreshholdForPreloading)) 00092 { 00093 mReaderHasMoreFrames = LoadFramesIntoBuffer(mFrameLoadChunkSize); 00094 } 00095 00096 if ( frameBuffer.size() == 0 ) 00097 { 00098 return NULL; 00099 } 00100 else 00101 { 00102 Mutex::ScopedLock lock( dequeMutex ); 00103 00104 //std::cout << "Retrieving buffer pos: " << frameBufferPosition << ", size: " << frameBuffer.size() << std::endl; 00105 Frame* nextFrame = frameBuffer.at(frameBufferPosition); 00106 frameBufferPosition++; 00107 00108 if (nextFrame == NULL) 00109 { 00110 std::cout << "next frame is null" << std::endl; 00111 } 00112 00113 return nextFrame; 00114 } 00115 } 00116 00117 bool BufferedSDIFFileReader::LoadFramesIntoBuffer(int argNumberOfBuffers) 00118 { 00119 // when we read in the SDIFFrames, let's first put them in a temporary 00120 // list object so we can avoid locking the frameBuffer every iteration 00121 // of the loop 00122 std::deque<Frame*> tempFrameBuffer; 00123 00124 // this object locks the mSDIFFileReader until the scopedlock goes 00125 // out of scope and is garbage collected. its destructor frees the lock 00126 { 00127 Mutex::ScopedLock lock( readSDIFMutex ); 00128 00129 // here's the loop where we read in the desired number of buffers 00130 for (int counter = 0; counter < argNumberOfBuffers; counter++) 00131 { 00132 Frame* aFrame = new Frame(); 00133 aFrame->AddSpectralPeakArray(); 00134 aFrame->AddResidualSpec(); 00135 aFrame->AddFundamental(); 00136 aFrame->AddSynthAudioFrame(); 00137 aFrame->UpdateData(); 00138 00139 TTime frameCenterTime; 00140 00141 // we read in the frame 00142 mReaderHasMoreFrames = mSDIFFileReader.ReadFrame( aFrame->GetFundamental(), aFrame->GetSpectralPeakArray(), aFrame->GetResidualSpec(), frameCenterTime ); 00143 00144 // we'll update the frame position variable when we actually add these to 00145 // the frameVector 00146 00147 // as long as there was something to read, add the frame to the temporary buffer 00148 if (mReaderHasMoreFrames) 00149 { 00150 aFrame->SetCenterTime(frameCenterTime); 00151 00152 tempFrameBuffer.push_back( aFrame ); 00153 } 00154 else 00155 { 00156 std::cout << "BufferedSDIFReader: could only load " << counter << " of "; 00157 std::cout << argNumberOfBuffers << " frames." << std::endl; 00158 delete aFrame; 00159 break; 00160 } 00161 } 00162 } 00163 00164 // now let's copy the frames from the temporary buffer to the frameBuffer 00165 Mutex::ScopedLock lock( dequeMutex ); 00166 for (unsigned int counter = 0; counter < tempFrameBuffer.size(); counter++) 00167 { 00168 Frame* aFrame = tempFrameBuffer.at(counter); 00169 frameBuffer.push_back( aFrame ); 00170 } 00171 00172 return mReaderHasMoreFrames; 00173 } 00174 00175 int BufferedSDIFFileReader::GetNumberOfFramesLoaded() 00176 { 00177 Mutex::ScopedLock lock( dequeMutex ); 00178 return frameBuffer.size(); 00179 } 00180 00181 void BufferedSDIFFileReader::LoadFramesIntoBufferOnThread(Thread* argThread) 00182 { 00183 CLAM_ASSERT(argThread != NULL, "Thread* given to BufferedSDIFFileReader may not be null!"); 00184 00185 mThreadPtr = argThread; 00186 try // Note the exception handling 00187 { 00188 mThreadPtr->SetThreadCode( mFunctor ); 00189 00190 mThreadPtr->Start(); 00191 00192 //mThreadPtr->Stop(); 00193 00194 } 00195 catch( std::exception& e ) // Here we handle standard library exceptions 00196 { 00197 std::cerr << e.what() << std::endl; 00198 std::string msg("BufferedSDIFFileReader: exception when starting thread. SDIFFile will be loaded on main thread."); 00199 std::cerr << msg << std::endl; 00200 } 00201 } 00202 00203 void BufferedSDIFFileReader::StopLoadingFramesIntoBufferOnThread() 00204 { 00205 try // Note the exception handling 00206 { 00207 if ( mThreadPtr != NULL) 00208 { 00209 mThreadPtr = NULL; 00210 } 00211 } 00212 catch( std::exception& e ) // Here we handle standard library exceptions 00213 { 00214 std::cerr << e.what() << std::endl; 00215 std::string msg("BufferedSDIFFileReader: exception when stopping thread."); 00216 std::cerr << msg << std::endl; 00217 } 00218 } 00219 00220 bool BufferedSDIFFileReader::IsThreaded() 00221 { 00222 return mThreadPtr != NULL; 00223 } 00224 00225 void BufferedSDIFFileReader::Run() 00226 { 00227 int iterationsSinceLastExecution = 0; 00228 while ( mReaderHasMoreFrames && totalNumberOfFramesToLoad <= frameBuffer.size() ) 00229 { 00230 //std::cout << "Thread <" << mThreadPtr << "> this <" << this << "> is loading buffers." << std::endl; 00231 mReaderHasMoreFrames = LoadFramesIntoBuffer(mFrameLoadChunkSize); 00232 iterationsSinceLastExecution = 0; 00233 mThreadPtr->Yield(); 00234 } 00235 } 00236 00237 00238 00239 } // END CLAM 00240 00241