comparison data/model/WaveFileModel.cpp @ 384:6f6ab834449d spectrogram-cache-rejig

* Merge from trunk
author Chris Cannam
date Wed, 27 Feb 2008 11:59:42 +0000
parents 1afaf98dbf11
children
comparison
equal deleted inserted replaced
337:a6fab10ff9e6 384:6f6ab834449d
171 WaveFileModel::getMaker() const 171 WaveFileModel::getMaker() const
172 { 172 {
173 if (m_reader) return m_reader->getMaker(); 173 if (m_reader) return m_reader->getMaker();
174 return ""; 174 return "";
175 } 175 }
176
177 QString
178 WaveFileModel::getLocation() const
179 {
180 if (m_reader) return m_reader->getLocation();
181 return "";
182 }
176 183
177 size_t 184 size_t
178 WaveFileModel::getData(int channel, size_t start, size_t count, 185 WaveFileModel::getData(int channel, size_t start, size_t count,
179 float *buffer) const 186 float *buffer) const
180 { 187 {
181 // Always read these directly from the file. 188 // Always read these directly from the file.
182 // This is used for e.g. audio playback. 189 // This is used for e.g. audio playback.
183 // Could be much more efficient (although compiler optimisation will help) 190 // Could be much more efficient (although compiler optimisation will help)
184 191
185 if (start > m_startFrame) { 192 if (start >= m_startFrame) {
186 start -= m_startFrame; 193 start -= m_startFrame;
187 } else { 194 } else {
188 for (size_t i = 0; i < count; ++i) buffer[i] = 0.f; 195 for (size_t i = 0; i < count; ++i) buffer[i] = 0.f;
189 if (count <= m_startFrame - start) { 196 if (count <= m_startFrame - start) {
190 return 0; 197 return 0;
202 #ifdef DEBUG_WAVE_FILE_MODEL 209 #ifdef DEBUG_WAVE_FILE_MODEL
203 // std::cerr << "WaveFileModel::getValues(" << channel << ", " 210 // std::cerr << "WaveFileModel::getValues(" << channel << ", "
204 // << start << ", " << end << "): calling reader" << std::endl; 211 // << start << ", " << end << "): calling reader" << std::endl;
205 #endif 212 #endif
206 213
207 SampleBlock frames; 214 int channels = getChannelCount();
215
216 SampleBlock frames(count * channels);
208 m_reader->getInterleavedFrames(start, count, frames); 217 m_reader->getInterleavedFrames(start, count, frames);
209 218
210 size_t i = 0; 219 size_t i = 0;
211 220
212 int ch0 = channel, ch1 = channel, channels = getChannelCount(); 221 int ch0 = channel, ch1 = channel;
213 if (channel == -1) { 222 if (channel == -1) {
214 ch0 = 0; 223 ch0 = 0;
215 ch1 = channels - 1; 224 ch1 = channels - 1;
216 } 225 }
217 226
253 if (!m_reader || !m_reader->isOK() || count == 0) { 262 if (!m_reader || !m_reader->isOK() || count == 0) {
254 for (size_t i = 0; i < count; ++i) buffer[i] = 0.0; 263 for (size_t i = 0; i < count; ++i) buffer[i] = 0.0;
255 return 0; 264 return 0;
256 } 265 }
257 266
258 SampleBlock frames; 267 int channels = getChannelCount();
268
269 SampleBlock frames(count * channels);
259 m_reader->getInterleavedFrames(start, count, frames); 270 m_reader->getInterleavedFrames(start, count, frames);
260 271
261 size_t i = 0; 272 size_t i = 0;
262 273
263 int ch0 = channel, ch1 = channel, channels = getChannelCount(); 274 int ch0 = channel, ch1 = channel;
264 if (channel == -1) { 275 if (channel == -1) {
265 ch0 = 0; 276 ch0 = 0;
266 ch1 = channels - 1; 277 ch1 = channels - 1;
267 } 278 }
268 279
283 } 294 }
284 295
285 return i; 296 return i;
286 } 297 }
287 298
299 size_t
300 WaveFileModel::getData(size_t fromchannel, size_t tochannel,
301 size_t start, size_t count,
302 float **buffer) const
303 {
304 size_t channels = getChannelCount();
305
306 if (fromchannel > tochannel) {
307 std::cerr << "ERROR: WaveFileModel::getData: fromchannel ("
308 << fromchannel << ") > tochannel (" << tochannel << ")"
309 << std::endl;
310 return 0;
311 }
312
313 if (tochannel >= channels) {
314 std::cerr << "ERROR: WaveFileModel::getData: tochannel ("
315 << tochannel << ") >= channel count (" << channels << ")"
316 << std::endl;
317 return 0;
318 }
319
320 if (fromchannel == tochannel) {
321 return getData(fromchannel, start, count, buffer[0]);
322 }
323
324 size_t reqchannels = (tochannel - fromchannel) + 1;
325
326 // Always read these directly from the file.
327 // This is used for e.g. audio playback.
328 // Could be much more efficient (although compiler optimisation will help)
329
330 if (start >= m_startFrame) {
331 start -= m_startFrame;
332 } else {
333 for (size_t c = 0; c < reqchannels; ++c) {
334 for (size_t i = 0; i < count; ++i) buffer[c][i] = 0.f;
335 }
336 if (count <= m_startFrame - start) {
337 return 0;
338 } else {
339 count -= (m_startFrame - start);
340 start = 0;
341 }
342 }
343
344 if (!m_reader || !m_reader->isOK() || count == 0) {
345 for (size_t c = 0; c < reqchannels; ++c) {
346 for (size_t i = 0; i < count; ++i) buffer[c][i] = 0.f;
347 }
348 return 0;
349 }
350
351 SampleBlock frames(count * channels);
352 m_reader->getInterleavedFrames(start, count, frames);
353
354 size_t i = 0;
355
356 int ch0 = fromchannel, ch1 = tochannel;
357
358 size_t index = 0, available = frames.size();
359
360 while (i < count) {
361
362 if (index >= available) break;
363
364 size_t destc = 0;
365
366 for (size_t c = 0; c < channels; ++c) {
367
368 if (c >= fromchannel && c <= tochannel) {
369 buffer[destc][i] = frames[index];
370 ++destc;
371 }
372
373 ++index;
374 }
375
376 ++i;
377 }
378
379 return i;
380 }
381
382 size_t
383 WaveFileModel::getSummaryBlockSize(size_t desired) const
384 {
385 int cacheType = 0;
386 int power = m_zoomConstraint.getMinCachePower();
387 size_t roundedBlockSize = m_zoomConstraint.getNearestBlockSize
388 (desired, cacheType, power, ZoomConstraint::RoundDown);
389 if (cacheType != 0 && cacheType != 1) {
390 // We will be reading directly from file, so can satisfy any
391 // blocksize requirement
392 return desired;
393 } else {
394 return roundedBlockSize;
395 }
396 }
397
288 void 398 void
289 WaveFileModel::getSummaries(size_t channel, size_t start, size_t count, 399 WaveFileModel::getSummaries(size_t channel, size_t start, size_t count,
290 RangeBlock &ranges, size_t &blockSize) const 400 RangeBlock &ranges, size_t &blockSize) const
291 { 401 {
292 ranges.clear(); 402 ranges.clear();
293 if (!isOK()) return; 403 if (!isOK()) return;
404 ranges.reserve((count / blockSize) + 1);
294 405
295 if (start > m_startFrame) start -= m_startFrame; 406 if (start > m_startFrame) start -= m_startFrame;
296 else if (count <= m_startFrame - start) return; 407 else if (count <= m_startFrame - start) return;
297 else { 408 else {
298 count -= (m_startFrame - start); 409 count -= (m_startFrame - start);
299 start = 0; 410 start = 0;
300 } 411 }
301 412
302 int cacheType = 0; 413 int cacheType = 0;
303 int power = m_zoomConstraint.getMinCachePower(); 414 int power = m_zoomConstraint.getMinCachePower();
304 blockSize = m_zoomConstraint.getNearestBlockSize 415 size_t roundedBlockSize = m_zoomConstraint.getNearestBlockSize
305 (blockSize, cacheType, power, ZoomConstraint::RoundUp); 416 (blockSize, cacheType, power, ZoomConstraint::RoundDown);
306 417
307 size_t channels = getChannelCount(); 418 size_t channels = getChannelCount();
308 419
309 if (cacheType != 0 && cacheType != 1) { 420 if (cacheType != 0 && cacheType != 1) {
310 421
314 // for stereo files, in two separate calls to this method. 425 // for stereo files, in two separate calls to this method.
315 // We could fairly trivially handle this for most cases that 426 // We could fairly trivially handle this for most cases that
316 // matter by putting a single cache in getInterleavedFrames 427 // matter by putting a single cache in getInterleavedFrames
317 // for short queries. 428 // for short queries.
318 429
319 SampleBlock frames; 430 m_directReadMutex.lock();
320 m_reader->getInterleavedFrames(start, count, frames); 431
432 if (m_lastDirectReadStart != start ||
433 m_lastDirectReadCount != count ||
434 m_directRead.empty()) {
435
436 m_reader->getInterleavedFrames(start, count, m_directRead);
437 m_lastDirectReadStart = start;
438 m_lastDirectReadCount = count;
439 }
440
321 float max = 0.0, min = 0.0, total = 0.0; 441 float max = 0.0, min = 0.0, total = 0.0;
322 size_t i = 0, got = 0; 442 size_t i = 0, got = 0;
323 443
324 while (i < count) { 444 while (i < count) {
325 445
326 size_t index = i * channels + channel; 446 size_t index = i * channels + channel;
327 if (index >= frames.size()) break; 447 if (index >= m_directRead.size()) break;
328 448
329 float sample = frames[index]; 449 float sample = m_directRead[index];
330 if (sample > max || got == 0) max = sample; 450 if (sample > max || got == 0) max = sample;
331 if (sample < min || got == 0) min = sample; 451 if (sample < min || got == 0) min = sample;
332 total += fabsf(sample); 452 total += fabsf(sample);
333 453
334 ++i; 454 ++i;
339 min = max = total = 0.0f; 459 min = max = total = 0.0f;
340 got = 0; 460 got = 0;
341 } 461 }
342 } 462 }
343 463
464 m_directReadMutex.unlock();
465
344 if (got > 0) { 466 if (got > 0) {
345 ranges.push_back(Range(min, max, total / got)); 467 ranges.push_back(Range(min, max, total / got));
346 } 468 }
347 469
348 return; 470 return;
350 } else { 472 } else {
351 473
352 QMutexLocker locker(&m_mutex); 474 QMutexLocker locker(&m_mutex);
353 475
354 const RangeBlock &cache = m_cache[cacheType]; 476 const RangeBlock &cache = m_cache[cacheType];
477
478 blockSize = roundedBlockSize;
355 479
356 size_t cacheBlock, div; 480 size_t cacheBlock, div;
357 481
358 if (cacheType == 0) { 482 if (cacheType == 0) {
359 cacheBlock = (1 << m_zoomConstraint.getMinCachePower()); 483 cacheBlock = (1 << m_zoomConstraint.getMinCachePower());