Beispiel #1
0
bool EffectAmplify::ProcessOne(int count, WaveTrack *t,
                               sampleCount start, sampleCount len)
{
   sampleCount s = start;
   sampleCount originalLen = len;
   sampleCount blockSize = t->GetMaxBlockSize();

   sampleType *buffer = new sampleType[blockSize];
   
   while (len) {
      unsigned int block = t->GetBestBlockSize(s);
      if (block > len)
         block = len;

      t->Get(buffer, s, block);
      for (unsigned int i = 0; i < block; i++) {
         buffer[i] = (sampleType) (buffer[i] * ratio);
      }
      t->Set(buffer, s, block);

      len -= block;
      s += block;
      
      if (TrackProgress(count, (s-start)/(double)originalLen))
         break;
   }

   delete[] buffer;

   return true;
}
Beispiel #2
0
bool EffectInvert::ProcessOne(int count, WaveTrack *t,
                              sampleCount start, sampleCount len)
{
   // keep track of two blocks whose data we will swap
   sampleCount s = start;
   sampleCount originalLen = len;
   sampleCount blockSize = t->GetMaxBlockSize();
   
   sampleType *buffer = new sampleType[blockSize];
   
   while (len > 0) {
      unsigned int block = t->GetBestBlockSize(s);
      if (block > len)
         block = len;

      t->Get(buffer, s, block);
      for (unsigned int i = 0; i < block; i++) {
         buffer[i] = (sampleType) (-buffer[i]);
      }
      t->Set(buffer, s, block);

      len -= block;
      s += block;

      TrackProgress(count, (s-start)/(double)originalLen);
   }

   delete[] buffer;

   return true;
}
bool BlockGenerator::GenerateTrack(WaveTrack *tmp,
                                   const WaveTrack &track,
                                   int ntrack)
{
   bool bGoodResult = true;
   numSamples = track.TimeToLongSamples(GetDuration());
   sampleCount i = 0;
   float *data = new float[tmp->GetMaxBlockSize()];
   sampleCount block = 0;

   while ((i < numSamples) && bGoodResult) {
      block = tmp->GetBestBlockSize(i);
      if (block > (numSamples - i))
         block = numSamples - i;

      GenerateBlock(data, track, block);

      // Add the generated data to the temporary track
      tmp->Append((samplePtr)data, floatSample, block);
      i += block;

      // Update the progress meter
      if (TrackProgress(ntrack, (double)i / numSamples))
         bGoodResult = false;
   }
   delete[] data;
   return bGoodResult;
}
Beispiel #4
0
bool EffectRepeat::Process()
{
   this->CopyInputWaveTracks(); // Set up mOutputWaveTracks.
   bool bGoodResult = true;

   TrackListIterator iter(mOutputWaveTracks);
   WaveTrack *track = (WaveTrack *) iter.First();
   int nTrack = 0;
	double maxDestLen = 0.0; // used to change selection to generated bit
   while ((track != NULL) && bGoodResult) {
      double trackStart = track->GetStartTime();
      double trackEnd = track->GetEndTime();
      double t0 = mT0 < trackStart? trackStart: mT0;
      double t1 = mT1 > trackEnd? trackEnd: mT1;

      if (t1 <= t0)
         continue;

      sampleCount start = track->TimeToLongSamples(t0);
      sampleCount end = track->TimeToLongSamples(t1);
      sampleCount len = (sampleCount)(end - start);
      double tLen = track->LongSamplesToTime(len);
      double tc = t0 + tLen;

      if (len <= 0)
         continue;

      Track *dest;
      track->Copy(t0, t1, &dest);
      for(int j=0; j<repeatCount; j++)
      {
         if (!track->Paste(tc, dest) || 
               TrackProgress(nTrack, j / repeatCount)) // TrackProgress returns true on Cancel.
         {
            bGoodResult = false;
            break;
         }
         tc += tLen;
      }
      if (tc > maxDestLen)
         maxDestLen = tc;
      delete dest;

      track = (WaveTrack *) iter.Next();
      nTrack++;
   }

   if (bGoodResult)
   {
      // Change selection to just the generated bits.
      mT0 = mT1;
	   mT1 = maxDestLen;
   }

   this->ReplaceProcessedWaveTracks(bGoodResult); 
   return bGoodResult;
}
Beispiel #5
0
bool EffectClickRemoval::ProcessOne(int count, WaveTrack * track,
                                    sampleCount start, sampleCount len)
{
   bool rc = true;
   sampleCount s = 0;
   sampleCount idealBlockLen = track->GetMaxBlockSize() * 4;

   if (idealBlockLen % windowSize != 0)
      idealBlockLen += (windowSize - (idealBlockLen % windowSize));

   float *buffer = new float[idealBlockLen];

   float *datawindow = new float[windowSize];

   int i;

   while((s < len)&&((len-s)>(windowSize/2))) {
      sampleCount block = idealBlockLen;
      if (s + block > len)
         block = len - s;

      track->Get((samplePtr) buffer, floatSample, start + s, block);

      for(i=0; i<(block-windowSize/2); i+=windowSize/2) {
         int wcopy = windowSize;
         if (i + wcopy > block)
            wcopy = block - i;

         int j;
         for(j=0; j<wcopy; j++)
            datawindow[j] = buffer[i+j];
         for(j=wcopy; j<windowSize; j++)
            datawindow[j] = 0;

         RemoveClicks(windowSize, datawindow);

         for(j=0; j<wcopy; j++)
           buffer[i+j] = datawindow[j];
      }

      track->Set((samplePtr) buffer, floatSample, start + s, block);

      s += block;

      if (TrackProgress(count, s / (double) len)) {
         rc = false;
         break;
      }
   }

   delete[] buffer;
   delete[] datawindow;

   return rc;
}
Beispiel #6
0
//ProcessOne() takes a track, transforms it to bunch of buffer-blocks,
//and executes ProcessData, on it...
// uses mMult and mOffset to normalize a track.  Needs to have them set before being called
bool EffectNormalize::ProcessOne(WaveTrack * track, wxString msg)
{
   bool rc = true;
   sampleCount s;

   //Transform the marker timepoints to samples
   sampleCount start = track->TimeToLongSamples(mCurT0);
   sampleCount end = track->TimeToLongSamples(mCurT1);
         
   //Get the length of the buffer (as double). len is
   //used simply to calculate a progress meter, so it is easier
   //to make it a double now than it is to do it later 
   double len = (double)(end - start);

   //Initiate a processing buffer.  This buffer will (most likely)
   //be shorter than the length of the track being processed.
   float *buffer = new float[track->GetMaxBlockSize()];

   //Go through the track one buffer at a time. s counts which
   //sample the current buffer starts at.
   s = start;
   while (s < end) {
      //Get a block of samples (smaller than the size of the buffer)
      sampleCount block = track->GetBestBlockSize(s);
      
      //Adjust the block size if it is the final block in the track
      if (s + block > end)
         block = end - s;
      
      //Get the samples from the track and put them in the buffer
      track->Get((samplePtr) buffer, floatSample, s, block);
      
      //Process the buffer.
      ProcessData(buffer, block);
   
      //Copy the newly-changed samples back onto the track.
      track->Set((samplePtr) buffer, floatSample, s, block);
         
      //Increment s one blockfull of samples
      s += block;
      
      //Update the Progress meter
		if (TrackProgress(mCurTrackNum, 
                        0.5+((double)(s - start) / len)/2.0, msg)) {
         rc = false; //lda .. break, not return, so that buffer is deleted
         break;
      }
   }
   //Clean up the buffer
   delete[] buffer;

   //Return true because the effect processing succeeded ... unless cancelled
   return rc;
}
Beispiel #7
0
//ProcessOne() takes a track, transforms it to bunch of buffer-blocks,
//and executes ProcessSimpleMono on these blocks
bool EffectSimpleMono::ProcessOne(WaveTrack * track,
                                  longSampleCount start, longSampleCount end)
{
   
   longSampleCount s;
   //Get the length of the buffer (as double). len is
   //used simple to calculate a progress meter, so it is easier
   //to make it a double now than it is to do it later 
   double len = (double)(end - start);

   //Initiate a processing buffer.  This buffer will (most likely)
   //be shorter than the length of the track being processed.
   float *buffer = new float[track->GetMaxBlockSize()];

   //Go through the track one buffer at a time. s counts which
   //sample the current buffer starts at.
   s = start;
   while (s < end) {
      //Get a block of samples (smaller than the size of the buffer)
      sampleCount block = track->GetBestBlockSize(s);

      //Adjust the block size if it is the final block in the track
      if (s + block > end)
         block = end - s;

      //Get the samples from the track and put them in the buffer
      track->Get((samplePtr) buffer, floatSample, s, block);

      //Process the buffer.  If it fails, clean up and exit.
      if (!ProcessSimpleMono(buffer, block)) {
         delete[]buffer;

         //Return false because the effect failed.
         return false;
      }

      //Processing succeeded. copy the newly-changed samples back 
      //onto the track.
      track->Set((samplePtr) buffer, floatSample, s, block);

      //Increment s one blockfull of samples
      s += block;

      //Update the Progress meter
      if (TrackProgress(mCurTrackNum, s / len))
         return false;
   }

   //Clean up the buffer
   delete[]buffer;

   //Return true because the effect processing succeeded.
   return true;
}
Beispiel #8
0
bool EffectRepair::ProcessOne(int count, WaveTrack * track,
                              sampleCount start,
                              size_t len,
                              size_t repairStart, size_t repairLen)
{
   Floats buffer{ len };
   track->Get((samplePtr) buffer.get(), floatSample, start, len);
   InterpolateAudio(buffer.get(), len, repairStart, repairLen);
   track->Set((samplePtr)&buffer[repairStart], floatSample,
              start + repairStart, repairLen);
   return !TrackProgress(count, 1.0); // TrackProgress returns true on Cancel.
}
Beispiel #9
0
bool EffectEcho::ProcessOne(int count, WaveTrack * track,
                            sampleCount start, sampleCount len)
{
   sampleCount s = 0;
   sampleCount blockSize = (sampleCount) (track->GetRate() * delay);
   
   //do nothing if the delay is less than 1 sample or greater than
   //the length of the selection
   if (blockSize < 1 || blockSize > len)
      return true;

   float *buffer0 = new float[blockSize];
   float *buffer1 = new float[blockSize];

   float *ptr0 = buffer0;
   float *ptr1 = buffer1;

   bool first = true;

   while (s < len) {
      sampleCount block = blockSize;
      if (s + block > len)
         block = len - s;

      track->Get((samplePtr)ptr0, floatSample, start + s, block);
      if (!first) {
         for (sampleCount i = 0; i < block; i++)
            ptr0[i] += ptr1[i] * decay;
         track->Set((samplePtr)ptr0, floatSample, start + s, block);
      }

      float *ptrtemp = ptr0;
      ptr0 = ptr1;
      ptr1 = ptrtemp;

      first = false;

      s += block;
      
      if (TrackProgress(count, s / (double) len)) {
         delete[]buffer0;
         delete[]buffer1;

         return false;
      }
   }

   delete[]buffer0;
   delete[]buffer1;

   return true;
}
Beispiel #10
0
bool EffectRepair::ProcessOne(int count, WaveTrack * track,
                              sampleCount start,
                              sampleCount len,
                              sampleCount repairStart, sampleCount repairLen)
{
   float *buffer = new float[len];
   track->Get((samplePtr) buffer, floatSample, start, len);
   InterpolateAudio(buffer, len, repairStart, repairLen);
   track->Set((samplePtr)&buffer[repairStart], floatSample,
              start + repairStart, repairLen);
   delete[] buffer;
   return !TrackProgress(count, 1.0); // TrackProgress returns true on Cancel.
}
Beispiel #11
0
bool EffectEcho::ProcessOne(int count, WaveTrack * t,
                            sampleCount start, sampleCount len)
{
   sampleCount s = start;
   sampleCount blockSize = (sampleCount) (t->rate * delay);
   
   sampleCount originalLen = len;

   if (blockSize < 1 || blockSize > len)
      return true;

   sampleType *buffer0 = new sampleType[blockSize];
   sampleType *buffer1 = new sampleType[blockSize];

   sampleType *ptr0 = buffer0;
   sampleType *ptr1 = buffer1;

   bool first = true;

   while (len) {
      sampleCount block = blockSize;
      if (block > len)
         block = len;

      t->Get(ptr0, s, block);
      if (!first) {
         for (sampleCount i = 0; i < block; i++)
            ptr0[i] += (sampleType) (ptr1[i] * decay);
         t->Set(ptr0, s, block);
      }

      sampleType *ptrtemp = ptr0;
      ptr0 = ptr1;
      ptr1 = ptrtemp;

      first = false;

      len -= block;
      s += block;
      
      TrackProgress(count, (s-start)/(double)originalLen);
   }

   delete[]buffer0;
   delete[]buffer1;

   return true;
}
Beispiel #12
0
bool EffectStereoToMono::ProcessOne(int count)
{
   float  curLeftFrame;
   float  curRightFrame;
   float  curMonoFrame;

   sampleCount idealBlockLen = mLeftTrack->GetMaxBlockSize() * 2;
   sampleCount index = mStart;
   float *leftBuffer = new float[idealBlockLen];
   float *rightBuffer = new float[idealBlockLen];
   bool bResult = true;

   while (index < mEnd) {
      bResult &= mLeftTrack->Get((samplePtr)leftBuffer, floatSample, index, idealBlockLen);
      bResult &= mRightTrack->Get((samplePtr)rightBuffer, floatSample, index, idealBlockLen);
      sampleCount limit = idealBlockLen;
      if ((index + idealBlockLen) > mEnd) {
         limit = mEnd - index;
      }
      for (sampleCount i = 0; i < limit; ++i) {
         index++;
         curLeftFrame = leftBuffer[i];
         curRightFrame = rightBuffer[i];
         curMonoFrame = (curLeftFrame + curRightFrame) / 2.0;
         leftBuffer[i] = curMonoFrame;
      }
      bResult &= mOutTrack->Append((samplePtr)leftBuffer, floatSample, limit);
      if (TrackProgress(count, 2.*((double)index / (double)(mEnd - mStart))))
         return false;
   }

   double minStart = wxMin(mLeftTrack->GetStartTime(), mRightTrack->GetStartTime());
   bResult &= mLeftTrack->Clear(mLeftTrack->GetStartTime(), mLeftTrack->GetEndTime());
   bResult &= mOutTrack->Flush();
   bResult &= mLeftTrack->Paste(minStart, mOutTrack);
   mLeftTrack->SetLinked(false);
   mRightTrack->SetLinked(false);
   mLeftTrack->SetChannel(Track::MonoChannel);
   mOutputTracks->Remove(mRightTrack);
   delete mRightTrack;

   delete [] leftBuffer;
   delete [] rightBuffer;

   return bResult;
}
Beispiel #13
0
bool EffectReverse::ProcessOneClip(int count, WaveTrack *track,
                               sampleCount start, sampleCount len,
                               sampleCount originalStart, sampleCount originalEnd)
{
   bool rc = true;
   // keep track of two blocks whose data we will swap
   sampleCount first = start;
   sampleCount second;

   sampleCount blockSize = track->GetMaxBlockSize();
   float tmp;
   float *buffer1 = new float[blockSize];
   float *buffer2 = new float[blockSize];
   
   sampleCount originalLen = (sampleCount)originalEnd-originalStart;

   while (len > 1) {
      sampleCount block = track->GetBestBlockSize(first);
      if (block > len / 2)
         block = len / 2;
      second = first + (len - block);

      track->Get((samplePtr)buffer1, floatSample, first, block);
      track->Get((samplePtr)buffer2, floatSample, second, block);
      for (int i = 0; i < block; i++) {
         tmp = buffer1[i];
         buffer1[i] = buffer2[block-i-1];
         buffer2[block-i-1] = tmp;
      }
      track->Set((samplePtr)buffer1, floatSample, first, block);
      track->Set((samplePtr)buffer2, floatSample, second, block);

      len -= 2 * block;
      first += block;
      
      if( TrackProgress(count, 2*(first-originalStart) / (double) originalLen) ) {
         rc = false;
         break;
      }
   }

   delete[] buffer1;
   delete[] buffer2;

   return rc;
}
Beispiel #14
0
bool EffectReverse::ProcessOneClip(int count, WaveTrack *track,
                               sampleCount start, sampleCount len,
                               sampleCount originalStart, sampleCount originalEnd)
{
   bool rc = true;
   // keep track of two blocks whose data we will swap
   auto first = start;

   auto blockSize = track->GetMaxBlockSize();
   float tmp;
   Floats buffer1{ blockSize };
   Floats buffer2{ blockSize };

   auto originalLen = originalEnd - originalStart;

   while (len > 1) {
      auto block =
         limitSampleBufferSize( track->GetBestBlockSize(first), len / 2 );
      auto second = first + (len - block);

      track->Get((samplePtr)buffer1.get(), floatSample, first, block);
      track->Get((samplePtr)buffer2.get(), floatSample, second, block);
      for (decltype(block) i = 0; i < block; i++) {
         tmp = buffer1[i];
         buffer1[i] = buffer2[block-i-1];
         buffer2[block-i-1] = tmp;
      }
      track->Set((samplePtr)buffer1.get(), floatSample, first, block);
      track->Set((samplePtr)buffer2.get(), floatSample, second, block);

      len -= 2 * block;
      first += block;

      if( TrackProgress(count, 2 * ( first - originalStart ).as_double() /
                        originalLen.as_double() ) ) {
         rc = false;
         break;
      }
   }

   return rc;
}
bool EffectSineSweepGenerator::GenerateTrack(WaveTrack *tmp, const WaveTrack &track, int ntrack)
{
#ifdef __AUDEBUG__
   printf("elsg: GENERATETRACK\n"); fflush(stdout); // ************DEBUG
#endif
   bool bGoodResult = true;
   //numSamples = track.TimeToLongSamples(mDuration);
   sampleCount numSamples;
   //Filter has different length
   if(ntrack == m_pSsg->GetFilterChannel())       
      numSamples = sampleCount(m_pSsg->GetFilterLength());
   else
      numSamples = sampleCount(m_pSsg->GetBuffersLength());
   
   sampleCount i = 0;
   AFSample *data = new AFSample[tmp->GetMaxBlockSize()];
   sampleCount block = 0;

   while ((i < numSamples) && bGoodResult) 
   {
      block = tmp->GetBestBlockSize(i);
      if (block > (numSamples - i))
         block = numSamples - i;

//       GenerateBlock(data, track, block);
      m_pSsg->FillBlock(data, AFSampleCount(block), AFSampleCount(i), ntrack);

      // Add the generated data to the temporary track
      tmp->Append((samplePtr)data, floatSample, block);
      i += block;

      // Update the progress meter
      if (TrackProgress(ntrack, (double)i / numSamples))
         bGoodResult = false;
      
   }
   tmp->Flush();

   delete[] data;
   return bGoodResult;   
}
Beispiel #16
0
void EffectStereoToMono::ProcessOne()
{
   float  curLeftFrame;
   float  curRightFrame;
   float  curMonoFrame;

   sampleCount idealBlockLen = mLeftTrack->GetMaxBlockSize() * 2;
   sampleCount index = 0;
   sampleCount outTrackOffset = 0;
   float *leftBuffer = new float[idealBlockLen];
   float *rightBuffer = new float[idealBlockLen];
   bool rc;

   while (index < mLeftTrackLen) {
      rc = mLeftTrack->Get((samplePtr)leftBuffer, floatSample, index, idealBlockLen);
      rc = mRightTrack->Get((samplePtr)rightBuffer, floatSample, index, idealBlockLen);
      sampleCount limit = idealBlockLen;
      if ((index + idealBlockLen) > mLeftTrackLen) {
         limit = mLeftTrackLen - index;
      }
      for (sampleCount i = 0; i < limit; ++i) {
         index++;
         curLeftFrame = leftBuffer[i];
         curRightFrame = rightBuffer[i];
         curMonoFrame = (curLeftFrame + curRightFrame) / 2.0;
         leftBuffer[i] = curMonoFrame;
      }
      rc = mLeftTrack->Set((samplePtr)leftBuffer, floatSample, outTrackOffset, limit);
      outTrackOffset += limit;
      TrackProgress(0, ((double)index / (double)mLeftTrackLen));
   }

   mLeftTrack->SetLinked(false);
   mRightTrack->SetLinked(false);
   mLeftTrack->SetChannel(Track::MonoChannel);
   mTracks->Remove(mRightTrack);
   delete mRightTrack;

   delete [] leftBuffer;
   delete [] rightBuffer;
}
Beispiel #17
0
bool EffectFilter::ProcessOne(int count, WaveTrack * t,
                                 sampleCount start, sampleCount len)
{
   sampleCount s = start;
   sampleCount idealBlockLen = t->GetMaxBlockSize() * 4;
   
   if (idealBlockLen % windowSize != 0)
      idealBlockLen += (windowSize - (idealBlockLen % windowSize));
   
   sampleType *buffer = new sampleType[idealBlockLen];
   
   sampleType *window1 = new sampleType[windowSize];
   sampleType *window2 = new sampleType[windowSize];
   sampleType *thisWindow = window1;
   sampleType *lastWindow = window2;
   
   sampleCount originalLen = len;
   
   unsigned int i;
   
   for(i=0; i<windowSize; i++)
      lastWindow[i] = 0;
   
   while(len) {
      unsigned int block = idealBlockLen;
      if (block > len)
         block = len;
      
      t->Get(buffer, s, block);
      
      for(i=0; i<block; i+=windowSize/2) {
         unsigned int wcopy = windowSize;
         if (i + wcopy > block)
            wcopy = block - i;
         
         unsigned int j;
         for(j=0; j<wcopy; j++)
            thisWindow[j] = buffer[i+j];
         for(j=wcopy; j<windowSize; j++)
            thisWindow[j] = 0;
         
         Filter(windowSize, thisWindow);
         
         for(j=0; j<windowSize/2; j++)
            buffer[i+j] = thisWindow[j] + lastWindow[windowSize/2 + j];
         
         sampleType *tempP = thisWindow;
         thisWindow = lastWindow;
         lastWindow = tempP;
      }
      
      if (len > block && len > windowSize/2)
         block -= windowSize/2;
      
      t->Set(buffer, s, block);
      
      len -= block;
      s += block;
      
      TrackProgress(count, (s-start)/(double)originalLen);
   }
   
   delete[] buffer;
   delete[] window1;
   delete[] window2;
   
   return true;
}
Beispiel #18
0
bool VampEffect::Process()
{
   if (!mPlugin) return false;

   TrackListIterator iter(mWaveTracks);

   int count = 0;

   WaveTrack *left = (WaveTrack *)iter.First();

   bool multiple = false;
   int prevTrackChannels = 0;

   TrackListIterator scooter(iter);
   if (left->GetLinked()) scooter.Next();      
   if (scooter.Next()) {
      // if there is another track beyond this one and any linked one,
      // then we're processing more than one track.  That means we
      // should use the originating track name in each new label
      // track's name, to make clear which is which
      multiple = true;
   }

   while (left) {

      sampleCount lstart, rstart;
      sampleCount len;
      GetSamples(left, &lstart, &len);
      
      WaveTrack *right = NULL;
      int channels = 1;

      if (left->GetLinked()) {
         right = (WaveTrack *)iter.Next();
         channels = 2;
         GetSamples(right, &rstart, &len);
      }

      size_t step = mPlugin->getPreferredStepSize();
      size_t block = mPlugin->getPreferredBlockSize();

      bool initialiseRequired = true;

      if (block == 0) {
         if (step != 0) block = step;
         else block = 1024;
      }
      if (step == 0) {
         step = block;
      }

      if (prevTrackChannels > 0) {
         // Plugin has already been initialised, so if the number of
         // channels remains the same, we only need to do a reset.
         // Otherwise we need to re-construct the whole plugin,
         // because a Vamp plugin can't be re-initialised.
         if (prevTrackChannels == channels) {
            mPlugin->reset();
            initialiseRequired = false;
         } else {
            //!!! todo: retain parameters previously set
            Init();
         }
      }

      if (initialiseRequired) {
         if (!mPlugin->initialise(channels, step, block)) {
            wxMessageBox(_("Sorry, Vamp Plug-in failed to initialize."));
            return false;
         }
      }

      LabelTrack *ltrack = mFactory->NewLabelTrack();

      if (!multiple) {
         ltrack->SetName(GetEffectName());
      } else {
         ltrack->SetName(wxString::Format(wxT("%s: %s"),
                                          left->GetName().c_str(),
                                          GetEffectName().c_str()));
      }

      mTracks->Add(ltrack);

      float **data = new float*[channels];
      for (int c = 0; c < channels; ++c) data[c] = new float[block];

      sampleCount originalLen = len;
      sampleCount ls = lstart;
      sampleCount rs = rstart;

      while (len) {
         
         int request = block;
         if (request > len) request = len;

         if (left) left->Get((samplePtr)data[0], floatSample, ls, request);
         if (right) right->Get((samplePtr)data[1], floatSample, rs, request);

         if (request < (int)block) {
            for (int c = 0; c < channels; ++c) {
               for (int i = request; i < (int)block; ++i) {
                  data[c][i] = 0.f;
               }
            }
         }

         Vamp::RealTime timestamp = Vamp::RealTime::frame2RealTime
            (ls, (int)(mRate + 0.5));

         Vamp::Plugin::FeatureSet features = mPlugin->process(data, timestamp);
         AddFeatures(ltrack, features);

         if (len > (int)step) len -= step;
         else len = 0;

         ls += step;
         rs += step;

         if (channels > 1) {
            if (TrackGroupProgress(count, (ls - lstart) / double(originalLen)))
               return false;
         } else {
            if (TrackProgress(count, (ls - lstart) / double(originalLen)))
               return false;
         }
      }

      Vamp::Plugin::FeatureSet features = mPlugin->getRemainingFeatures();
      AddFeatures(ltrack, features);

      prevTrackChannels = channels;

      left = (WaveTrack *)iter.Next();
   }

   return true;
}
Beispiel #19
0
//ProcessOne() takes a track, transforms it to bunch of buffer-blocks,
//and executes ProcessSoundTouch on these blocks
bool EffectSoundTouch::ProcessOne(WaveTrack *track,
                                  longSampleCount start, longSampleCount end)
{
   WaveTrack *outputTrack;
   longSampleCount s;

   mSoundTouch->setSampleRate((unsigned int)(track->GetRate()+0.5));
   
   outputTrack = mFactory->NewWaveTrack(track->GetSampleFormat());

   //Get the length of the buffer (as double). len is
   //used simple to calculate a progress meter, so it is easier
   //to make it a double now than it is to do it later 
   double len = (double)(end - start);

   //Initiate a processing buffer.  This buffer will (most likely)
   //be shorter than the length of the track being processed.
   float *buffer = new float[track->GetMaxBlockSize()];

   //Go through the track one buffer at a time. s counts which
   //sample the current buffer starts at.
   s = start;
   while (s < end) {
      //Get a block of samples (smaller than the size of the buffer)
      sampleCount block = track->GetBestBlockSize(s);

      //Adjust the block size if it is the final block in the track
      if (s + block > end)
         block = end - s;

      //Get the samples from the track and put them in the buffer
      track->Get((samplePtr) buffer, floatSample, s, block);

      //Add samples to SoundTouch
      mSoundTouch->putSamples(buffer, block);

      //Get back samples from SoundTouch
      unsigned int outputCount = mSoundTouch->numSamples();
      if (outputCount > 0) {
         float *buffer2 = new float[outputCount];
         mSoundTouch->receiveSamples(buffer2, outputCount);
         outputTrack->Append((samplePtr)buffer2, floatSample, outputCount);
         delete[] buffer2;
      }

      //Increment s one blockfull of samples
      s += block;

      //Update the Progress meter
      if (TrackProgress(mCurTrackNum, (s - start) / len))
         return false;
   }

   // Tell SoundTouch to finish processing any remaining samples
   mSoundTouch->flush();

   unsigned int outputCount = mSoundTouch->numSamples();
   if (outputCount > 0) {
      float *buffer2 = new float[outputCount];
      mSoundTouch->receiveSamples(buffer2, outputCount);
      outputTrack->Append((samplePtr)buffer2, floatSample, outputCount);
      delete[] buffer2;
   }

   // Flush the output WaveTrack (since it's buffered, too)
   outputTrack->Flush();

   // Clean up the buffer
   delete[]buffer;

   // Take the output track and insert it in place of the original
   // sample data

   track->Clear(mT0, mT1);
   track->Paste(mT0, outputTrack);

	double newLength = outputTrack->GetEndTime(); 
	if (newLength > m_maxNewLength) 
		m_maxNewLength = newLength; 

   // Delete the outputTrack now that its data is inserted in place
   delete outputTrack;

   //Return true because the effect processing succeeded.
   return true;
}
Beispiel #20
0
bool EffectBassBoost::ProcessOne(int count, WaveTrack * t,
                                 sampleCount start, sampleCount len)
{
   float samplerate = (float) (t->GetRate());

   /* Compute coefficents of the biquand IIR filter */
   float omega = 2 * 3.141592653589 * frequency / samplerate;
   float sn = sin(omega);
   float cs = cos(omega);
   float a = exp(log(10) * dB_boost / 40);
   float shape = 1.0;           /*Low Shelf filter's shape, if this is too large
                                   or too small it will result an unstable filter */
   float beta = sqrt((a * a + 1) / shape - (pow((a - 1), 2)));
   /*  Coefficients  */
   float b0 = a * ((a + 1) - (a - 1) * cs + beta * sn);
   float b1 = 2 * a * ((a - 1) - (a + 1) * cs);
   float b2 = a * ((a + 1) - (a - 1) * cs - beta * sn);
   float a0 = ((a + 1) + (a - 1) * cs + beta * sn);
   float a1 = -2 * ((a - 1) + (a + 1) * cs);
   float a2 = (a + 1) + (a - 1) * cs - beta * sn;
   /* initialise the filter */
   float xn1 = 0, xn2 = 0, yn1 = 0, yn2 = 0;

   float out, in = 0;

   sampleCount s = start;
   sampleCount originalLen = len;
   sampleCount blockSize = t->GetMaxBlockSize();

   float *buffer = new float[blockSize];

   while (len) {
      sampleCount block = t->GetBestBlockSize(s);
      if (block > len)
         block = len;

      t->Get(buffer, s, block);

      for (int i = 0; i < block; i++) {
         in = buffer[i];
         out = (b0 * in + b1 * xn1 + b2 * xn2 - a1 * yn1 - a2 * yn2) / a0;
         xn2 = xn1;
         xn1 = in;
         yn2 = yn1;
         yn1 = out;

         if (out < -1.0)
            out = -1.0;
         else if (out > 1.0)
            out = 1.0;        //Prevents clipping

         buffer[i] = out;
      }

      t->Set(buffer, s, block);
      
      len -= block;
      s += block;
      
      TrackProgress(count, (s-start)/(double)originalLen);
   }

   delete[]buffer;

   return true;
}
Beispiel #21
0
bool EffectPaulstretch::ProcessOne(WaveTrack *track,double t0,double t1,int count)
{
   auto badAllocMessage = _("Requested value exceeds memory capacity.");

   const auto stretch_buf_size = GetBufferSize(track->GetRate());
   if (stretch_buf_size == 0) {
      ::Effect::MessageBox( badAllocMessage );
      return false;
   }

   double amount = this->mAmount;

   auto start = track->TimeToLongSamples(t0);
   auto end = track->TimeToLongSamples(t1);
   auto len = end - start;

   const auto minDuration = stretch_buf_size * 2 + 1;
   if (minDuration < stretch_buf_size) {
      // overflow!
      ::Effect::MessageBox( badAllocMessage );
      return false;
   }

   if (len < minDuration) {   //error because the selection is too short

      float maxTimeRes = log( len.as_double() ) / log(2.0);
      maxTimeRes = pow(2.0, floor(maxTimeRes) + 0.5);
      maxTimeRes = maxTimeRes / track->GetRate();

      if (this->IsPreviewing()) {
         double defaultPreviewLen;
         gPrefs->Read(wxT("/AudioIO/EffectsPreviewLen"), &defaultPreviewLen, 6.0);

         /* i18n-hint: 'Time Resolution' is the name of a control in the Paulstretch effect.*/
         if ((minDuration / mProjectRate) < defaultPreviewLen) {
            ::Effect::MessageBox (wxString::Format(_("Audio selection too short to preview.\n\n"
                                               "Try increasing the audio selection to at least %.1f seconds,\n"
                                               "or reducing the 'Time Resolution' to less than %.1f seconds."),
                                             (minDuration / track->GetRate()) + 0.05, // round up to 1/10 s.
                                             floor(maxTimeRes * 10.0) / 10.0),
                            wxOK | wxICON_EXCLAMATION);
         }
         else {
            /* i18n-hint: 'Time Resolution' is the name of a control in the Paulstretch effect.*/
            ::Effect::MessageBox (wxString::Format(_("Unable to Preview.\n\n"
                                               "For the current audio selection, the maximum\n"
                                               "'Time Resolution' is %.1f seconds."),
                                             floor(maxTimeRes * 10.0) / 10.0),
                            wxOK | wxICON_EXCLAMATION);
         }
      }
      else {
         /* i18n-hint: 'Time Resolution' is the name of a control in the Paulstretch effect.*/
         ::Effect::MessageBox (wxString::Format(_("The 'Time Resolution' is too long for the selection.\n\n"
                                            "Try increasing the audio selection to at least %.1f seconds,\n"
                                            "or reducing the 'Time Resolution' to less than %.1f seconds."),
                                          (minDuration / track->GetRate()) + 0.05, // round up to 1/10 s.
                                          floor(maxTimeRes * 10.0) / 10.0),
                         wxOK | wxICON_EXCLAMATION);
      }

      return false;
   }


   auto dlen = len.as_double();
   double adjust_amount = dlen /
      (dlen - ((double)stretch_buf_size * 2.0));
   amount = 1.0 + (amount - 1.0) * adjust_amount;

   auto outputTrack = mFactory->NewWaveTrack(track->GetSampleFormat(),track->GetRate());

   try {
      // This encloses all the allocations of buffers, including those in
      // the constructor of the PaulStretch object

      PaulStretch stretch(amount, stretch_buf_size, track->GetRate());

      auto nget = stretch.get_nsamples_for_fill();

      auto bufsize = stretch.poolsize;
      Floats buffer0{ bufsize };
      float *bufferptr0 = buffer0.get();
      bool first_time = true;

      const auto fade_len = std::min<size_t>(100, bufsize / 2 - 1);
      bool cancelled = false;

      {
         Floats fade_track_smps{ fade_len };
         decltype(len) s=0;

         while (s < len) {
            track->Get((samplePtr)bufferptr0, floatSample, start + s, nget);
            stretch.process(buffer0.get(), nget);

            if (first_time) {
               stretch.process(buffer0.get(), 0);
            };

            s += nget;

            if (first_time){//blend the the start of the selection
               track->Get((samplePtr)fade_track_smps.get(), floatSample, start, fade_len);
               first_time = false;
               for (size_t i = 0; i < fade_len; i++){
                  float fi = (float)i / (float)fade_len;
                  stretch.out_buf[i] =
                     stretch.out_buf[i] * fi + (1.0 - fi) * fade_track_smps[i];
               }
            }
            if (s >= len){//blend the end of the selection
               track->Get((samplePtr)fade_track_smps.get(), floatSample, end - fade_len, fade_len);
               for (size_t i = 0; i < fade_len; i++){
                  float fi = (float)i / (float)fade_len;
                  auto i2 = bufsize / 2 - 1 - i;
                  stretch.out_buf[i2] =
                     stretch.out_buf[i2] * fi + (1.0 - fi) *
                     fade_track_smps[fade_len - 1 - i];
               }
            }

            outputTrack->Append((samplePtr)stretch.out_buf.get(), floatSample, stretch.out_bufsize);

            nget = stretch.get_nsamples();
            if (TrackProgress(count,
               s.as_double() / len.as_double()
            )) {
               cancelled = true;
               break;
            }
         }
      }

      if (!cancelled){
         outputTrack->Flush();

         track->Clear(t0,t1);
         track->Paste(t0, outputTrack.get());
         m_t1 = mT0 + outputTrack->GetEndTime();
      }
      
      return !cancelled;
   }
   catch ( const std::bad_alloc& ) {
      ::Effect::MessageBox( badAllocMessage );
      return false;
   }
};
Beispiel #22
0
bool LadspaEffect::ProcessStereo(int count, WaveTrack *left, WaveTrack *right,
                                 sampleCount lstart,
                                 sampleCount rstart,
                                 sampleCount len)
{
    /* Allocate buffers */
    if (mBlockSize == 0) {
        mBlockSize = left->GetMaxBlockSize() * 2;

        fInBuffer = new float *[inputs];
        unsigned long i;
        for (i = 0; i < inputs; i++)
            fInBuffer[i] = new float[mBlockSize];
        fOutBuffer = new float *[outputs];
        for (i = 0; i < outputs; i++)
            fOutBuffer[i] = new float[mBlockSize];
    }

    /* Instantiate the plugin */

    unsigned long rate = (unsigned long)(left->GetRate() + 0.5);
    LADSPA_Handle handle = mData->instantiate(mData, rate);

    unsigned long p;
    for(p=0; p<inputs; p++) {
        mData->connect_port(handle, inputPorts[p], fInBuffer[p]);
    }
    for(p=0; p<outputs; p++) {
        mData->connect_port(handle, outputPorts[p], fOutBuffer[p]);
    }

    for(p=0; p<mData->PortCount; p++) {
        LADSPA_PortDescriptor d = mData->PortDescriptors[p];
        if (LADSPA_IS_PORT_CONTROL(d)) {
            if (LADSPA_IS_PORT_INPUT(d)) {
                mData->connect_port(handle, p, &inputControls[p]);
            }
            else
                mData->connect_port(handle, p, &outputControls[p]);
        }
    }

    if (mData->activate)
        mData->activate(handle);

    // Actually perform the effect here

    sampleCount originalLen = len;
    sampleCount ls = lstart;
    sampleCount rs = rstart;
    while (len) {
        int block = mBlockSize;
        if (block > len)
            block = len;

        if (left && inputs > 0) {
            left->Get((samplePtr)fInBuffer[0], floatSample, ls, block);
        }
        if (right && inputs > 1) {
            right->Get((samplePtr)fInBuffer[1], floatSample, rs, block);
        }

        mData->run(handle, block);

        if (left && outputs > 0) {
            left->Set((samplePtr)fOutBuffer[0], floatSample, ls, block);
        }

        if (right && outputs > 1) {
            right->Set((samplePtr)fOutBuffer[1], floatSample, rs, block);
        }

        len -= block;
        ls += block;
        rs += block;

        if (inputs > 1) {
            if (TrackGroupProgress(count, (ls-lstart)/(double)originalLen))
                return false;
        }
        else {
            if (TrackProgress(count, (ls-lstart)/(double)originalLen))
                return false;
        }
    }

    if (mData->deactivate)
        mData->deactivate(handle);

    if (mData->cleanup)
        mData->cleanup(handle);

    return true;
}
Beispiel #23
0
bool VSTEffect::ProcessStereo(int count,
                              WaveTrack *left, WaveTrack *right,
                              sampleCount lstart, sampleCount rstart,
                              sampleCount len)
{
   bool rc = true;

   // Initialize time info
   mTimeInfo.samplePos = 0.0;
   mTimeInfo.sampleRate = left->GetRate();
   mTimeInfo.flags |= kVstTransportPlaying;

   // Turn the power on
   callDispatcher(effMainsChanged, 0, 1, NULL, 0.0);

   // Tell effect we're starting to process
   callDispatcher(effStartProcess, 0, 0, NULL, 0.0);

   // Actually perform the effect here
   sampleCount originalLen = len;
   sampleCount ls = lstart;
   sampleCount rs = rstart;
   while (len) {
      int block = mBlockSize;
      if (block > len) {
         block = len;
      }

      left->Get((samplePtr)mInBuffer[0], floatSample, ls, block);
      if (right) {
         right->Get((samplePtr)mInBuffer[1], floatSample, rs, block);
      }

      callProcessReplacing(mInBuffer, mOutBuffer, block);

      left->Set((samplePtr)mOutBuffer[0], floatSample, ls, block);
      if (right) {
         right->Set((samplePtr)mOutBuffer[1], floatSample, rs, block);
      }      

      len -= block;
      ls += block;
      rs += block;
      mTimeInfo.samplePos += ((double) block / mTimeInfo.sampleRate);

      if (mInputs > 1) {      
         if (TrackGroupProgress(count, (ls - lstart) / (double)originalLen)) {
            rc = false;
            break;
         }
      }
      else {
         if (TrackProgress(count, (ls - lstart) / (double)originalLen)) {
            rc = false;
            break;
         }
      }
   }

   // Tell effect we're done
   callDispatcher(effStopProcess, 0, 0, NULL, 0.0);

   // Turn the power off
   callDispatcher(effMainsChanged, 0, 0, NULL, 0.0);

   // No longer playing
   mTimeInfo.samplePos = 0.0;
   mTimeInfo.sampleRate = 44100.0;
   mTimeInfo.tempo = 120.0;
   mTimeInfo.timeSigNumerator = 4;
   mTimeInfo.timeSigDenominator = 4;
   mTimeInfo.flags = kVstTempoValid | kVstNanosValid;

   return rc;
}
Beispiel #24
0
bool EffectNoiseRemoval::ProcessOne(int count, WaveTrack * track,
                                    longSampleCount start, sampleCount len)
{
   bool retCode = true;
   sampleCount s = 0;
   sampleCount idealBlockLen = track->GetMaxBlockSize() * 4;

   if (idealBlockLen % windowSize != 0)
      idealBlockLen += (windowSize - (idealBlockLen % windowSize));
   
   float *buffer = new float[idealBlockLen];
   
   float *window1 = new float[windowSize];
   float *window2 = new float[windowSize];
   float *thisWindow = window1;
   float *lastWindow = window2;
   
   int i;
   
   for(i=0; i<windowSize; i++) {
      lastWindow[i] = 0;
      smoothing[i] = float(0.0);
   }
   
   while((s < len)&&((len-s)>(windowSize/2))) {
      sampleCount block = idealBlockLen;
      if (s + block > len)
         block = len - s;
      
      track->Get((samplePtr) buffer, floatSample, start + s, block);
      
      for(i=0; i<(block-windowSize/2); i+=windowSize/2) {
         int wcopy = windowSize;
         if (i + wcopy > block)
            wcopy = block - i;
         
         int j;
         for(j=0; j<wcopy; j++)
            thisWindow[j] = buffer[i+j];
         for(j=wcopy; j<windowSize; j++)
            thisWindow[j] = 0;
         
         if (mDoProfile)
            GetProfile(windowSize, thisWindow);
         else {
				//TIDY-ME: could we just test mLevel=<0 in CheckWhetherSkipEffect?
            if (mLevel > 0) { // Skip NoiseRemoval if zero ... may apply for CleanChain
            RemoveNoise(windowSize, thisWindow);
               for(j=0; j<windowSize/2; j++) {
               	buffer[i+j] = thisWindow[j] + lastWindow[windowSize/2 + j];
         		}
            }
         }
         
         float *tempP = thisWindow;
         thisWindow = lastWindow;
         lastWindow = tempP;
      }
      
      // Shift by half-a-window less than the block size we loaded
      // (so that the blocks properly overlap)
      block -= windowSize/2;

      if (!mDoProfile)
         track->Set((samplePtr) buffer, floatSample, start + s, block);
      
      s += block;
      
      if (TrackProgress(count, s / (double) len)) {
         retCode = false;
         break;
      }
   }
   delete[] buffer;
   delete[] window1;
   delete[] window2;
   
   return retCode;
}
Beispiel #25
0
// ProcessOne() takes a track, transforms it to bunch of buffer-blocks,
// and calls libsamplerate code on these blocks.
bool EffectChangeSpeed::ProcessOne(WaveTrack * track,
                           sampleCount start, sampleCount end)
{
   if (track == NULL)
      return false;

   // initialization, per examples of Mixer::Mixer and
   // EffectSoundTouch::ProcessOne

   WaveTrack * outputTrack = mFactory->NewWaveTrack(track->GetSampleFormat(),
                                                    track->GetRate());

   //Get the length of the selection (as double). len is
   //used simple to calculate a progress meter, so it is easier
   //to make it a double now than it is to do it later 
   double len = (double)(end - start);

   // Initiate processing buffers, most likely shorter than 
   // the length of the selection being processed.
   sampleCount inBufferSize = track->GetMaxBlockSize();

   float * inBuffer = new float[inBufferSize];

   sampleCount outBufferSize = 
      (sampleCount)((mFactor * inBufferSize) + 10);
   float * outBuffer = new float[outBufferSize]; 

   // Set up the resampling stuff for this track.
   Resample resample(true, mFactor, mFactor);

   //Go through the track one buffer at a time. samplePos counts which
   //sample the current buffer starts at.
   bool bResult = true;
   sampleCount blockSize;
   sampleCount samplePos = start;
   while (samplePos < end) {
      //Get a blockSize of samples (smaller than the size of the buffer)
      blockSize = track->GetBestBlockSize(samplePos);

      //Adjust the block size if it is the final block in the track
      if (samplePos + blockSize > end)
         blockSize = end - samplePos;

      //Get the samples from the track and put them in the buffer
      track->Get((samplePtr) inBuffer, floatSample, samplePos, blockSize);

      int inUsed;
      int outgen = resample.Process(mFactor,
                                    inBuffer,
                                    blockSize,
                                    ((samplePos + blockSize) >= end),
                                    &inUsed,
                                    outBuffer,
                                    outBufferSize);
      if (outgen < 0) {
         bResult = false;
         break;
      }

      if (outgen > 0)
         outputTrack->Append((samplePtr)outBuffer, floatSample, 
                             outgen);

      // Increment samplePos
      samplePos += inUsed;

      // Update the Progress meter
      if (TrackProgress(mCurTrackNum, (samplePos - start) / len)) {
         bResult = false;
         break;
      }
   }

   // Flush the output WaveTrack (since it's buffered, too)
   outputTrack->Flush();

   // Clean up the buffers
   delete [] inBuffer;
   delete [] outBuffer;

   // Take the output track and insert it in place of the original
   // sample data
   double newLength = outputTrack->GetEndTime(); 
   if (bResult) 
   {
      SetTimeWarper(new LinearTimeWarper(mCurT0, mCurT0, mCurT1, mCurT0 + newLength));
      bResult = track->ClearAndPaste(mCurT0, mCurT1, outputTrack, true, false, GetTimeWarper());
   }

   if (newLength > mMaxNewLength) 
      mMaxNewLength = newLength; 

   // Delete the outputTrack now that its data is inserted in place
   delete outputTrack;

   return bResult;
}
Beispiel #26
0
bool LV2Effect::ProcessStereo(int count,
                              WaveTrack *left,
                              WaveTrack *right,
                              sampleCount lstart, 
                              sampleCount rstart,
                              sampleCount len)
{
   /* Allocate buffers */
   if (mBlockSize == 0)
   {
      mBlockSize = left->GetMaxBlockSize() * 2;

      fInBuffer = new float *[mAudioInputs.GetCount()];
      for (size_t i = 0; i < mAudioInputs.GetCount(); i++)
      {
         fInBuffer[i] = new float[mBlockSize];
      }

      fOutBuffer = new float *[mAudioOutputs.GetCount()];
      for (size_t i = 0; i < mAudioOutputs.GetCount(); i++)
      {
         fOutBuffer[i] = new float[mBlockSize];
      }
   }

   /* Instantiate the plugin */
   LilvInstance *handle = lilv_plugin_instantiate(mData,
                                                  left->GetRate(), 
                                                  gLV2Features);
   if (!handle)
   {
      wxMessageBox(wxString::Format(_("Unable to load plug-in %s"), pluginName.c_str()));
      return false;
   }

   /* Write the Note On to the MIDI event buffer and connect it */
   LV2_Event_Buffer *midiBuffer = NULL;
   int noteOffTime;
   if (mMidiInput)
   {
      midiBuffer = lv2_event_buffer_new(40, 2);
      LV2_Event_Iterator iter;
      lv2_event_begin(&iter, midiBuffer);
      uint8_t noteOn[] = { 0x90, mNoteKey, mNoteVelocity };
      lv2_event_write(&iter, 0, 0, 1, 3, noteOn);
      noteOffTime = mNoteLength * left->GetRate();
      if (noteOffTime < len && noteOffTime < mBlockSize) {
         uint8_t noteOff[] = { 0x80, mNoteKey, 64 };
         lv2_event_write(&iter, noteOffTime, 0, 1, 3, noteOff);
      }
      lilv_instance_connect_port(handle, mMidiInput->mIndex, midiBuffer);
   }

   for (size_t p = 0; p < mAudioInputs.GetCount(); p++)
   {
      lilv_instance_connect_port(handle, mAudioInputs[p].mIndex, fInBuffer[p]);
   }

   for (size_t p = 0; p < mAudioOutputs.GetCount(); p++)
   {
      lilv_instance_connect_port(handle, mAudioOutputs[p].mIndex, fOutBuffer[p]);
   }

   for (size_t p = 0; p < mControlInputs.GetCount(); p++)
   {
      lilv_instance_connect_port(handle, mControlInputs[p].mIndex,
                                 &mControlInputs[p].mControlBuffer);
   }

   for (size_t p = 0; p < mControlOutputs.GetCount(); p++)
   {
      lilv_instance_connect_port(handle, mControlOutputs[p].mIndex, 
                                 &mControlOutputs[p].mControlBuffer);
   }

   float latency = 0.0;
   if (mLatencyPortIndex >= 0)
   {
      lilv_instance_connect_port(handle, mLatencyPortIndex, &latency);
   }

   lilv_instance_activate(handle);

   // Actually perform the effect here

   sampleCount originalLen = len;
   sampleCount ls = lstart;
   sampleCount rs = rstart;
   sampleCount ols = ls;
   sampleCount ors = rs;
   bool noteOver = false;

   sampleCount delayed = 0;
   sampleCount delay = 0;
   bool cleared = false;

   while (len || delayed)
   {
      int block = mBlockSize;

      if (len)
      {
         if (block > len)
         {
            block = len;
         }
   
         if (left &&  mAudioInputs.GetCount() > 0)
         {
            left->Get((samplePtr)fInBuffer[0], floatSample, ls, block);
         }
   
         if (right && mAudioInputs.GetCount() > 1)
         {
            right->Get((samplePtr)fInBuffer[1], floatSample, rs, block);
         }
      }
      else if (delayed)
      {
         // At the end if we don't have enough left for a whole block
         if (block > delayed)
         {
            block = delayed;
         }

         // Clear the input buffer so that we only pass zeros to the effect.
         if (!cleared)
         {
            for (int i = 0; i < mBlockSize; i++)
            {
               fInBuffer[0][i] = 0.0;
            }

            if (right)
            {
               memcpy(fInBuffer[1], fOutBuffer[0], mBlockSize);
            }
            cleared = true;
         }
      }

      lilv_instance_run(handle, block);

      if (delayed == 0 && latency != 0)
      {
         delayed = delay = latency;
      }

      if (delay >= block)
      {
         delay -= block;
      }
      else if (delay > 0)
      {
         sampleCount oblock = block - delay;
         if (left && mAudioOutputs.GetCount() > 0)
         {
            left->Set((samplePtr)(fOutBuffer[0] + delay), floatSample, ols, oblock);
         }
         
         if (right && mAudioOutputs.GetCount() > 1)
         {
            right->Set((samplePtr)(fOutBuffer[1] + delay), floatSample, ors, oblock);
         }
         ols += oblock;
         ors += oblock;
         delay = 0;
      }
      else
      {
         if (left && mAudioOutputs.GetCount() > 0)
         {
            left->Set((samplePtr)fOutBuffer[0], floatSample, ols, block);
         }
         
         if (right && mAudioOutputs.GetCount() > 1)
         {
            right->Set((samplePtr)fOutBuffer[1], floatSample, ors, block);
         }
         ols += block;
         ors += block;
      }

      if (len)
      {
         len -= block;
         noteOffTime -= block;

         // Clear the event buffer and add the note off event if needed
         if (mMidiInput)
         {
            lv2_event_buffer_reset(midiBuffer, 1, 
                                   (uint8_t *)midiBuffer + 
                                   sizeof(LV2_Event_Buffer));
   
            if (!noteOver && noteOffTime < len && noteOffTime < block)
            {
               LV2_Event_Iterator iter;
               lv2_event_begin(&iter, midiBuffer);
               uint8_t noteOff[] = { 0x80, mNoteKey, 64 };
               lv2_event_write(&iter, noteOffTime, 0, 1, 3, noteOff);
               noteOver = true;
            }
         }         
      }
      else if (delayed)
      {
         delayed -= block;
      }
      ls += block;
      rs += block;
      
      if (mAudioInputs.GetCount() > 1)
      {
         if (TrackGroupProgress(count, (ls-lstart)/(double)originalLen))
         {
            return false;
         }
      }
      else
      {
         if (TrackProgress(count, (ls-lstart)/(double)originalLen))
         {
            return false;
         }
      }
      
   }
   
   lilv_instance_deactivate(handle);
   lilv_instance_free(handle);
   
   return true;
}
Beispiel #27
0
//AnalyseDC() takes a track, transforms it to bunch of buffer-blocks,
//and executes AnalyzeData on it...
// sets mOffset
bool EffectNormalize::AnalyseDC(WaveTrack * track, wxString msg)
{
   bool rc = true;
   sampleCount s;

   mOffset = 0.0; // we might just return

   if(!mDC)  // don't do analysis if not doing dc removal
      return(rc);

   //Transform the marker timepoints to samples
   sampleCount start = track->TimeToLongSamples(mCurT0);
   sampleCount end = track->TimeToLongSamples(mCurT1);
         
   //Get the length of the buffer (as double). len is
   //used simply to calculate a progress meter, so it is easier
   //to make it a double now than it is to do it later 
   double len = (double)(end - start);

   //Initiate a processing buffer.  This buffer will (most likely)
   //be shorter than the length of the track being processed.
   float *buffer = new float[track->GetMaxBlockSize()];

   mSum = 0.0; // dc offset inits
   mCount = 0;

   //Go through the track one buffer at a time. s counts which
   //sample the current buffer starts at.
   s = start;
   while (s < end) {
      //Get a block of samples (smaller than the size of the buffer)
      sampleCount block = track->GetBestBlockSize(s);
      
      //Adjust the block size if it is the final block in the track
      if (s + block > end)
         block = end - s;
      
      //Get the samples from the track and put them in the buffer
      track->Get((samplePtr) buffer, floatSample, s, block);
      
      //Process the buffer.
      AnalyzeData(buffer, block);
         
      //Increment s one blockfull of samples
      s += block;
      
      //Update the Progress meter
		if (TrackProgress(mCurTrackNum, 
                        ((double)(s - start) / len)/2.0, msg)) {
         rc = false; //lda .. break, not return, so that buffer is deleted
         break;
      }
   }

   //Clean up the buffer
   delete[] buffer;

   mOffset = (float)(-mSum / mCount);  // calculate actual offset (amount that needs to be added on)

   //Return true because the effect processing succeeded ... unless cancelled
   return rc;
}
Beispiel #28
0
bool EffectNoise::Process()
{
   if (noiseDuration <= 0.0)
      noiseDuration = sDefaultGenerateLen;

   //Iterate over each track
   int ntrack = 0;
   this->CopyInputWaveTracks(); // Set up mOutputWaveTracks.
   bool bGoodResult = true;

   TrackListIterator iter(mOutputWaveTracks);
   WaveTrack *track = (WaveTrack *)iter.First();
   while (track) {
      WaveTrack *tmp = mFactory->NewWaveTrack(track->GetSampleFormat(), track->GetRate());
      numSamples = (longSampleCount)(noiseDuration * track->GetRate() + 0.5);
      longSampleCount i = 0;
      float *data = new float[tmp->GetMaxBlockSize()];
      sampleCount block;

      while ((i < numSamples) && bGoodResult) {
         block = tmp->GetBestBlockSize(i);
         if (block > (numSamples - i))
             block = numSamples - i;

         MakeNoise(data, block, track->GetRate(), noiseAmplitude);

         tmp->Append((samplePtr)data, floatSample, block);
         i += block;

         //Update the Progress meter
         if (TrackProgress(ntrack, (double)i / numSamples))
            bGoodResult = false;
      }
      delete[] data;

      tmp->Flush();
      track->Clear(mT0, mT1);
      track->Paste(mT0, tmp);
      delete tmp;

      if (!bGoodResult)
         break;

      //Iterate to the next track
      ntrack++;
      track = (WaveTrack *)iter.Next();
   }

   if (bGoodResult)
   {
      /*
         save last used values
         save duration unless value was got from selection, so we save only
         when user explicitely setup a value
      */
      if (mT1 == mT0)
         gPrefs->Write(wxT("/CsPresets/NoiseGen_Duration"), noiseDuration);

      gPrefs->Write(wxT("/CsPresets/NoiseGen_Type"), noiseType);
      gPrefs->Write(wxT("/CsPresets/NoiseGen_Amp"), noiseAmplitude);

      mT1 = mT0 + noiseDuration; // Update selection.
   }

   this->ReplaceProcessedWaveTracks(bGoodResult); 
   return bGoodResult;
}
Beispiel #29
0
bool EffectDtmf::GenerateTrack(WaveTrack *tmp,
                               const WaveTrack &track,
                               int ntrack)
{
   bool bGoodResult = true;

   // all dtmf sequence durations in samples from seconds
   numSamplesSequence = (sampleCount)(mDuration * track.GetRate() + 0.5);
   numSamplesTone = (sampleCount)(dtmfTone * track.GetRate() + 0.5);
   numSamplesSilence = (sampleCount)(dtmfSilence * track.GetRate() + 0.5);

   // recalculate the sum, and spread the difference - due to approximations.
   // Since diff should be in the order of "some" samples, a division (resulting in zero)
   // is not sufficient, so we add the additional remaining samples in each tone/silence block,
   // at least until available.
   int diff = numSamplesSequence - (dtmfNTones*numSamplesTone) - (dtmfNTones-1)*numSamplesSilence;
   if (diff>dtmfNTones) {
      // in this case, both these values would change, so it makes sense to recalculate diff
      // otherwise just keep the value we already have

      // should always be the case that dtmfNTones>1, as if 0, we don't even start processing,
      // and with 1 there is no difference to spread (no silence slot)...
      wxASSERT(dtmfNTones > 1);
      numSamplesTone += (diff/(dtmfNTones));
      numSamplesSilence += (diff/(dtmfNTones-1));
      diff = numSamplesSequence - (dtmfNTones*numSamplesTone) - (dtmfNTones-1)*numSamplesSilence;
   }
   // this var will be used as extra samples distributor
   int extra=0;

   sampleCount i = 0;
   sampleCount j = 0;
   int n=0; // pointer to string in dtmfString
   sampleCount block;
   bool isTone = true;
   float *data = new float[tmp->GetMaxBlockSize()];

   // for the whole dtmf sequence, we will be generating either tone or silence
   // according to a bool value, and this might be done in small chunks of size
   // 'block', as a single tone might sometimes be larger than the block
   // tone and silence generally have different duration, thus two generation blocks
   //
   // Note: to overcome a 'clicking' noise introduced by the abrupt transition from/to
   // silence, I added a fade in/out of 1/250th of a second (4ms). This can still be
   // tweaked but gives excellent results at 44.1kHz: I haven't tried other freqs.
   // A problem might be if the tone duration is very short (<10ms)... (?)
   //
   // One more problem is to deal with the approximations done when calculating the duration 
   // of both tone and silence: in some cases the final sum might not be same as the initial
   // duration. So, to overcome this, we had a redistribution block up, and now we will spread
   // the remaining samples in every bin in order to achieve the full duration: test case was
   // to generate an 11 tone DTMF sequence, in 4 seconds, and with DutyCycle=75%: after generation
   // you ended up with 3.999s or in other units: 3 seconds and 44097 samples.
   //
   while ((i < numSamplesSequence) && bGoodResult) {
      if (isTone)
         // generate tone
      {
         // the statement takes care of extracting one sample from the diff bin and
         // adding it into the tone block until depletion
         extra=(diff-- > 0?1:0);
         for(j=0; j < numSamplesTone+extra && bGoodResult; j+=block) {
            block = tmp->GetBestBlockSize(j);
            if (block > (numSamplesTone+extra - j))
               block = numSamplesTone+extra - j;

            // generate the tone and append
            MakeDtmfTone(data, block, track.GetRate(), dtmfString[n], j, numSamplesTone, dtmfAmplitude);
            tmp->Append((samplePtr)data, floatSample, block);
            //Update the Progress meter
            if (TrackProgress(ntrack, (double)(i+j) / numSamplesSequence))
               bGoodResult = false;
         }
         i += numSamplesTone;
         n++;
         if(n>=dtmfNTones)break;
      }
      else
         // generate silence
      {
         // the statement takes care of extracting one sample from the diff bin and
         // adding it into the silence block until depletion
         extra=(diff-- > 0?1:0);
         for(j=0; j < numSamplesSilence+extra && bGoodResult; j+=block) {
            block = tmp->GetBestBlockSize(j);
            if (block > (numSamplesSilence+extra - j))
               block = numSamplesSilence+extra - j;

            // generate silence and append
            memset(data, 0, sizeof(float)*block);
            tmp->Append((samplePtr)data, floatSample, block);
            //Update the Progress meter
            if (TrackProgress(ntrack, (double)(i+j) / numSamplesSequence))
               bGoodResult = false;
         }
         i += numSamplesSilence;
      }
      // flip flag
      isTone=!isTone;

   } // finished the whole dtmf sequence

   delete[] data;
   return bGoodResult;
}
Beispiel #30
0
bool EffectTruncSilence::Process()
{
   SelectedTrackListOfKindIterator iter(Track::Wave, mTracks);
   WaveTrack *t;
   double t0 = mT0;
   double t1 = mT1;
   int tndx; 
   int tcount = 0;
   int fr;

   // Init using first track
   t = (WaveTrack *) iter.First();
   double rate = t->GetRate();
   sampleCount blockLen = t->GetMaxBlockSize();

   // Get the left and right bounds for all tracks
   while (t) {
      // Make sure all tracks have the same sample rate
      if (rate != t->GetRate()) {
         wxMessageBox(_("All tracks must have the same sample rate"), _("Truncate Silence"));
         return false;
      }

      // Count the tracks
      tcount++;

      // Set the current bounds to whichever left marker is
      // greater and whichever right marker is less
      t0 = wxMax(mT0, t->GetStartTime());
      t1 = wxMin(mT1, t->GetEndTime());

      // Use the smallest block size of all the tracks
      blockLen = wxMin(blockLen, t->GetMaxBlockSize());

      // Iterate to the next track
      t = (WaveTrack*) iter.Next();
   }

   // Just a sanity check, really it should be much higher
   if(blockLen < 4*mBlendFrameCount)
      blockLen = 4*mBlendFrameCount;

   // Transform the marker timepoints to samples
   t = (WaveTrack *) iter.First();
   sampleCount start = t->TimeToLongSamples(t0);
   sampleCount end = t->TimeToLongSamples(t1);

   // Bigger buffers reduce 'reset'
   //blockLen *= 8;
   // Stress-test the logic for cutting samples through block endpoints
   //blockLen /= 8;

   // Set thresholds
   // We have a lower bound on the amount of silence we chop out at a time
   // to avoid chopping up low frequency sounds.  We're good down to 10Hz
   // if we use 100ms.
   const float minTruncMs = 1.0f;
   double truncDbSilenceThreshold = Enums::Db2Signal[mTruncDbChoiceIndex];
   int truncInitialAllowedSilentSamples = 
      int((wxMax( mTruncInitialAllowedSilentMs, minTruncMs) * rate) / 1000.0);
   int truncLongestAllowedSilentSamples = 
      int((wxMax( mTruncLongestAllowedSilentMs, minTruncMs) * rate) / 1000.0);

   // Require at least 4 samples for lengths
   if(truncInitialAllowedSilentSamples < 4)
      truncInitialAllowedSilentSamples = 4;
   if(truncLongestAllowedSilentSamples < 4)
      truncLongestAllowedSilentSamples = 4;

   // If the cross-fade is longer than the minimum length,
   // then limit the cross-fade length to the minimum length
   // This allows us to have reasonable cross-fade by default
   // and still allow for 1ms minimum lengths
   if(truncInitialAllowedSilentSamples < mBlendFrameCount)
      mBlendFrameCount = truncInitialAllowedSilentSamples;
   if(truncLongestAllowedSilentSamples < mBlendFrameCount)
      mBlendFrameCount = truncLongestAllowedSilentSamples;

   // For sake of efficiency, don't let blockLen be less than double the longest silent samples
   // up until a sane limit of 1Meg samples
   while((blockLen > 0) && (blockLen < truncLongestAllowedSilentSamples*2) && (blockLen < 1048576)) {
      blockLen *= 2;
   }
    // Don't allow either value to be more than half of the block length
   if(truncLongestAllowedSilentSamples > blockLen/2)
      truncLongestAllowedSilentSamples = blockLen/2;
   if(truncInitialAllowedSilentSamples > truncLongestAllowedSilentSamples)
      truncInitialAllowedSilentSamples = truncLongestAllowedSilentSamples;

   // We use the 'longest' variable as additive to the 'initial' variable
   truncLongestAllowedSilentSamples -= truncInitialAllowedSilentSamples;

   // Perform the crossfade half-way through the minimum removed silence duration
   int rampInFrames = (truncInitialAllowedSilentSamples + mBlendFrameCount) / 2;
   if(rampInFrames > truncInitialAllowedSilentSamples)
      rampInFrames = truncInitialAllowedSilentSamples;

   // Allocate buffers
   float **buffer = new float*[tcount];
   for (tndx = 0; tndx < tcount; tndx++) {
      buffer[tndx] = new float[blockLen];
   }

   // Start processing
   //Track::All is needed because this effect has clear functionality
   this->CopyInputTracks(Track::All); // Set up mOutputTracks.
   SelectedTrackListOfKindIterator iterOut(Track::Wave, mOutputTracks);

   sampleCount index = start;
   sampleCount outTrackOffset = start;
   bool cancelled = false;
   // Reset
   bool ignoringFrames = false;
   bool truncToMinimum = true;  // Ignore the initial samples until we get above the noise floor
   sampleCount consecutiveSilentFrames = 0;
   sampleCount truncIndex = 0;
   sampleCount i = 0;
   sampleCount keep;

   while (index < end) {

      // Limit size of current block if we've reached the end
      sampleCount count = blockLen-i;
      if ((index + count) > end) {
         count = end - index; 
      }

      // Fill the buffers
      tndx = 0;
      t = (WaveTrack *) iter.First();
      while (t) {
         t->Get((samplePtr)(buffer[tndx++]+i), floatSample, index, count);
         t = (WaveTrack *) iter.Next();
      }

      // Shift over to account for samples remaining from prior block
      sampleCount limit = count+i;

      // Look for silences in current block
      for ( ; i < limit; i++) {

         // Is current frame in all tracks below threshold
         bool below = true;
         for (tndx = 0; tndx < tcount; tndx++) {
            if (fabs(buffer[tndx][i]) >= truncDbSilenceThreshold) {
               below = false;
               break;
            }
         }
         // Make sure we cross-fade and output the last silence
         // so we get a smooth transition into whatever follows the selected region
         // Also set the 'truncToMinimum' flag so that the last silence is truncated to the minimum amount
         if(below && ((index+i+1) == end)) {
            below = false;
            truncToMinimum = true;
         }

         // Count frame if it's below threshold
         if (below) {
            consecutiveSilentFrames++;

            // Ignore this frame (equivalent to cutting it)
            // otherwise, keep sample to be part of allowed silence
            if (consecutiveSilentFrames > truncInitialAllowedSilentSamples) {
               ignoringFrames = true;
               continue;
            }
         }
         else {
            if (ignoringFrames == true) {
               // Scale the consectiveSilentFrames so we keep a silence duration
               // which is proportional to the original silence up to the limit
               keep = consecutiveSilentFrames - truncInitialAllowedSilentSamples;
               keep /= mSilenceCompressRatio;

               // The first and last samples always get truncated to the minimum amount
               if(truncToMinimum == true)
                  keep = 0;
               if(keep > truncLongestAllowedSilentSamples)
                  keep = truncLongestAllowedSilentSamples;
               if(keep < 0)
                  keep = 0;

               // Compute the location of the cross-fade to be halfway through the silence
               // with restriction to the samples we still have available to use
               rampInFrames = (truncInitialAllowedSilentSamples - keep + mBlendFrameCount) / 2;
               if(rampInFrames > truncInitialAllowedSilentSamples)
                  rampInFrames = truncInitialAllowedSilentSamples;
               if(rampInFrames < mBlendFrameCount)
                  rampInFrames = mBlendFrameCount;

               // Include the cross-fade samples in the count to make the loop logic easier
               keep += rampInFrames;
               truncIndex -= rampInFrames;

               // back up for cross-fade
               sampleCount curOffset = i - keep;

               if(curOffset < 0) {
                  // This should never happen, but just in case...
                  keep += curOffset - rampInFrames;
                  if(keep < mBlendFrameCount)
                     keep = mBlendFrameCount;
                  curOffset = 0;
               }
               if(truncIndex < 0) {
                  // This should never happen, but just in case...
                  truncIndex = 0;
               }

               for (tndx = 0; tndx < tcount; tndx++) {
                  // Cross fade the cut point
                  for (fr = 0; fr < mBlendFrameCount; fr++) {
                     buffer[tndx][truncIndex+fr] = ((mBlendFrameCount-fr)*buffer[tndx][truncIndex+fr] + fr*buffer[tndx][curOffset + fr]) / mBlendFrameCount;
                  }
                  // Append the 'keep' samples, if any
                  for ( ; fr < keep; fr++) {
                     buffer[tndx][truncIndex+fr] = buffer[tndx][curOffset + fr];
                  }
               }
               truncIndex += keep;
            }
            consecutiveSilentFrames = 0;
            ignoringFrames = false;
            truncToMinimum = false;
         }

         // Can get here either because > dbThreshold
         // or silence duration isn't longer than allowed
         for (tndx = 0; tndx < tcount; tndx++) {
            buffer[tndx][truncIndex] = buffer[tndx][i];
         }
         truncIndex++;
      }

      // Update tracks if any samples were removed, now or before
      if (outTrackOffset + truncIndex != index + limit) {
         // Put updated sample back into output tracks.
         tndx = 0;
         t = (WaveTrack *) iterOut.First();
         while (t) {
            t->Set((samplePtr)buffer[tndx++], floatSample, outTrackOffset, truncIndex);
            t = (WaveTrack *) iterOut.Next();
         }
      }

      // If currently in a silent section, retain samples for the next pass
      if(ignoringFrames) {
         keep = consecutiveSilentFrames - truncInitialAllowedSilentSamples;
         if(keep > (truncLongestAllowedSilentSamples+mBlendFrameCount))
            keep = truncLongestAllowedSilentSamples+mBlendFrameCount;
         for (tndx = 0; tndx < tcount; tndx++) {
            for(fr = 0; fr < truncInitialAllowedSilentSamples; fr++) {
               buffer[tndx][fr] = buffer[tndx][truncIndex-truncInitialAllowedSilentSamples+fr];
            }
            for(fr = 0; fr < keep; fr++) {
               buffer[tndx][truncInitialAllowedSilentSamples+fr] = buffer[tndx][i-keep+fr];
            }
         }
         // Update the output index, less what we are retaining for next time
         outTrackOffset += truncIndex - truncInitialAllowedSilentSamples;
         // Append the following buffer to the existing data
         i = consecutiveSilentFrames = truncInitialAllowedSilentSamples + keep;
         truncIndex = truncInitialAllowedSilentSamples;
      } else {
         // Maintain output index
         outTrackOffset += truncIndex;
         // Reset the buffer pointers to the beginning
         i = 0;
         truncIndex = 0;
         consecutiveSilentFrames = 0;
      }

      // Update progress and bail if user cancelled
      cancelled = TrackProgress(0, ((double)index / (double)end));
      if (cancelled) {
         break;
      }

      // Bump to next block
      index += count;
   }

   AudacityProject *p = GetActiveProject();
   if (!p)
      return false;

   // Remove stale data at end of output tracks.
   if (!cancelled && (outTrackOffset < end)) {
      t = (WaveTrack *) iterOut.First();
      if( p->IsSticky() )
         t->Clear(outTrackOffset / rate, t1, mOutputTracks);
      else
         while(t) {
            t->Clear(outTrackOffset / rate, t1, mOutputTracks);
            t = (WaveTrack *) iterOut.Next();
         }         

      t1 = outTrackOffset / rate;
   }

   // Free buffers
   for (tndx = 0; tndx < tcount; tndx++) {
      delete [] buffer[tndx];
   }
   delete [] buffer;

   mT0 = t0;
   mT1 = t1;

   this->ReplaceProcessedTracks(!cancelled); 
   return !cancelled;
}