Esempio n. 1
0
sampleCount Mixer::MixSameRate(int *channelFlags, WaveTrack *track,
                               longSampleCount *pos)
{
   int slen = mMaxOut;
   int c;
   double t = *pos / track->GetRate();

   if (t + slen/track->GetRate() > mT1)
      slen = (int)((mT1 - t) * track->GetRate() + 0.5);
   
   if (slen <= 0)
      return 0;

   if (slen > mMaxOut)
      slen = mMaxOut;

   track->Get((samplePtr)mFloatBuffer, floatSample, *pos, slen);
   track->GetEnvelopeValues(mEnvValues, slen, t, 1.0 / mRate);
   for(int i=0; i<slen; i++)
      mFloatBuffer[i] *= mEnvValues[i]; // Track gain control will go here?
   
   for(c=0; c<mNumChannels; c++)
      if (mApplyTrackGains)
         mGains[c] = track->GetChannelGain(c);
      else
         mGains[c] = 1.0;

   MixBuffers(mNumChannels, channelFlags, mGains,
              (samplePtr)mFloatBuffer, mTemp, slen, mInterleaved);

   *pos += slen;

   return slen;
}
Esempio n. 2
0
sampleCount Mixer::MixSameRate(int *channelFlags, WaveTrack *track,
                               sampleCount *pos)
{
   int slen = mMaxOut;
   int c;
   const double t = *pos / track->GetRate();
   const double trackEndTime = track->GetEndTime();
   const double trackStartTime = track->GetStartTime();
   const bool backwards = (mT1 < mT0);
   const double tEnd = backwards
      ? std::max(trackStartTime, mT1)
      : std::min(trackEndTime, mT1);

   //don't process if we're at the end of the selection or track.
   if ((backwards ? t <= tEnd : t >= tEnd))
      return 0;
   //if we're about to approach the end of the track or selection, figure out how much we need to grab
   if (backwards) {
      if (t - slen/track->GetRate() < tEnd)
         slen = (int)((t - tEnd) * track->GetRate() + 0.5);
   }
   else {
      if (t + slen/track->GetRate() > tEnd)
         slen = (int)((tEnd - t) * track->GetRate() + 0.5);
   }

   if (slen > mMaxOut)
      slen = mMaxOut;

   if (backwards) {
      track->Get((samplePtr)mFloatBuffer, floatSample, *pos - (slen - 1), slen);
      track->GetEnvelopeValues(mEnvValues, slen, t - (slen - 1) / mRate, 1.0 / mRate);
      for(int i=0; i<slen; i++)
         mFloatBuffer[i] *= mEnvValues[i]; // Track gain control will go here?
      ReverseSamples((samplePtr)mFloatBuffer, floatSample, 0, slen);

      *pos -= slen;
   }
   else {
      track->Get((samplePtr)mFloatBuffer, floatSample, *pos, slen);
      track->GetEnvelopeValues(mEnvValues, slen, t, 1.0 / mRate);
      for(int i=0; i<slen; i++)
         mFloatBuffer[i] *= mEnvValues[i]; // Track gain control will go here?

      *pos += slen;
   }

   for(c=0; c<mNumChannels; c++)
      if (mApplyTrackGains)
         mGains[c] = track->GetChannelGain(c);
      else
         mGains[c] = 1.0;

   MixBuffers(mNumChannels, channelFlags, mGains,
              (samplePtr)mFloatBuffer, mTemp, slen, mInterleaved);

   return slen;
}
Esempio n. 3
0
sampleCount Mixer::MixSameRate(int *channelFlags, WaveTrack *track,
                               sampleCount *pos)
{
   int slen = mMaxOut;
   int c;
   double t = *pos / track->GetRate();
   double trackEndTime = track->GetEndTime();
   double tEnd = trackEndTime > mT1 ? mT1 : trackEndTime;

   //don't process if we're at the end of the selection or track.
   if (t>=tEnd)
      return 0;
   //if we're about to approach the end of the track or selection, figure out how much we need to grab 
   if (t + slen/track->GetRate() > tEnd)
      slen = (int)((tEnd - t) * track->GetRate() + 0.5);

   if (slen > mMaxOut)
      slen = mMaxOut;

   track->Get((samplePtr)mFloatBuffer, floatSample, *pos, slen);
   track->GetEnvelopeValues(mEnvValues, slen, t, 1.0 / mRate);
   for(int i=0; i<slen; i++)
      mFloatBuffer[i] *= mEnvValues[i]; // Track gain control will go here?
   
   for(c=0; c<mNumChannels; c++)
      if (mApplyTrackGains)
         mGains[c] = track->GetChannelGain(c);
      else
         mGains[c] = 1.0;

   MixBuffers(mNumChannels, channelFlags, mGains,
              (samplePtr)mFloatBuffer, mTemp, slen, mInterleaved);

   *pos += slen;

   return slen;
}
Esempio n. 4
0
sampleCount Mixer::MixVariableRates(int *channelFlags, WaveTrack *track,
                                    longSampleCount *pos, float *queue,
                                    int *queueStart, int *queueLen,
                                    Resample *SRC)
{
   double initialWarp = mRate / track->GetRate();
   double t = *pos / track->GetRate();
   int sampleSize = SAMPLE_SIZE(floatSample);
   int i, c;

   sampleCount out = 0;

   while(out < mMaxOut) {
      if (*queueLen < mProcessLen) {
         memmove(queue, &queue[*queueStart],
                 (*queueLen)*sampleSize);
         *queueStart = 0;

         int getLen = mQueueMaxLen - *queueLen;

         #if 0

         // TODO: fix this code so that extra silence isn't added
         // to the end of a track

         double trackTime = (*pos + getLen) / track->GetRate();
         if (trackTime > track->GetEndTime()) {
            getLen = (int)(0.5 + track->GetRate() *
                           (track->GetEndTime() -
                            ((*pos) / track->GetRate())));
         }
         #endif

         track->Get((samplePtr)&queue[*queueLen], floatSample,
                    *pos, getLen);

         track->GetEnvelopeValues(mEnvValues, getLen, (*pos) / track->GetRate(),
                                  1.0 / track->GetRate());

         for(i=0; i<getLen; i++)
            queue[(*queueLen)+i] *= mEnvValues[i];
         *queueLen += getLen;
         *pos += getLen;
      }

      sampleCount thisProcessLen = mProcessLen;
      if (*queueLen < mProcessLen)
         thisProcessLen = *queueLen;

      double factor = initialWarp;
      if (mTimeTrack) {
         double warpFactor = mTimeTrack->GetEnvelope()->GetValue(t);
         warpFactor = (mTimeTrack->GetRangeLower() * (1 - warpFactor) +
                       warpFactor * mTimeTrack->GetRangeUpper())/100.0;

         factor /= warpFactor;
      }

      int input_used;
      bool last = (*queueLen < mProcessLen);
      int outgen = SRC->Process(factor,
                                &queue[*queueStart],
                                thisProcessLen,
                                last,
                                &input_used,
                                &mFloatBuffer[out],
                                mMaxOut - out);

      if (outgen < 0)
         return 0;

      *queueStart += input_used;
      *queueLen -= input_used;
      out += outgen;
      t += (input_used / track->GetRate());

      if (last)
         break;
   }

   for(c=0; c<mNumChannels; c++)
      if (mApplyTrackGains)
         mGains[c] = track->GetChannelGain(c);
      else
         mGains[c] = 1.0;

   MixBuffers(mNumChannels, channelFlags, mGains,
              (samplePtr)mFloatBuffer, mTemp, mMaxOut, mInterleaved);

   return mMaxOut;
}
Esempio n. 5
0
sampleCount Mixer::MixVariableRates(int *channelFlags, WaveTrack *track,
                                    longSampleCount *pos, float *queue,
                                    int *queueStart, int *queueLen,
                                    Resample *SRC)
{
   double trackRate = track->GetRate();
   double initialWarp = mRate / trackRate;
   double t = *pos / trackRate;
   int sampleSize = SAMPLE_SIZE(floatSample);
   int i, c;

   sampleCount out = 0;

   // Find the last sample
   longSampleCount last = -1;
   WaveClipList::Node* it = track->GetClipIterator();
   while (it) {
      longSampleCount end = it->GetData()->GetEndSample();
      if (end > last) {
         last = end;
      }
      it = it->GetNext();
   }

   longSampleCount max = trackRate * mT1;
   if (last > max)
      last = max;

   while(out < mMaxOut) {
      if (*queueLen < mProcessLen) {
         memmove(queue, &queue[*queueStart], (*queueLen)*sampleSize);
         *queueStart = 0;

         int getLen = mQueueMaxLen - *queueLen;

         // Constrain
         if (*pos + getLen > last) {
            getLen = last - *pos;
         }

         // Nothing to do if past end of track
         if (getLen <= 0) {
            break;
         }

         track->Get((samplePtr)&queue[*queueLen], floatSample,
                    *pos, getLen);

         track->GetEnvelopeValues(mEnvValues, getLen, (*pos) / trackRate,
                                  1.0 / trackRate);

         for(i=0; i<getLen; i++)
            queue[(*queueLen)+i] *= mEnvValues[i];
         *queueLen += getLen;
         *pos += getLen;
      }

      sampleCount thisProcessLen = mProcessLen;
      if (*queueLen < mProcessLen)
         thisProcessLen = *queueLen;

      double factor = initialWarp;
      if (mTimeTrack) {
         double warpFactor = mTimeTrack->GetEnvelope()->GetValue(t);
         warpFactor = (mTimeTrack->GetRangeLower() * (1 - warpFactor) +
                       warpFactor * mTimeTrack->GetRangeUpper())/100.0;

         factor /= warpFactor;
      }

      int input_used;
      bool last = (*queueLen < mProcessLen);
      int outgen = SRC->Process(factor,
                                &queue[*queueStart],
                                thisProcessLen,
                                last,
                                &input_used,
                                &mFloatBuffer[out],
                                mMaxOut - out);

      if (outgen < 0)
         return 0;

      *queueStart += input_used;
      *queueLen -= input_used;
      out += outgen;
      t += (input_used / trackRate);

      if (last)
         break;
   }

   for(c=0; c<mNumChannels; c++)
      if (mApplyTrackGains)
         mGains[c] = track->GetChannelGain(c);
      else
         mGains[c] = 1.0;

   MixBuffers(mNumChannels, channelFlags, mGains,
              (samplePtr)mFloatBuffer, mTemp, out, mInterleaved);

   return out;
}
Esempio n. 6
0
sampleCount Mixer::MixVariableRates(int *channelFlags, WaveTrackCache &cache,
                                    sampleCount *pos, float *queue,
                                    int *queueStart, int *queueLen,
                                    Resample * pResample)
{
   const WaveTrack *const track = cache.GetTrack();
   const double trackRate = track->GetRate();
   const double initialWarp = mRate / mSpeed / trackRate;
   const double tstep = 1.0 / trackRate;
   int sampleSize = SAMPLE_SIZE(floatSample);

   sampleCount out = 0;

   /* time is floating point. Sample rate is integer. The number of samples
    * has to be integer, but the multiplication gives a float result, which we
    * round to get an integer result. TODO: is this always right or can it be
    * off by one sometimes? Can we not get this information directly from the
    * clip (which must know) rather than convert the time?
    *
    * LLL:  Not at this time.  While WaveClips provide methods to retrieve the
    *       start and end sample, they do the same float->sampleCount conversion
    *       to calculate the position.
    */

   // Find the last sample
   double endTime = track->GetEndTime();
   double startTime = track->GetStartTime();
   const bool backwards = (mT1 < mT0);
   const double tEnd = backwards
      ? std::max(startTime, mT1)
      : std::min(endTime, mT1);
   const sampleCount endPos = track->TimeToLongSamples(tEnd);
   // Find the time corresponding to the start of the queue, for use with time track
   double t = (*pos + (backwards ? *queueLen : - *queueLen)) / trackRate;

   while (out < mMaxOut) {
      if (*queueLen < mProcessLen) {
         // Shift pending portion to start of the buffer
         memmove(queue, &queue[*queueStart], (*queueLen) * sampleSize);
         *queueStart = 0;

         int getLen =
            std::min((backwards ? *pos - endPos : endPos - *pos),
                      sampleCount(mQueueMaxLen - *queueLen));

         // Nothing to do if past end of play interval
         if (getLen > 0) {
            if (backwards) {
               auto results = cache.Get(floatSample, *pos - (getLen - 1), getLen);
               memcpy(&queue[*queueLen], results, sizeof(float) * getLen);

               track->GetEnvelopeValues(mEnvValues,
                                        getLen,
                                        (*pos - (getLen- 1)) / trackRate,
                                        tstep);

               *pos -= getLen;
            }
            else {
               auto results = cache.Get(floatSample, *pos, getLen);
               memcpy(&queue[*queueLen], results, sizeof(float) * getLen);

               track->GetEnvelopeValues(mEnvValues,
                                        getLen,
                                        (*pos) / trackRate,
                                        tstep);

               *pos += getLen;
            }

            for (int i = 0; i < getLen; i++) {
               queue[(*queueLen) + i] *= mEnvValues[i];
            }

            if (backwards)
               ReverseSamples((samplePtr)&queue[0], floatSample,
                              *queueLen, getLen);

            *queueLen += getLen;
         }
      }

      sampleCount thisProcessLen = mProcessLen;
      bool last = (*queueLen < mProcessLen);
      if (last) {
         thisProcessLen = *queueLen;
      }

      double factor = initialWarp;
      if (mTimeTrack)
      {
         //TODO-MB: The end time is wrong when the resampler doesn't use all input samples,
         //         as a result of this the warp factor may be slightly wrong, so AudioIO will stop too soon
         //         or too late (resulting in missing sound or inserted silence). This can't be fixed
         //         without changing the way the resampler works, because the number of input samples that will be used
         //         is unpredictable. Maybe it can be compensated later though.
         if (backwards)
            factor *= mTimeTrack->ComputeWarpFactor
               (t - (double)thisProcessLen / trackRate + tstep, t + tstep);
         else
            factor *= mTimeTrack->ComputeWarpFactor
               (t, t + (double)thisProcessLen / trackRate);
      }

      int input_used;
      int outgen = pResample->Process(factor,
                                      &queue[*queueStart],
                                      thisProcessLen,
                                      last,
                                      &input_used,
                                      &mFloatBuffer[out],
                                      mMaxOut - out);

      if (outgen < 0) {
         return 0;
      }

      *queueStart += input_used;
      *queueLen -= input_used;
      out += outgen;
      t += ((backwards ? -input_used : input_used) / trackRate);

      if (last) {
         break;
      }
   }

   for (int c = 0; c < mNumChannels; c++) {
      if (mApplyTrackGains) {
         mGains[c] = track->GetChannelGain(c);
      }
      else {
         mGains[c] = 1.0;
      }
   }

   MixBuffers(mNumChannels,
              channelFlags,
              mGains,
              (samplePtr)mFloatBuffer,
              mTemp,
              out,
              mInterleaved);

   return out;
}
Esempio n. 7
0
sampleCount Mixer::MixVariableRates(int *channelFlags, WaveTrack *track,
                                    sampleCount *pos, float *queue,
                                    int *queueStart, int *queueLen,
                                    Resample * pResample)
{
   double trackRate = track->GetRate();
   double initialWarp = mRate / trackRate;
   double tstep = 1.0 / trackRate;
   double t = (*pos - *queueLen) / trackRate;
   int sampleSize = SAMPLE_SIZE(floatSample);

   sampleCount out = 0;

   /* time is floating point. Sample rate is integer. The number of samples
    * has to be integer, but the multiplication gives a float result, which we
    * round to get an integer result. TODO: is this always right or can it be
    * off by one sometimes? Can we not get this information directly from the
    * clip (which must know) rather than convert the time?
    *
    * LLL:  Not at this time.  While WaveClips provide methods to retrieve the
    *       start and end sample, they do the same float->sampleCount conversion
    *       to calculate the position.
    */

   // Find the last sample
   sampleCount endPos;
   double endTime = track->GetEndTime();
   if (endTime > mT1) {
      endPos = track->TimeToLongSamples(mT1);
   }
   else {
      endPos = track->TimeToLongSamples(endTime);
   }

   while (out < mMaxOut) {
      if (*queueLen < mProcessLen) {
         memmove(queue, &queue[*queueStart], (*queueLen) * sampleSize);
         *queueStart = 0;

         int getLen = mQueueMaxLen - *queueLen;

         // Constrain
         if (*pos + getLen > endPos) {
            getLen = endPos - *pos;
         }

         // Nothing to do if past end of track
         if (getLen > 0) {
            track->Get((samplePtr)&queue[*queueLen],
                       floatSample,
                       *pos,
                       getLen);

            track->GetEnvelopeValues(mEnvValues,
                                     getLen,
                                     (*pos) / trackRate,
                                     tstep);

            for (int i = 0; i < getLen; i++) {
               queue[(*queueLen) + i] *= mEnvValues[i];
            }

            *queueLen += getLen;
            *pos += getLen;
         }
      }

      sampleCount thisProcessLen = mProcessLen;
      bool last = (*queueLen < mProcessLen);
      if (last) {
         thisProcessLen = *queueLen;
      }

      double factor = initialWarp;
      if (mTimeTrack) 
      {
         //TODO-MB: The end time is wrong when the resampler doesn't use all input samples,
         //         as a result of this the warp factor may be slightly wrong, so AudioIO will stop too soon
         //         or too late (resulting in missing sound or inserted silence). This can't be fixed
         //         without changing the way the resampler works, because the number of input samples that will be used
         //         is unpredictable. Maybe it can be compensated lated though.
         factor *= mTimeTrack->ComputeWarpFactor(t, t + (double)thisProcessLen / trackRate);
      }

      int input_used;
      int outgen = pResample->Process(factor,
                                      &queue[*queueStart],
                                      thisProcessLen,
                                      last,
                                      &input_used,
                                      &mFloatBuffer[out],
                                      mMaxOut - out);

      if (outgen < 0) {
         return 0;
      }

      *queueStart += input_used;
      *queueLen -= input_used;
      out += outgen;
      t += (input_used / trackRate);

      if (last) {
         break;
      }
   }

   for (int c = 0; c < mNumChannels; c++) {
      if (mApplyTrackGains) {
         mGains[c] = track->GetChannelGain(c);
      }
      else {
         mGains[c] = 1.0;
      }
   }

   MixBuffers(mNumChannels,
              channelFlags,
              mGains,
              (samplePtr)mFloatBuffer,
              mTemp,
              out,
              mInterleaved);

   return out;
}