SampleManager.cc
上传用户:weiliju62
上传日期:2007-01-06
资源大小:619k
文件大小:12k
源码类别:

SCSI/ASPI

开发平台:

MultiPlatform

  1. /*  cdrdao - write audio CD-Rs in disc-at-once mode
  2.  *
  3.  *  Copyright (C) 1998  Andreas Mueller <mueller@daneb.ping.de>
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2 of the License, or
  8.  *  (at your option) any later version.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with this program; if not, write to the Free Software
  17.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  */
  19. /*
  20.  * $Log: SampleManager.cc,v $
  21.  * Revision 1.6  1999/08/07 16:27:28  mueller
  22.  * Applied patch from Yves Bastide:
  23.  * * prefixing member function names with their class name in connect_to_method
  24.  * * explicitly `const_cast'ing a cast to const
  25.  *
  26.  * Revision 1.5  1999/05/24 18:10:25  mueller
  27.  * Adapted to new reading interface of 'trackdb'.
  28.  *
  29.  * Revision 1.4  1999/03/06 13:55:18  mueller
  30.  * Adapted to Gtk-- version 0.99.1
  31.  *
  32.  * Revision 1.3  1999/01/30 19:45:43  mueller
  33.  * Fixes for compilation with Gtk-- 0.11.1.
  34.  *
  35.  * Revision 1.1  1998/11/20 18:56:06  mueller
  36.  * Initial revision
  37.  *
  38.  */
  39. #include <stdio.h>
  40. #include <limits.h>
  41. #include <math.h>
  42. #include <assert.h>
  43. #include <gtk--.h>
  44. #include <gtk/gtk.h>
  45. #include "SampleManager.h"
  46. #include "TocEdit.h"
  47. #include "guiUpdate.h"
  48. #include "Toc.h"
  49. #include "util.h"
  50. #include "TrackDataScrap.h"
  51. class SampleManagerImpl : public Gtk_Signal_Base {
  52. public:
  53.   SampleManagerImpl(unsigned long);
  54.   ~SampleManagerImpl();
  55.   unsigned long blocking_;
  56.   TocEdit *tocEdit_;
  57.   TocReader tocReader_;
  58.   short *leftNegSamples_;
  59.   short *leftPosSamples_;
  60.   short *rightNegSamples_;
  61.   short *rightPosSamples_;
  62.   long samplesSize_;
  63.   long blocks_;
  64.   unsigned long slength_;
  65.   long chunk_;
  66.   Sample *block_;
  67.   long actBlock_;
  68.   long endBlock_;
  69.   long burstBlock_;
  70.   unsigned long length_;
  71.   gfloat percent_;
  72.   gfloat percentStep_;
  73.   int withGui_;
  74.   int aborted_;
  75.   Gtk_Window *progressWindow_;
  76.   Gtk_ProgressBar *progressBar_;
  77.   
  78.   void getPeak(unsigned long start, unsigned long end,
  79.        short *leftNeg, short *leftPos,
  80.        short *rightNeg, short *rightPos);
  81.   int scanToc(unsigned long start, unsigned long end);
  82.   int readSamples();
  83.   void abortAction();
  84.   void reallocSamples(unsigned long maxSample);
  85.   void removeSamples(unsigned long start, unsigned long end, TrackDataScrap *);
  86.   void insertSamples(unsigned long pos, unsigned long len,
  87.      const TrackDataScrap *);
  88. };
  89. SampleManager::SampleManager(unsigned long blocking)
  90. {
  91.   impl_ = new SampleManagerImpl(blocking);
  92.   
  93. }
  94. SampleManager::~SampleManager()
  95. {
  96.   delete impl_;
  97.   impl_ = NULL;
  98. }
  99. unsigned long SampleManager::blocking() const
  100. {
  101.   return impl_->blocking_;
  102. }
  103. void SampleManager::setTocEdit(TocEdit *t)
  104. {
  105.   impl_->tocEdit_ = t;
  106.   impl_->tocReader_.init(t->toc());
  107.   impl_->blocks_ = 0;
  108. }
  109. int SampleManager::scanToc(unsigned long start, unsigned long end)
  110. {
  111.   return impl_->scanToc(start, end);
  112. }
  113. void SampleManager::getPeak(unsigned long start, unsigned long end,
  114.     short *leftNeg, short *leftPos,
  115.     short *rightNeg, short *rightPos)
  116. {
  117.   impl_->getPeak(start, end, leftNeg, leftPos, rightNeg, rightPos);
  118. }
  119. void SampleManager::removeSamples(unsigned long start, unsigned long end,
  120.   TrackDataScrap *scrap)
  121. {
  122.   impl_->removeSamples(start, end, scrap);
  123. }
  124. void SampleManager::insertSamples(unsigned long pos, unsigned long len,
  125.   const TrackDataScrap *scrap)
  126. {
  127.   impl_->insertSamples(pos, len, scrap);
  128. }
  129. SampleManagerImpl::SampleManagerImpl(unsigned long blocking) : tocReader_(NULL)
  130. {
  131.   blocking_ = blocking;
  132.   tocEdit_ = NULL;
  133.   leftNegSamples_ = leftPosSamples_ = NULL;
  134.   rightNegSamples_ = rightPosSamples_ = NULL;
  135.   samplesSize_ = 0;
  136.   blocks_ = 0;
  137.   slength_ = 0;
  138.   block_ = new Sample[blocking_];
  139.   actBlock_ = endBlock_ = burstBlock_ = 0;
  140.   length_ = 0;
  141.   withGui_ = 0;
  142.   // allocate space in chunks of 40 minutes
  143.   chunk_ = 40 * 60 * 75 * 588 / blocking;
  144.   // create progress window
  145.   Gtk_VBox *vbox = new Gtk_VBox();
  146.   Gtk_Label *label = new Gtk_Label(string("Scanning Audio Data..."));
  147.   
  148.   vbox->pack_start(*label, FALSE, FALSE, 5);
  149.   label->show();
  150.   progressBar_ = new Gtk_ProgressBar();
  151.   progressBar_->set_bar_style(GTK_PROGRESS_CONTINUOUS);
  152.   progressBar_->set_orientation(GTK_PROGRESS_LEFT_TO_RIGHT);
  153.   vbox->pack_start(*(progressBar_), FALSE, FALSE);
  154.   progressBar_->show();
  155.   Gtk_HBox *hbox = new Gtk_HBox();
  156.   Gtk_Button *button = new Gtk_Button(string(" Abort "));
  157.   hbox->pack_start(*button, TRUE, FALSE);
  158.   button->show();
  159.   connect_to_method(button->clicked, this, &SampleManagerImpl::abortAction);
  160.   vbox->pack_start(*hbox, FALSE, FALSE, 5);
  161.   hbox->show();
  162.   progressWindow_ = new Gtk_Window(GTK_WINDOW_DIALOG);
  163.   progressWindow_->add(vbox);
  164.   progressWindow_->set_usize(200, 0);
  165.   vbox->show();
  166. }
  167. SampleManagerImpl::~SampleManagerImpl()
  168. {
  169.   delete[] block_;
  170.   delete[] leftNegSamples_;
  171.   delete[] leftPosSamples_;
  172.   delete[] rightNegSamples_;
  173.   delete[] rightPosSamples_;
  174.   tocEdit_ = NULL;
  175. }
  176. void SampleManagerImpl::getPeak(unsigned long start, unsigned long end,
  177. short *leftNeg, short *leftPos,
  178. short *rightNeg, short *rightPos)
  179. {
  180.   *leftNeg = *leftPos = 0;
  181.   *rightNeg = *rightPos = 0;
  182.   long startBlock = start / blocking_;
  183.   long endBlock = end / blocking_;
  184.   long i;
  185.   if (startBlock >= blocks_ || endBlock >= blocks_)
  186.     return;
  187.   for (i = startBlock; i <= endBlock; i++) {
  188.     assert(leftNegSamples_[i] <= 0);
  189.     assert(rightNegSamples_[i] <= 0);
  190.     assert(leftPosSamples_[i] >= 0);
  191.     assert(rightPosSamples_[i] >= 0);
  192.     if (leftNegSamples_[i] < *leftNeg)
  193.       *leftNeg = leftNegSamples_[i];
  194.     if (leftPosSamples_[i] > *leftPos)
  195.       *leftPos = leftPosSamples_[i];
  196.     if (rightNegSamples_[i] < *rightNeg)
  197.       *rightNeg = rightNegSamples_[i];
  198.     if (rightPosSamples_[i] > *rightPos)
  199.       *rightPos = rightPosSamples_[i];
  200.   }
  201. }
  202. int SampleManagerImpl::scanToc(unsigned long start, unsigned long end)
  203. {
  204.   long i;
  205.   const Toc *toc;
  206.   actBlock_ = start / blocking_;
  207.   endBlock_ = end / blocking_;
  208.   if (tocEdit_ == NULL || endBlock_ < actBlock_)
  209.     return 1;
  210.   toc = tocEdit_->toc();
  211.   length_ = toc->length().samples();
  212.   if (end >= length_)
  213.     return 1;
  214.   length_ -= actBlock_ * blocking_;
  215.   reallocSamples(end);
  216.   for (i = actBlock_; i <= endBlock_; i++) {
  217.     leftNegSamples_[i] = rightNegSamples_[i] = -16000;
  218.     leftPosSamples_[i] = rightPosSamples_[i] = 16000;
  219.   }
  220.   //message(0, "readSamples: %ldn", endBlock_ - actBlock_ + 1);
  221.   
  222.   if (tocReader_.openData() != 0)
  223.     return 2;
  224.   if (tocReader_.seekSample(actBlock_ * blocking_) != 0) {
  225.     tocReader_.closeData();
  226.     return 2;
  227.   }
  228.   long len = endBlock_ - actBlock_ + 1;
  229.   if (len < 2000) {
  230.     burstBlock_ = len;
  231.     percentStep_ = 1.0;
  232.     withGui_ = 0;
  233.   }
  234.   else if (len < 10000) {
  235.     burstBlock_ = len / 100;
  236.     percentStep_ = 0.01;
  237.     withGui_ = 1;
  238.   }
  239.   else {
  240.     burstBlock_ = 500;
  241.     percentStep_ = gfloat(burstBlock_) / gfloat(len);
  242.     withGui_ = 1;
  243.   }
  244.   if (burstBlock_ == 0) 
  245.     burstBlock_ = 1;
  246.   percent_ = 0;
  247.   aborted_ = 0;
  248.   if (withGui_) {
  249.     progressWindow_->show();
  250.     connect_to_method(Gtk_Main::idle(), this, &SampleManagerImpl::readSamples);
  251.     tocEdit_->blockEdit();
  252.   }
  253.   else {
  254.     while (readSamples()) ;
  255.   }
  256.   return 0;
  257. }
  258. int SampleManagerImpl::readSamples()
  259. {
  260.   int j;
  261.   long n;
  262.   short lpossum, rpossum, lnegsum, rnegsum;
  263.   int ret;
  264.   long burstEnd = actBlock_ + burstBlock_;
  265.   if (withGui_ && aborted_) {
  266.     tocReader_.closeData();
  267.     progressWindow_->hide();
  268.     tocEdit_->unblockEdit();
  269.     guiUpdate(UPD_SAMPLES);
  270.     return 0;
  271.   }
  272.   for (; actBlock_ <= endBlock_ && actBlock_ < burstEnd && length_ > 0;
  273.        actBlock_++) {
  274.     n = length_ > blocking_ ? blocking_ : length_;
  275.     if ((ret = tocReader_.readSamples(block_, n)) == n) {
  276.       lpossum = lnegsum = rpossum = rnegsum = 0;
  277.       for (j = 0; j < n; j++) {
  278. short d = block_[j].left();
  279. if (d > lpossum)
  280.   lpossum = d;
  281. if (d < lnegsum)
  282.   lnegsum = d;
  283. d = block_[j].right();
  284. if (d > rpossum)
  285.   rpossum = d;
  286. if (d < rnegsum)
  287.   rnegsum = d;
  288.       }
  289.       leftNegSamples_[actBlock_] = lnegsum;
  290.       leftPosSamples_[actBlock_] = lpossum;
  291.       rightNegSamples_[actBlock_] = rnegsum;
  292.       rightPosSamples_[actBlock_] = rpossum;
  293.     }
  294.     else {
  295.       message(-2, "Cannot read audio data: %ld - %ld.", n, ret);
  296.       tocReader_.closeData();
  297.       if (withGui_) {
  298. progressWindow_->hide();
  299.       }
  300.       tocEdit_->unblockEdit();
  301.       guiUpdate(UPD_SAMPLES);
  302.       return 0;
  303.     }
  304.     length_ -= n;
  305.   }
  306.   
  307.   if (actBlock_ >= endBlock_ && actBlock_ < burstEnd) {
  308.     tocReader_.closeData();
  309.     if (withGui_) {
  310.       progressWindow_->hide();
  311.     }
  312.     tocEdit_->unblockEdit();
  313.     guiUpdate(UPD_SAMPLES);
  314.     return 0;
  315.   }
  316.   percent_ += percentStep_;
  317.   if (percent_ > 1.0) 
  318.     percent_ = 1.0;
  319.   if (withGui_) {
  320.     progressBar_->set_percentage(percent_);
  321.   }
  322.   return 1;
  323. }
  324. void SampleManagerImpl::abortAction()
  325. {
  326.   aborted_ = 1;
  327. }
  328. void SampleManagerImpl::reallocSamples(unsigned long maxSample)
  329. {
  330.   long i;
  331.   long maxBlock = (maxSample / blocking_) + 1;
  332.   if (maxSample >= slength_)
  333.     slength_ = maxSample + 1;
  334.   if (maxBlock > blocks_)
  335.     blocks_ = maxBlock;
  336.   if (blocks_ > samplesSize_) {
  337.     long newSize = samplesSize_ + chunk_;
  338.     while (newSize < blocks_)
  339.       newSize += chunk_;
  340.     short *newLeftNeg = new short[newSize];
  341.     short *newLeftPos = new short[newSize];
  342.     short *newRightNeg = new short[newSize];
  343.     short *newRightPos = new short[newSize];
  344.     for (i = 0; i < samplesSize_; i++) {
  345.       newLeftNeg[i] = leftNegSamples_[i];
  346.       newLeftPos[i] = leftPosSamples_[i];
  347.       newRightNeg[i] = rightNegSamples_[i];
  348.       newRightPos[i] = rightPosSamples_[i];
  349.     }
  350.     samplesSize_ = newSize;
  351.     delete[] leftNegSamples_;
  352.     delete[] leftPosSamples_;
  353.     delete[] rightNegSamples_;
  354.     delete[] rightPosSamples_;
  355.     leftNegSamples_ = newLeftNeg;
  356.     leftPosSamples_ = newLeftPos;
  357.     rightNegSamples_ = newRightNeg;
  358.     rightPosSamples_ = newRightPos;
  359.   }
  360. }
  361. void SampleManagerImpl::removeSamples(unsigned long start, unsigned long end,
  362.       TrackDataScrap *scrap)
  363. {
  364.   long i;
  365.   long bstart;
  366.   long oldBlocks = blocks_;
  367.   long blen;
  368.   unsigned long slen;
  369.   if (start > end || end >= slength_)
  370.     return;
  371.   slen = end - start + 1;
  372.   
  373.   slength_ -= slen;
  374.   if (slength_ == 0) {
  375.     blocks_ = 0;
  376.     return;
  377.   }
  378.   blocks_ = ((slength_ - 1) / blocking_) + 1;
  379.   
  380.   blen = oldBlocks - blocks_;
  381.   
  382.   bstart = start / blocking_;
  383.   if (scrap != NULL)
  384.     scrap->setPeaks(blen, &(leftNegSamples_[bstart]),
  385.     &(leftPosSamples_[bstart]), &(rightNegSamples_[bstart]),
  386.     &(rightPosSamples_[bstart]));
  387.   if (blen > 0) {
  388.     for (i = bstart; i < blocks_; i++) {
  389.       leftNegSamples_[i] = leftNegSamples_[i + blen];
  390.       leftPosSamples_[i] = leftPosSamples_[i + blen];
  391.       rightNegSamples_[i] = rightNegSamples_[i + blen];
  392.       rightPosSamples_[i] = rightPosSamples_[i + blen] ;
  393.     }
  394.   }
  395. }
  396. void SampleManagerImpl::insertSamples(unsigned long pos, unsigned long len,
  397.       const TrackDataScrap *scrap)
  398. {
  399.   long blen;
  400.   long bpos;
  401.   long oldBlocks;
  402.   long i;
  403.   if (len == 0)
  404.     return;
  405.   bpos = pos / blocking_;
  406.   if (bpos > blocks_)
  407.     bpos = blocks_;
  408.   oldBlocks = blocks_;
  409.   reallocSamples(slength_ + (len - 1));
  410.   blen = blocks_ - oldBlocks;
  411.   if (blen > 0) {
  412.     for (i = blocks_ - 1; i >= bpos + blen; i--) {
  413.       leftNegSamples_[i] = leftNegSamples_[i - blen];
  414.       leftPosSamples_[i] = leftPosSamples_[i - blen];
  415.       rightNegSamples_[i] = rightNegSamples_[i - blen];
  416.       rightPosSamples_[i] = rightPosSamples_[i - blen] ;
  417.     }
  418.     // initialize the new region
  419.     for (i = bpos; i < bpos + blen; i++) {
  420.       leftNegSamples_[i] = -16000;
  421.       leftPosSamples_[i] = 16000;
  422.       rightNegSamples_[i] = -16000;
  423.       rightPosSamples_[i] = 16000;
  424.     }
  425.     if (scrap != NULL)
  426.       scrap->getPeaks(blen, &(leftNegSamples_[bpos]), &(leftPosSamples_[bpos]),
  427.       &(rightNegSamples_[bpos]), &(rightPosSamples_[bpos]));
  428.   }
  429. }