Audacity  3.0.3
ODComputeSummaryTask.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  ODComputeSummaryTask.cpp
6 
7  Created by Michael Chinen (mchinen) on 6/8/08.
8  Audacity(R) is copyright (c) 1999-2008 Audacity Team.
9  License: GPL v2. See License.txt.
10 
11 ******************************************************************//*******************************************************************/
18 
19 
20 
21 #include "ODComputeSummaryTask.h"
22 #include "../blockfile/ODPCMAliasBlockFile.h"
23 #include "../Sequence.h"
24 #include "../WaveClip.h"
25 #include "../WaveTrack.h"
26 #include <wx/wx.h>
27 
28 //36 blockfiles > 3 minutes stereo 44.1kHz per ODTask::DoSome
29 #define nBlockFilesPerDoSome 36
30 
33 {
34  mMaxBlockFiles = 0;
35  mHasUpdateRan=false;
36 }
37 
38 std::unique_ptr<ODTask> ODComputeSummaryTask::Clone() const
39 {
40  auto clone = std::make_unique<ODComputeSummaryTask>();
41  clone->mDemandSample = GetDemandSample();
42  // This std::move is needed to "upcast" the pointer type
43  return std::move(clone);
44 }
45 
46 
49 {
50  //The terminate block won't allow DoSomeInternal and this method to be run async, so this is thread-safe.
51  //Deref the block files since they are ref'ed when put into the array.
52  mBlockFilesMutex.Lock();
53  mBlockFiles.clear();
54  mBlockFilesMutex.Unlock();
55 }
56 
59 {
60  if(mBlockFiles.size()<=0)
61  {
62  mPercentCompleteMutex.Lock();
63  mPercentComplete = 1.0;
64  mPercentCompleteMutex.Unlock();
65  return;
66  }
67 
68  mBlockFilesMutex.Lock();
69  for(size_t j=0; j < mWaveTracks.size() && mBlockFiles.size();j++)
70  {
71  bool success = false;
72  const auto bf = mBlockFiles[0].lock();
73 
74  sampleCount blockStartSample = 0;
75  sampleCount blockEndSample = 0;
76 
77  if(bf)
78  {
79  // WriteSummary might throw, but this is a worker thread, so stop
80  // the exceptions here!
81  success = GuardedCall<bool>( [&] {
82  bf->DoWriteSummary();
83  return true;
84  } );
85  blockStartSample = bf->GetStart();
86  blockEndSample = blockStartSample + bf->GetLength();
87  }
88  else
89  {
90  success = true;
91  // The block file disappeared.
92  //the waveform in the wavetrack now is shorter, so we need to update mMaxBlockFiles
93  //because now there is less work to do.
95  }
96 
97  if (success)
98  {
99  //take it out of the array - we are done with it.
100  mBlockFiles.erase(mBlockFiles.begin());
101  }
102  else
103  // The task does not make progress
104  ;
105 
106  //This is a bit of a convenience in case someone tries to terminate the task by closing the trackpanel or window.
107  //ODComputeSummaryTask::Terminate() uses this lock to remove everything, and we don't want it to wait since the UI is being blocked.
108  mBlockFilesMutex.Unlock();
109  wxThread::This()->Yield();
110  mBlockFilesMutex.Lock();
111 
112  //update the gui for all associated blocks. It doesn't matter that we're hitting more wavetracks then we should
113  //because this loop runs a number of times equal to the number of tracks, they probably are getting processed in
114  //the next iteration at the same sample window.
115  if (success && bf) {
116  mWaveTrackMutex.Lock();
117  for(size_t i=0;i<mWaveTracks.size();i++)
118  {
119  auto waveTrack = mWaveTracks[i].lock();
120  if(success && waveTrack)
121  {
122 #if 0 // LLL: Commented out while removing OD file handling
123  waveTrack->AddInvalidRegion(blockStartSample,blockEndSample);
124 #endif
125  }
126  }
127  mWaveTrackMutex.Unlock();
128  }
129  }
130 
131  mBlockFilesMutex.Unlock();
132 
133  //update percentage complete.
135 }
136 
140 {
141  if(mMaxBlockFiles==0)
142  return 1.0;
143 
144  float nextPercent;
145  mPercentCompleteMutex.Lock();
146  nextPercent=mPercentComplete + ((float)nBlockFilesPerDoSome/(mMaxBlockFiles+1));
147  mPercentCompleteMutex.Unlock();
148 
149  return nextPercent;
150 }
151 
153 {
154  mHasUpdateRanMutex.Lock();
155  mHasUpdateRan=true;
156  mHasUpdateRanMutex.Unlock();
157 }
158 
160 {
161  bool ret;
162  mHasUpdateRanMutex.Lock();
163  ret = mHasUpdateRan;
164  mHasUpdateRanMutex.Unlock();
165  return ret;
166 }
167 
169 {
170  bool hasUpdateRan;
171  hasUpdateRan = HasUpdateRan();
172  mPercentCompleteMutex.Lock();
173  if(hasUpdateRan)
174  mPercentComplete = (float) 1.0 - ((float)mBlockFiles.size() / (mMaxBlockFiles+1));
175  else
176  mPercentComplete =0.0;
177  mPercentCompleteMutex.Unlock();
178 }
179 
183 {
184  std::vector< std::weak_ptr< ODPCMAliasBlockFile > > tempBlocks;
185 
186  mWaveTrackMutex.Lock();
187 
188  for(size_t j=0;j<mWaveTracks.size();j++)
189  {
190  auto waveTrack = mWaveTracks[j].lock();
191  if(waveTrack)
192  {
193  BlockArray *blocks;
194  Sequence *seq;
195 
196  //gather all the blockfiles that we should process in the wavetrack.
197  for (const auto &clip : waveTrack->GetAllClips()) {
198  seq = clip->GetSequence();
199  //This lock may be way too big since the whole file is one sequence.
200  //TODO: test for large files and find a way to break it down.
201  Sequence::DeleteUpdateMutexLocker locker(*seq);
202 
203  //See Sequence::Delete() for why need this for now..
204  //We don't need the mBlockFilesMutex here because it is only for the vector list.
205  //These are existing blocks, and its wavetrack or blockfiles won't be deleted because
206  //of the respective mWaveTrackMutex lock and LockDeleteUpdateMutex() call.
207  blocks = clip->GetSequenceBlockArray();
208  int i;
209  int insertCursor;
210 
211  insertCursor =0;//OD TODO:see if this works, removed from inner loop (bfore was n*n)
212 
213  for(i=0; i<(int)blocks->size(); i++)
214  {
215  //if there is data but no summary, this blockfile needs summarizing.
216  SeqBlock &block = (*blocks)[i];
217  const auto &file = block.f;
218  if(file->IsDataAvailable() && !file->IsSummaryAvailable())
219  {
220  const auto odpcmaFile =
221  std::static_pointer_cast<ODPCMAliasBlockFile>(file);
222  odpcmaFile->SetStart(block.start);
223  odpcmaFile->SetClipOffset(sampleCount(
224  clip->GetStartTime()*clip->GetRate()
225  ));
226 
227  //these will always be linear within a sequence-lets take advantage of this by keeping a cursor.
228  {
229  std::shared_ptr< ODPCMAliasBlockFile > ptr;
230  while(insertCursor < (int)tempBlocks.size() &&
231  (!(ptr = tempBlocks[insertCursor].lock()) ||
232  ptr->GetStart() + ptr->GetClipOffset() <
233  odpcmaFile->GetStart() + odpcmaFile->GetClipOffset()))
234  insertCursor++;
235  }
236 
237  tempBlocks.insert(tempBlocks.begin() + insertCursor++, odpcmaFile);
238  }
239  }
240  }
241  }
242  }
243  mWaveTrackMutex.Unlock();
244 
245  //get the NEW order.
246  mBlockFilesMutex.Lock();
247  OrderBlockFiles(tempBlocks);
248  mBlockFilesMutex.Unlock();
249 
250  MarkUpdateRan();
251 }
252 
253 
254 
257  (std::vector< std::weak_ptr< ODPCMAliasBlockFile > > &unorderedBlocks)
258 {
259  mBlockFiles.clear();
260  //Order the blockfiles into our queue in a fancy convenient way. (this could be user-prefs)
261  //for now just put them in linear. We start the order from the first block that includes the ondemand sample
262  //(which the user sets by clicking.)
263  //Note that this code assumes that the array is sorted in time.
264 
265  //find the startpoint
266  auto processStartSample = GetDemandSample();
267  std::shared_ptr< ODPCMAliasBlockFile > firstBlock;
268  for(auto i = unorderedBlocks.size(); i--;)
269  {
270  auto ptr = unorderedBlocks[i].lock();
271  if(ptr)
272  {
273  //test if the blockfiles are near the task cursor. we use the last mBlockFiles[0] as our point of reference
274  //and add ones that are closer.
275  if(firstBlock &&
276  ptr->GetGlobalEnd() >= processStartSample &&
277  ( firstBlock->GetGlobalEnd() < processStartSample ||
278  ptr->GetGlobalStart() <= firstBlock->GetGlobalStart())
279  )
280  {
281  //insert at the front of the list if we get blockfiles that are after the demand sample
282  firstBlock = ptr;
283  mBlockFiles.insert(mBlockFiles.begin(), unorderedBlocks[i]);
284  }
285  else
286  {
287  //otherwise no priority
288  if ( !firstBlock )
289  firstBlock = ptr;
290  mBlockFiles.push_back(unorderedBlocks[i]);
291  }
292  if(mMaxBlockFiles< (int) mBlockFiles.size())
293  mMaxBlockFiles = mBlockFiles.size();
294  }
295  else
296  {
297  // The block file disappeared.
298  // Let it be deleted and forget about it.
299  }
300  }
301 }
nBlockFilesPerDoSome
#define nBlockFilesPerDoSome
Definition: ODComputeSummaryTask.cpp:29
ODComputeSummaryTask::OrderBlockFiles
void OrderBlockFiles(std::vector< std::weak_ptr< ODPCMAliasBlockFile > > &unorderedBlocks)
Orders the input as either On-Demand or default layered order.
Definition: ODComputeSummaryTask.cpp:257
ODComputeSummaryTask::Clone
std::unique_ptr< ODTask > Clone() const override
Definition: ODComputeSummaryTask.cpp:38
Sequence
A WaveTrack contains WaveClip(s). A WaveClip contains a Sequence. A Sequence is primarily an interfac...
Definition: Sequence.h:61
ODTask::mPercentCompleteMutex
ODLock mPercentCompleteMutex
Definition: ODTask.h:152
ODTask::mWaveTracks
std::vector< std::weak_ptr< WaveTrack > > mWaveTracks
Definition: ODTask.h:160
ODTask::mWaveTrackMutex
ODLock mWaveTrackMutex
Definition: ODTask.h:161
ODComputeSummaryTask::mBlockFiles
std::vector< std::weak_ptr< ODPCMAliasBlockFile > > mBlockFiles
Definition: ODComputeSummaryTask.h:77
ODComputeSummaryTask::CalculatePercentComplete
void CalculatePercentComplete() override
recalculates the percentage complete.
Definition: ODComputeSummaryTask.cpp:168
ODComputeSummaryTask::ODComputeSummaryTask
ODComputeSummaryTask()
Constructs an ODTask.
Definition: ODComputeSummaryTask.cpp:32
ODComputeSummaryTask::ComputeNextWorkUntilPercentageComplete
float ComputeNextWorkUntilPercentageComplete() override
Definition: ODComputeSummaryTask.cpp:139
ODComputeSummaryTask::mMaxBlockFiles
int mMaxBlockFiles
Definition: ODComputeSummaryTask.h:78
ODComputeSummaryTask.h
ODComputeSummaryTask::HasUpdateRan
bool HasUpdateRan()
Definition: ODComputeSummaryTask.cpp:159
ODPCMAliasBlockFile::GetGlobalStart
sampleCount GetGlobalStart() const
Definition: ODPCMAliasBlockFile.h:107
SeqBlock
Data structure containing pointer to a sample block and a start time. Element of a BlockArray.
Definition: Sequence.h:28
ODComputeSummaryTask::mHasUpdateRan
bool mHasUpdateRan
Definition: ODComputeSummaryTask.h:80
BlockArray
Definition: Sequence.h:49
sampleCount
Positions or offsets within audio files need a wide type.
Definition: SampleCount.h:18
ODTask::mPercentComplete
volatile float mPercentComplete
Definition: ODTask.h:151
ODTask::GetDemandSample
virtual sampleCount GetDemandSample() const
Definition: ODTask.cpp:221
ODComputeSummaryTask::mBlockFilesMutex
ODLock mBlockFilesMutex
Definition: ODComputeSummaryTask.h:76
ODComputeSummaryTask::Update
void Update() override
Definition: ODComputeSummaryTask.cpp:182
ODPCMAliasBlockFile::GetGlobalEnd
sampleCount GetGlobalEnd() const
Definition: ODPCMAliasBlockFile.h:110
ODComputeSummaryTask::Terminate
void Terminate() override
releases memory that the ODTask owns. Subclasses should override.
Definition: ODComputeSummaryTask.cpp:48
ODPCMAliasBlockFile::GetClipOffset
sampleCount GetClipOffset() const
Gets the number of samples the clip associated with this blockfile is offset by.
Definition: ODPCMAliasBlockFile.h:104
ODComputeSummaryTask::MarkUpdateRan
void MarkUpdateRan()
tells us whether or not Update has been run at least once.
Definition: ODComputeSummaryTask.cpp:152
ODPCMAliasBlockFile::GetStart
sampleCount GetStart() const
Gets the value that indicates where the first sample in this block corresponds to the global sequence...
Definition: ODPCMAliasBlockFile.h:92
SeqBlock::start
sampleCount start
the sample in the global wavetrack that this block starts at.
Definition: Sequence.h:33
ODComputeSummaryTask::DoSomeInternal
void DoSomeInternal() override
Computes and writes the data for one BlockFile if it still has a refcount.
Definition: ODComputeSummaryTask.cpp:58
ODComputeSummaryTask::mHasUpdateRanMutex
ODLock mHasUpdateRanMutex
Definition: ODComputeSummaryTask.h:79