WaveFileModel.cpp

Go to the documentation of this file.
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
00002 
00003 /*
00004     Sonic Visualiser
00005     An audio file viewer and annotation editor.
00006     Centre for Digital Music, Queen Mary, University of London.
00007     This file copyright 2006 Chris Cannam and QMUL.
00008     
00009     This program is free software; you can redistribute it and/or
00010     modify it under the terms of the GNU General Public License as
00011     published by the Free Software Foundation; either version 2 of the
00012     License, or (at your option) any later version.  See the file
00013     COPYING included with this distribution for more information.
00014 */
00015 
00016 #include "WaveFileModel.h"
00017 
00018 #include "fileio/AudioFileReader.h"
00019 #include "fileio/AudioFileReaderFactory.h"
00020 
00021 #include "system/System.h"
00022 
00023 #include <QMessageBox>
00024 #include <QFileInfo>
00025 #include <QTextStream>
00026 
00027 #include <iostream>
00028 #include <unistd.h>
00029 #include <math.h>
00030 #include <sndfile.h>
00031 
00032 #include <cassert>
00033 
00034 //#define DEBUG_WAVE_FILE_MODEL 1
00035 
00036 using std::cerr;
00037 using std::endl;
00038 
00039 PowerOfSqrtTwoZoomConstraint
00040 WaveFileModel::m_zoomConstraint;
00041 
00042 WaveFileModel::WaveFileModel(FileSource source, size_t targetRate) :
00043     m_source(source),
00044     m_path(source.getLocation()),
00045     m_myReader(true),
00046     m_startFrame(0),
00047     m_fillThread(0),
00048     m_updateTimer(0),
00049     m_lastFillExtent(0),
00050     m_exiting(false)
00051 {
00052     m_source.waitForData();
00053     if (m_source.isOK()) {
00054         m_reader = AudioFileReaderFactory::createThreadingReader
00055             (m_source, targetRate);
00056         if (m_reader) {
00057             std::cerr << "WaveFileModel::WaveFileModel: reader rate: "
00058                       << m_reader->getSampleRate() << std::endl;
00059         }
00060     }
00061     if (m_reader) setObjectName(m_reader->getTitle());
00062     if (objectName() == "") setObjectName(QFileInfo(m_path).fileName());
00063     if (isOK()) fillCache();
00064 }
00065 
00066 WaveFileModel::WaveFileModel(FileSource source, AudioFileReader *reader) :
00067     m_source(source),
00068     m_path(source.getLocation()),
00069     m_myReader(false),
00070     m_startFrame(0),
00071     m_fillThread(0),
00072     m_updateTimer(0),
00073     m_lastFillExtent(0),
00074     m_exiting(false)
00075 {
00076     m_reader = reader;
00077     if (m_reader) setObjectName(m_reader->getTitle());
00078     if (objectName() == "") setObjectName(QFileInfo(m_path).fileName());
00079     fillCache();
00080 }
00081 
00082 WaveFileModel::~WaveFileModel()
00083 {
00084     m_exiting = true;
00085     if (m_fillThread) m_fillThread->wait();
00086     if (m_myReader) delete m_reader;
00087     m_reader = 0;
00088 }
00089 
00090 bool
00091 WaveFileModel::isOK() const
00092 {
00093     return m_reader && m_reader->isOK();
00094 }
00095 
00096 bool
00097 WaveFileModel::isReady(int *completion) const
00098 {
00099     bool ready = (isOK() && (m_fillThread == 0));
00100     double c = double(m_lastFillExtent) / double(getEndFrame() - getStartFrame());
00101     static int prevCompletion = 0;
00102     if (completion) {
00103         *completion = int(c * 100.0 + 0.01);
00104         if (m_reader) {
00105             int decodeCompletion = m_reader->getDecodeCompletion();
00106             if (decodeCompletion < 90) *completion = decodeCompletion;
00107             else *completion = std::min(*completion, decodeCompletion);
00108         }
00109         if (*completion != 0 &&
00110             *completion != 100 &&
00111             prevCompletion != 0 &&
00112             prevCompletion > *completion) {
00113             // just to avoid completion going backwards
00114             *completion = prevCompletion;
00115         }
00116         prevCompletion = *completion;
00117     }
00118 #ifdef DEBUG_WAVE_FILE_MODEL
00119     std::cerr << "WaveFileModel::isReady(): ready = " << ready << ", completion = " << (completion ? *completion : -1) << std::endl;
00120 #endif
00121     return ready;
00122 }
00123 
00124 Model *
00125 WaveFileModel::clone() const
00126 {
00127     WaveFileModel *model = new WaveFileModel(m_source);
00128     return model;
00129 }
00130 
00131 size_t
00132 WaveFileModel::getFrameCount() const
00133 {
00134     if (!m_reader) return 0;
00135     return m_reader->getFrameCount();
00136 }
00137 
00138 size_t
00139 WaveFileModel::getChannelCount() const
00140 {
00141     if (!m_reader) return 0;
00142     return m_reader->getChannelCount();
00143 }
00144 
00145 size_t
00146 WaveFileModel::getSampleRate() const 
00147 {
00148     if (!m_reader) return 0;
00149     return m_reader->getSampleRate();
00150 }
00151 
00152 size_t
00153 WaveFileModel::getNativeRate() const 
00154 {
00155     if (!m_reader) return 0;
00156     size_t rate = m_reader->getNativeRate();
00157     if (rate == 0) rate = getSampleRate();
00158     return rate;
00159 }
00160 
00161 QString
00162 WaveFileModel::getTitle() const
00163 {
00164     QString title;
00165     if (m_reader) title = m_reader->getTitle();
00166     if (title == "") title = objectName();
00167     return title;
00168 }
00169 
00170 QString
00171 WaveFileModel::getMaker() const
00172 {
00173     if (m_reader) return m_reader->getMaker();
00174     return "";
00175 }
00176 
00177 QString
00178 WaveFileModel::getLocation() const
00179 {
00180     if (m_reader) return m_reader->getLocation();
00181     return "";
00182 }
00183     
00184 size_t
00185 WaveFileModel::getData(int channel, size_t start, size_t count,
00186                        float *buffer) const
00187 {
00188     // Always read these directly from the file. 
00189     // This is used for e.g. audio playback.
00190     // Could be much more efficient (although compiler optimisation will help)
00191 
00192     if (start >= m_startFrame) {
00193         start -= m_startFrame;
00194     } else {
00195         for (size_t i = 0; i < count; ++i) buffer[i] = 0.f;
00196         if (count <= m_startFrame - start) {
00197             return 0;
00198         } else {
00199             count -= (m_startFrame - start);
00200             start = 0;
00201         }
00202     }
00203 
00204     if (!m_reader || !m_reader->isOK() || count == 0) {
00205         for (size_t i = 0; i < count; ++i) buffer[i] = 0.f;
00206         return 0;
00207     }
00208 
00209 #ifdef DEBUG_WAVE_FILE_MODEL
00210 //    std::cerr << "WaveFileModel::getValues(" << channel << ", "
00211 //              << start << ", " << end << "): calling reader" << std::endl;
00212 #endif
00213 
00214     int channels = getChannelCount();
00215 
00216     SampleBlock frames(count * channels);
00217     m_reader->getInterleavedFrames(start, count, frames);
00218 
00219     size_t i = 0;
00220 
00221     int ch0 = channel, ch1 = channel;
00222     if (channel == -1) {
00223         ch0 = 0;
00224         ch1 = channels - 1;
00225     }
00226     
00227     while (i < count) {
00228 
00229         buffer[i] = 0.0;
00230 
00231         for (int ch = ch0; ch <= ch1; ++ch) {
00232 
00233             size_t index = i * channels + ch;
00234             if (index >= frames.size()) break;
00235             
00236             float sample = frames[index];
00237             buffer[i] += sample;
00238         }
00239 
00240         ++i;
00241     }
00242 
00243     return i;
00244 }
00245 
00246 size_t
00247 WaveFileModel::getData(int channel, size_t start, size_t count,
00248                        double *buffer) const
00249 {
00250     if (start > m_startFrame) {
00251         start -= m_startFrame;
00252     } else {
00253         for (size_t i = 0; i < count; ++i) buffer[i] = 0.0;
00254         if (count <= m_startFrame - start) {
00255             return 0;
00256         } else {
00257             count -= (m_startFrame - start);
00258             start = 0;
00259         }
00260     }
00261 
00262     if (!m_reader || !m_reader->isOK() || count == 0) {
00263         for (size_t i = 0; i < count; ++i) buffer[i] = 0.0;
00264         return 0;
00265     }
00266 
00267     int channels = getChannelCount();
00268 
00269     SampleBlock frames(count * channels);
00270     m_reader->getInterleavedFrames(start, count, frames);
00271 
00272     size_t i = 0;
00273 
00274     int ch0 = channel, ch1 = channel;
00275     if (channel == -1) {
00276         ch0 = 0;
00277         ch1 = channels - 1;
00278     }
00279 
00280     while (i < count) {
00281 
00282         buffer[i] = 0.0;
00283 
00284         for (int ch = ch0; ch <= ch1; ++ch) {
00285 
00286             size_t index = i * channels + ch;
00287             if (index >= frames.size()) break;
00288             
00289             float sample = frames[index];
00290             buffer[i] += sample;
00291         }
00292 
00293         ++i;
00294     }
00295 
00296     return i;
00297 }
00298 
00299 size_t
00300 WaveFileModel::getData(size_t fromchannel, size_t tochannel,
00301                        size_t start, size_t count,
00302                        float **buffer) const
00303 {
00304     size_t channels = getChannelCount();
00305 
00306     if (fromchannel > tochannel) {
00307         std::cerr << "ERROR: WaveFileModel::getData: fromchannel ("
00308                   << fromchannel << ") > tochannel (" << tochannel << ")"
00309                   << std::endl;
00310         return 0;
00311     }
00312 
00313     if (tochannel >= channels) {
00314         std::cerr << "ERROR: WaveFileModel::getData: tochannel ("
00315                   << tochannel << ") >= channel count (" << channels << ")"
00316                   << std::endl;
00317         return 0;
00318     }
00319 
00320     if (fromchannel == tochannel) {
00321         return getData(fromchannel, start, count, buffer[0]);
00322     }
00323 
00324     size_t reqchannels = (tochannel - fromchannel) + 1;
00325 
00326     // Always read these directly from the file. 
00327     // This is used for e.g. audio playback.
00328     // Could be much more efficient (although compiler optimisation will help)
00329 
00330     if (start >= m_startFrame) {
00331         start -= m_startFrame;
00332     } else {
00333         for (size_t c = 0; c < reqchannels; ++c) {
00334             for (size_t i = 0; i < count; ++i) buffer[c][i] = 0.f;
00335         }
00336         if (count <= m_startFrame - start) {
00337             return 0;
00338         } else {
00339             count -= (m_startFrame - start);
00340             start = 0;
00341         }
00342     }
00343 
00344     if (!m_reader || !m_reader->isOK() || count == 0) {
00345         for (size_t c = 0; c < reqchannels; ++c) {
00346             for (size_t i = 0; i < count; ++i) buffer[c][i] = 0.f;
00347         }
00348         return 0;
00349     }
00350 
00351     SampleBlock frames(count * channels);
00352     m_reader->getInterleavedFrames(start, count, frames);
00353 
00354     size_t i = 0;
00355 
00356     int ch0 = fromchannel, ch1 = tochannel;
00357     
00358     size_t index = 0, available = frames.size();
00359 
00360     while (i < count) {
00361 
00362         if (index >= available) break;
00363 
00364         size_t destc = 0;
00365 
00366         for (size_t c = 0; c < channels; ++c) {
00367             
00368             if (c >= fromchannel && c <= tochannel) {
00369                 buffer[destc][i] = frames[index];
00370                 ++destc;
00371             }
00372 
00373             ++index;
00374         }
00375 
00376         ++i;
00377     }
00378 
00379     return i;
00380 }
00381 
00382 size_t
00383 WaveFileModel::getSummaryBlockSize(size_t desired) const
00384 {
00385     int cacheType = 0;
00386     int power = m_zoomConstraint.getMinCachePower();
00387     size_t roundedBlockSize = m_zoomConstraint.getNearestBlockSize
00388         (desired, cacheType, power, ZoomConstraint::RoundDown);
00389     if (cacheType != 0 && cacheType != 1) {
00390         // We will be reading directly from file, so can satisfy any
00391         // blocksize requirement
00392         return desired;
00393     } else {
00394         return roundedBlockSize;
00395     }
00396 }    
00397 
00398 void
00399 WaveFileModel::getSummaries(size_t channel, size_t start, size_t count,
00400                             RangeBlock &ranges, size_t &blockSize) const
00401 {
00402     ranges.clear();
00403     if (!isOK()) return;
00404     ranges.reserve((count / blockSize) + 1);
00405 
00406     if (start > m_startFrame) start -= m_startFrame;
00407     else if (count <= m_startFrame - start) return;
00408     else {
00409         count -= (m_startFrame - start);
00410         start = 0;
00411     }
00412 
00413     int cacheType = 0;
00414     int power = m_zoomConstraint.getMinCachePower();
00415     size_t roundedBlockSize = m_zoomConstraint.getNearestBlockSize
00416         (blockSize, cacheType, power, ZoomConstraint::RoundDown);
00417 
00418     size_t channels = getChannelCount();
00419 
00420     if (cacheType != 0 && cacheType != 1) {
00421 
00422         // We need to read directly from the file.  We haven't got
00423         // this cached.  Hope the requested area is small.  This is
00424         // not optimal -- we'll end up reading the same frames twice
00425         // for stereo files, in two separate calls to this method.
00426         // We could fairly trivially handle this for most cases that
00427         // matter by putting a single cache in getInterleavedFrames
00428         // for short queries.
00429 
00430         m_directReadMutex.lock();
00431 
00432         if (m_lastDirectReadStart != start ||
00433             m_lastDirectReadCount != count ||
00434             m_directRead.empty()) {
00435 
00436             m_reader->getInterleavedFrames(start, count, m_directRead);
00437             m_lastDirectReadStart = start;
00438             m_lastDirectReadCount = count;
00439         }
00440 
00441         float max = 0.0, min = 0.0, total = 0.0;
00442         size_t i = 0, got = 0;
00443 
00444         while (i < count) {
00445 
00446             size_t index = i * channels + channel;
00447             if (index >= m_directRead.size()) break;
00448             
00449             float sample = m_directRead[index];
00450             if (sample > max || got == 0) max = sample;
00451             if (sample < min || got == 0) min = sample;
00452             total += fabsf(sample);
00453             
00454             ++i;
00455             ++got;
00456             
00457             if (got == blockSize) {
00458                 ranges.push_back(Range(min, max, total / got));
00459                 min = max = total = 0.0f;
00460                 got = 0;
00461             }
00462         }
00463 
00464         m_directReadMutex.unlock();
00465 
00466         if (got > 0) {
00467             ranges.push_back(Range(min, max, total / got));
00468         }
00469 
00470         return;
00471 
00472     } else {
00473 
00474         QMutexLocker locker(&m_mutex);
00475     
00476         const RangeBlock &cache = m_cache[cacheType];
00477 
00478         blockSize = roundedBlockSize;
00479 
00480         size_t cacheBlock, div;
00481         
00482         if (cacheType == 0) {
00483             cacheBlock = (1 << m_zoomConstraint.getMinCachePower());
00484             div = (1 << power) / cacheBlock;
00485         } else {
00486             cacheBlock = ((unsigned int)((1 << m_zoomConstraint.getMinCachePower()) * sqrt(2) + 0.01));
00487             div = ((unsigned int)((1 << power) * sqrt(2) + 0.01)) / cacheBlock;
00488         }
00489 
00490         size_t startIndex = start / cacheBlock;
00491         size_t endIndex = (start + count) / cacheBlock;
00492 
00493         float max = 0.0, min = 0.0, total = 0.0;
00494         size_t i = 0, got = 0;
00495 
00496 #ifdef DEBUG_WAVE_FILE_MODEL
00497         cerr << "blockSize is " << blockSize << ", cacheBlock " << cacheBlock << ", start " << start << ", count " << count << " (frame count " << getFrameCount() << "), power is " << power << ", div is " << div << ", startIndex " << startIndex << ", endIndex " << endIndex << endl;
00498 #endif
00499 
00500         for (i = 0; i <= endIndex - startIndex; ) {
00501         
00502             size_t index = (i + startIndex) * channels + channel;
00503             if (index >= cache.size()) break;
00504             
00505             const Range &range = cache[index];
00506             if (range.max > max || got == 0) max = range.max;
00507             if (range.min < min || got == 0) min = range.min;
00508             total += range.absmean;
00509             
00510             ++i;
00511             ++got;
00512             
00513             if (got == div) {
00514                 ranges.push_back(Range(min, max, total / got));
00515                 min = max = total = 0.0f;
00516                 got = 0;
00517             }
00518         }
00519                 
00520         if (got > 0) {
00521             ranges.push_back(Range(min, max, total / got));
00522         }
00523     }
00524 
00525 #ifdef DEBUG_WAVE_FILE_MODEL
00526     cerr << "returning " << ranges.size() << " ranges" << endl;
00527 #endif
00528     return;
00529 }
00530 
00531 WaveFileModel::Range
00532 WaveFileModel::getSummary(size_t channel, size_t start, size_t count) const
00533 {
00534     Range range;
00535     if (!isOK()) return range;
00536 
00537     if (start > m_startFrame) start -= m_startFrame;
00538     else if (count <= m_startFrame - start) return range;
00539     else {
00540         count -= (m_startFrame - start);
00541         start = 0;
00542     }
00543 
00544     size_t blockSize;
00545     for (blockSize = 1; blockSize <= count; blockSize *= 2);
00546     if (blockSize > 1) blockSize /= 2;
00547 
00548     bool first = false;
00549 
00550     size_t blockStart = (start / blockSize) * blockSize;
00551     size_t blockEnd = ((start + count) / blockSize) * blockSize;
00552 
00553     if (blockStart < start) blockStart += blockSize;
00554         
00555     if (blockEnd > blockStart) {
00556         RangeBlock ranges;
00557         getSummaries(channel, blockStart, blockEnd - blockStart, ranges, blockSize);
00558         for (size_t i = 0; i < ranges.size(); ++i) {
00559             if (first || ranges[i].min < range.min) range.min = ranges[i].min;
00560             if (first || ranges[i].max > range.max) range.max = ranges[i].max;
00561             if (first || ranges[i].absmean < range.absmean) range.absmean = ranges[i].absmean;
00562             first = false;
00563         }
00564     }
00565 
00566     if (blockStart > start) {
00567         Range startRange = getSummary(channel, start, blockStart - start);
00568         range.min = std::min(range.min, startRange.min);
00569         range.max = std::max(range.max, startRange.max);
00570         range.absmean = std::min(range.absmean, startRange.absmean);
00571     }
00572 
00573     if (blockEnd < start + count) {
00574         Range endRange = getSummary(channel, blockEnd, start + count - blockEnd);
00575         range.min = std::min(range.min, endRange.min);
00576         range.max = std::max(range.max, endRange.max);
00577         range.absmean = std::min(range.absmean, endRange.absmean);
00578     }
00579 
00580     return range;
00581 }
00582 
00583 void
00584 WaveFileModel::fillCache()
00585 {
00586     m_mutex.lock();
00587 
00588     m_updateTimer = new QTimer(this);
00589     connect(m_updateTimer, SIGNAL(timeout()), this, SLOT(fillTimerTimedOut()));
00590     m_updateTimer->start(100);
00591 
00592     m_fillThread = new RangeCacheFillThread(*this);
00593     connect(m_fillThread, SIGNAL(finished()), this, SLOT(cacheFilled()));
00594 
00595     m_mutex.unlock();
00596     m_fillThread->start();
00597 
00598 #ifdef DEBUG_WAVE_FILE_MODEL
00599     std::cerr << "WaveFileModel::fillCache: started fill thread" << std::endl;
00600 #endif
00601 }   
00602 
00603 void
00604 WaveFileModel::fillTimerTimedOut()
00605 {
00606     if (m_fillThread) {
00607         size_t fillExtent = m_fillThread->getFillExtent();
00608 #ifdef DEBUG_WAVE_FILE_MODEL
00609         cerr << "WaveFileModel::fillTimerTimedOut: extent = " << fillExtent << endl;
00610 #endif
00611         if (fillExtent > m_lastFillExtent) {
00612             emit modelChanged(m_lastFillExtent, fillExtent);
00613             m_lastFillExtent = fillExtent;
00614         }
00615     } else {
00616 #ifdef DEBUG_WAVE_FILE_MODEL
00617         cerr << "WaveFileModel::fillTimerTimedOut: no thread" << std::endl;
00618 #endif
00619         emit modelChanged();
00620     }
00621 }
00622 
00623 void
00624 WaveFileModel::cacheFilled()
00625 {
00626     m_mutex.lock();
00627     delete m_fillThread;
00628     m_fillThread = 0;
00629     delete m_updateTimer;
00630     m_updateTimer = 0;
00631     m_mutex.unlock();
00632     if (getEndFrame() > m_lastFillExtent) {
00633         emit modelChanged(m_lastFillExtent, getEndFrame());
00634     }
00635     emit modelChanged();
00636 #ifdef DEBUG_WAVE_FILE_MODEL
00637     cerr << "WaveFileModel::cacheFilled" << endl;
00638 #endif
00639 }
00640 
00641 void
00642 WaveFileModel::RangeCacheFillThread::run()
00643 {
00644     size_t cacheBlockSize[2];
00645     cacheBlockSize[0] = (1 << m_model.m_zoomConstraint.getMinCachePower());
00646     cacheBlockSize[1] = ((unsigned int)((1 << m_model.m_zoomConstraint.getMinCachePower()) *
00647                                         sqrt(2) + 0.01));
00648     
00649     size_t frame = 0;
00650     size_t readBlockSize = 16384;
00651     SampleBlock block;
00652 
00653     if (!m_model.isOK()) return;
00654     
00655     size_t channels = m_model.getChannelCount();
00656     bool updating = m_model.m_reader->isUpdating();
00657 
00658     if (updating) {
00659         while (channels == 0 && !m_model.m_exiting) {
00660 //            std::cerr << "WaveFileModel::fill: Waiting for channels..." << std::endl;
00661             sleep(1);
00662             channels = m_model.getChannelCount();
00663         }
00664     }
00665 
00666     Range *range = new Range[2 * channels];
00667     size_t count[2];
00668     count[0] = count[1] = 0;
00669 
00670     bool first = true;
00671 
00672     while (first || updating) {
00673 
00674         updating = m_model.m_reader->isUpdating();
00675         m_frameCount = m_model.getFrameCount();
00676 
00677 //        std::cerr << "WaveFileModel::fill: frame = " << frame << ", count = " << m_frameCount << std::endl;
00678 
00679         while (frame < m_frameCount) {
00680 
00681 //            std::cerr << "WaveFileModel::fill inner loop: frame = " << frame << ", count = " << m_frameCount << ", blocksize " << readBlockSize << std::endl;
00682 
00683             if (updating && (frame + readBlockSize > m_frameCount)) break;
00684 
00685             m_model.m_reader->getInterleavedFrames(frame, readBlockSize, block);
00686 
00687 //            std::cerr << "block is " << block.size() << std::endl;
00688 
00689             for (size_t i = 0; i < readBlockSize; ++i) {
00690                 
00691                 if (channels * i + channels > block.size()) break;
00692 
00693                 for (size_t ch = 0; ch < size_t(channels); ++ch) {
00694 
00695                     size_t index = channels * i + ch;
00696                     float sample = block[index];
00697                     
00698                     for (size_t ct = 0; ct < 2; ++ct) { // cache type
00699                         
00700                         size_t rangeIndex = ch * 2 + ct;
00701                         
00702                         if (sample > range[rangeIndex].max || count[ct] == 0) {
00703                             range[rangeIndex].max = sample;
00704                         }
00705                         if (sample < range[rangeIndex].min || count[ct] == 0) {
00706                             range[rangeIndex].min = sample;
00707                         }
00708                         range[rangeIndex].absmean += fabsf(sample);
00709                     }
00710                 }
00711                 
00712                 QMutexLocker locker(&m_model.m_mutex);
00713 
00714                 for (size_t ct = 0; ct < 2; ++ct) {
00715 
00716                     if (++count[ct] == cacheBlockSize[ct]) {
00717 
00718                         for (size_t ch = 0; ch < size_t(channels); ++ch) {
00719                             size_t rangeIndex = ch * 2 + ct;
00720                             range[rangeIndex].absmean /= count[ct];
00721                             m_model.m_cache[ct].push_back(range[rangeIndex]);
00722                             range[rangeIndex] = Range();
00723                         }
00724 
00725                         count[ct] = 0;
00726                     }
00727                 }
00728                 
00729                 ++frame;
00730             }
00731             
00732             if (m_model.m_exiting) break;
00733             
00734             m_fillExtent = frame;
00735         }
00736 
00737 //        std::cerr << "WaveFileModel: inner loop ended" << std::endl;
00738 
00739         first = false;
00740         if (m_model.m_exiting) break;
00741         if (updating) {
00742 //            std::cerr << "sleeping..." << std::endl;
00743             sleep(1);
00744         }
00745     }
00746 
00747     if (!m_model.m_exiting) {
00748 
00749         QMutexLocker locker(&m_model.m_mutex);
00750 
00751         for (size_t ct = 0; ct < 2; ++ct) {
00752 
00753             if (count[ct] > 0) {
00754 
00755                 for (size_t ch = 0; ch < size_t(channels); ++ch) {
00756                     size_t rangeIndex = ch * 2 + ct;
00757                     range[rangeIndex].absmean /= count[ct];
00758                     m_model.m_cache[ct].push_back(range[rangeIndex]);
00759                     range[rangeIndex] = Range();
00760                 }
00761 
00762                 count[ct] = 0;
00763             }
00764             
00765             const Range &rr = *m_model.m_cache[ct].begin();
00766             MUNLOCK(&rr, m_model.m_cache[ct].capacity() * sizeof(Range));
00767         }
00768     }
00769     
00770     delete[] range;
00771 
00772     m_fillExtent = m_frameCount;
00773 
00774 #ifdef DEBUG_WAVE_FILE_MODEL        
00775     for (size_t ct = 0; ct < 2; ++ct) {
00776         cerr << "Cache type " << ct << " now contains " << m_model.m_cache[ct].size() << " ranges" << endl;
00777     }
00778 #endif
00779 }
00780 
00781 void
00782 WaveFileModel::toXml(QTextStream &out,
00783                      QString indent,
00784                      QString extraAttributes) const
00785 {
00786     Model::toXml(out, indent,
00787                  QString("type=\"wavefile\" file=\"%1\" %2")
00788                  .arg(encodeEntities(m_path)).arg(extraAttributes));
00789 }
00790 
00791     

Generated on Wed Feb 20 15:45:30 2008 for SonicVisualiser by  doxygen 1.5.1