Audacity  3.0.3
Classes | Public Member Functions | Private Member Functions | Private Attributes | List of all members
Mixer Class Reference

Functions for doing the mixdown of the tracks. More...

#include <Mix.h>

Collaboration diagram for Mixer:
[legend]

Classes

class  WarpOptions
 

Public Member Functions

 Mixer (const WaveTrackConstArray &inputTracks, bool mayThrow, const WarpOptions &warpOptions, double startTime, double stopTime, unsigned numOutChannels, size_t outBufferSize, bool outInterleaved, double outRate, sampleFormat outFormat, bool highQuality=true, MixerSpec *mixerSpec=nullptr, bool applytTrackGains=true)
 
virtual ~ Mixer ()
 
size_t Process (size_t maxSamples)
 
void Restart ()
 
void Reposition (double t, bool bSkipping=false)
 
void SetTimesAndSpeed (double t0, double t1, double speed, bool bSkipping=false)
 
void SetSpeedForPlayAtSpeed (double speed)
 
void SetSpeedForKeyboardScrubbing (double speed, double startTime)
 
double MixGetCurrentTime ()
 
constSamplePtr GetBuffer ()
 Retrieve the main buffer or the interleaved buffer. More...
 
constSamplePtr GetBuffer (int channel)
 Retrieve one of the non-interleaved buffers. More...
 

Private Member Functions

void Clear ()
 
size_t MixSameRate (int *channelFlags, WaveTrackCache &cache, sampleCount *pos)
 
size_t MixVariableRates (int *channelFlags, WaveTrackCache &cache, sampleCount *pos, float *queue, int *queueStart, int *queueLen, Resample *pResample)
 
void MakeResamplers ()
 

Private Attributes

const size_t mNumInputTracks
 
ArrayOf< WaveTrackCachemInputTrack
 
bool mbVariableRates
 
const BoundedEnvelopemEnvelope
 
ArrayOf< sampleCountmSamplePos
 
const bool mApplyTrackGains
 
Doubles mEnvValues
 
double mT0
 
double mT1
 
double mTime
 
ArrayOf< std::unique_ptr< Resample > > mResample
 
const size_t mQueueMaxLen
 
FloatBuffers mSampleQueue
 
ArrayOf< int > mQueueStart
 
ArrayOf< int > mQueueLen
 
size_t mProcessLen
 
MixerSpecmMixerSpec
 
size_t mMaxOut
 
const unsigned mNumChannels
 
Floats mGains
 
unsigned mNumBuffers
 
size_t mBufferSize
 
size_t mInterleavedBufferSize
 
const sampleFormat mFormat
 
bool mInterleaved
 
ArrayOf< SampleBuffermBuffer
 
ArrayOf< FloatsmTemp
 
Floats mFloatBuffer
 
const double mRate
 
double mSpeed
 
bool mHighQuality
 
std::vector< double > mMinFactor
 
std::vector< double > mMaxFactor
 
const bool mMayThrow
 

Detailed Description

Functions for doing the mixdown of the tracks.

Definition at line 76 of file Mix.h.

Constructor & Destructor Documentation

◆ Mixer()

Mixer::Mixer ( const WaveTrackConstArray inputTracks,
bool  mayThrow,
const WarpOptions warpOptions,
double  startTime,
double  stopTime,
unsigned  numOutChannels,
size_t  outBufferSize,
bool  outInterleaved,
double  outRate,
sampleFormat  outFormat,
bool  highQuality = true,
MixerSpec mixerSpec = nullptr,
bool  applytTrackGains = true 
)

Definition at line 237 of file Mix.cpp.

244  : mNumInputTracks { inputTracks.size() }
245 
246  , mApplyTrackGains{ applyTrackGains }
247 
248  // This is the number of samples grabbed in one go from a track
249  // and placed in a queue, when mixing with resampling.
250  // (Should we use WaveTrack::GetBestBlockSize instead?)
251  , mQueueMaxLen{ 65536 }
253 
254  , mNumChannels{ numOutChannels }
255  , mGains{ mNumChannels }
256 
257  , mFormat{ outFormat }
258  , mRate{ outRate }
259 
260  , mMayThrow{ mayThrow }
261 {
262  mHighQuality = highQuality;
264 
265  // mSamplePos holds for each track the next sample position not
266  // yet processed.
268  for(size_t i=0; i<mNumInputTracks; i++) {
269  mInputTrack[i].SetTrack(inputTracks[i]);
270  mSamplePos[i] = inputTracks[i]->TimeToLongSamples(startTime);
271  }
272  mEnvelope = warpOptions.envelope;
273  mT0 = startTime;
274  mT1 = stopTime;
275  mTime = startTime;
276  mBufferSize = outBufferSize;
277  mInterleaved = outInterleaved;
278  mSpeed = 1.0;
279  if( mixerSpec && mixerSpec->GetNumChannels() == mNumChannels &&
280  mixerSpec->GetNumTracks() == mNumInputTracks )
281  mMixerSpec = mixerSpec;
282  else
283  mMixerSpec = NULL;
284 
285  if (mInterleaved) {
286  mNumBuffers = 1;
288  }
289  else {
292  }
293 
295  mTemp.reinit(mNumBuffers);
296  for (unsigned int c = 0; c < mNumBuffers; c++) {
297  mBuffer[c].Allocate(mInterleavedBufferSize, mFormat);
298  mTemp[c].reinit(mInterleavedBufferSize);
299  }
300  // PRL: Bug2536: see other comments below
302 
303  // But cut the queue into blocks of this finer size
304  // for variable rate resampling. Each block is resampled at some
305  // constant rate.
306  mProcessLen = 1024;
307 
308  // Position in each queue of the start of the next block to resample.
310 
311  // For each queue, the number of available samples after the queue start.
314  mMinFactor.resize(mNumInputTracks);
315  mMaxFactor.resize(mNumInputTracks);
316  for (size_t i = 0; i<mNumInputTracks; i++) {
317  double factor = (mRate / mInputTrack[i].GetTrack()->GetRate());
318  if (mEnvelope) {
319  // variable rate resampling
320  mbVariableRates = true;
321  mMinFactor[i] = factor / mEnvelope->GetRangeUpper();
322  mMaxFactor[i] = factor / mEnvelope->GetRangeLower();
323  }
324  else if (warpOptions.minSpeed > 0.0 && warpOptions.maxSpeed > 0.0) {
325  // variable rate resampling
326  mbVariableRates = true;
327  mMinFactor[i] = factor / warpOptions.maxSpeed;
328  mMaxFactor[i] = factor / warpOptions.minSpeed;
329  }
330  else {
331  // constant rate resampling
332  mbVariableRates = false;
333  mMinFactor[i] = mMaxFactor[i] = factor;
334  }
335 
336  mQueueStart[i] = 0;
337  mQueueLen[i] = 0;
338  }
339 
340  MakeResamplers();
341 
342  const auto envLen = std::max(mQueueMaxLen, mInterleavedBufferSize);
343  mEnvValues.reinit(envLen);
344 }

◆ ~ Mixer()

virtual Mixer::~ Mixer ( )
virtual

Member Function Documentation

◆ Clear()

void Mixer::Clear ( )
private

Definition at line 356 of file Mix.cpp.

357 {
358  for (unsigned int c = 0; c < mNumBuffers; c++) {
359  memset(mTemp[c].get(), 0, mInterleavedBufferSize * sizeof(float));
360  }
361 }

References mInterleavedBufferSize, mNumBuffers, and mTemp.

Referenced by Process().

Here is the caller graph for this function:

◆ GetBuffer() [1/2]

constSamplePtr Mixer::GetBuffer ( )

Retrieve the main buffer or the interleaved buffer.

Definition at line 713 of file Mix.cpp.

714 {
715  return mBuffer[0].ptr();
716 }

References mBuffer.

◆ GetBuffer() [2/2]

constSamplePtr Mixer::GetBuffer ( int  channel)

Retrieve one of the non-interleaved buffers.

Definition at line 718 of file Mix.cpp.

719 {
720  return mBuffer[channel].ptr();
721 }

References mBuffer.

◆ MakeResamplers()

void Mixer::MakeResamplers ( )
private

Definition at line 350 of file Mix.cpp.

351 {
352  for (size_t i = 0; i < mNumInputTracks; i++)
353  mResample[i] = std::make_unique<Resample>(mHighQuality, mMinFactor[i], mMaxFactor[i]);
354 }

References mHighQuality, mMaxFactor, mMinFactor, mNumInputTracks, and mResample.

Referenced by Reposition(), and Restart().

Here is the caller graph for this function:

◆ MixGetCurrentTime()

double Mixer::MixGetCurrentTime ( )

Current time in seconds (unwarped, i.e. always between startTime and stopTime) This value is not accurate, it's useful for progress bars and indicators, but nothing else.

Definition at line 723 of file Mix.cpp.

724 {
725  return mTime;
726 }

References mTime.

◆ MixSameRate()

size_t Mixer::MixSameRate ( int *  channelFlags,
WaveTrackCache cache,
sampleCount pos 
)
private

Definition at line 565 of file Mix.cpp.

567 {
568  const WaveTrack *const track = cache.GetTrack().get();
569  const double t = ( *pos ).as_double() / track->GetRate();
570  const double trackEndTime = track->GetEndTime();
571  const double trackStartTime = track->GetStartTime();
572  const bool backwards = (mT1 < mT0);
573  const double tEnd = backwards
574  ? std::max(trackStartTime, mT1)
575  : std::min(trackEndTime, mT1);
576 
577  //don't process if we're at the end of the selection or track.
578  if ((backwards ? t <= tEnd : t >= tEnd))
579  return 0;
580  //if we're about to approach the end of the track or selection, figure out how much we need to grab
581  auto slen = limitSampleBufferSize(
582  mMaxOut,
583  // PRL: maybe t and tEnd should be given as sampleCount instead to
584  // avoid trouble subtracting one large value from another for a small
585  // difference
586  sampleCount{ (backwards ? t - tEnd : tEnd - t) * track->GetRate() + 0.5 }
587  );
588 
589  if (backwards) {
590  auto results = cache.GetFloats(*pos - (slen - 1), slen, mMayThrow);
591  if (results)
592  memcpy(mFloatBuffer.get(), results, sizeof(float) * slen);
593  else
594  memset(mFloatBuffer.get(), 0, sizeof(float) * slen);
595  track->GetEnvelopeValues(mEnvValues.get(), slen, t - (slen - 1) / mRate);
596  for(decltype(slen) i = 0; i < slen; i++)
597  mFloatBuffer[i] *= mEnvValues[i]; // Track gain control will go here?
599 
600  *pos -= slen;
601  }
602  else {
603  auto results = cache.GetFloats(*pos, slen, mMayThrow);
604  if (results)
605  memcpy(mFloatBuffer.get(), results, sizeof(float) * slen);
606  else
607  memset(mFloatBuffer.get(), 0, sizeof(float) * slen);
608  track->GetEnvelopeValues(mEnvValues.get(), slen, t);
609  for(decltype(slen) i = 0; i < slen; i++)
610  mFloatBuffer[i] *= mEnvValues[i]; // Track gain control will go here?
611 
612  *pos += slen;
613  }
614 
615  for(size_t c=0; c<mNumChannels; c++)
616  if (mApplyTrackGains)
617  mGains[c] = track->GetChannelGain(c);
618  else
619  mGains[c] = 1.0;
620 
621  MixBuffers(mNumChannels, channelFlags, mGains.get(),
622  mFloatBuffer.get(), mTemp.get(), slen, mInterleaved);
623 
624  return slen;
625 }

References floatSample, WaveTrack::GetChannelGain(), WaveTrack::GetEndTime(), WaveTrack::GetEnvelopeValues(), WaveTrackCache::GetFloats(), WaveTrack::GetRate(), WaveTrack::GetStartTime(), WaveTrackCache::GetTrack(), limitSampleBufferSize(), mApplyTrackGains, mEnvValues, mFloatBuffer, mGains, min(), mInterleaved, MixBuffers(), mMaxOut, mMayThrow, mNumChannels, mRate, mT0, mT1, mTemp, and ReverseSamples().

Referenced by Process().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ MixVariableRates()

size_t Mixer::MixVariableRates ( int *  channelFlags,
WaveTrackCache cache,
sampleCount pos,
float *  queue,
int *  queueStart,
int *  queueLen,
Resample pResample 
)
private

Definition at line 410 of file Mix.cpp.

414 {
415  const WaveTrack *const track = cache.GetTrack().get();
416  const double trackRate = track->GetRate();
417  const double initialWarp = mRate / mSpeed / trackRate;
418  const double tstep = 1.0 / trackRate;
419  auto sampleSize = SAMPLE_SIZE(floatSample);
420 
421  decltype(mMaxOut) out = 0;
422 
423  /* time is floating point. Sample rate is integer. The number of samples
424  * has to be integer, but the multiplication gives a float result, which we
425  * round to get an integer result. TODO: is this always right or can it be
426  * off by one sometimes? Can we not get this information directly from the
427  * clip (which must know) rather than convert the time?
428  *
429  * LLL: Not at this time. While WaveClips provide methods to retrieve the
430  * start and end sample, they do the same float->sampleCount conversion
431  * to calculate the position.
432  */
433 
434  // Find the last sample
435  double endTime = track->GetEndTime();
436  double startTime = track->GetStartTime();
437  const bool backwards = (mT1 < mT0);
438  const double tEnd = backwards
439  ? std::max(startTime, mT1)
440  : std::min(endTime, mT1);
441  const auto endPos = track->TimeToLongSamples(tEnd);
442  // Find the time corresponding to the start of the queue, for use with time track
443  double t = ((*pos).as_long_long() +
444  (backwards ? *queueLen : - *queueLen)) / trackRate;
445 
446  while (out < mMaxOut) {
447  if (*queueLen < (int)mProcessLen) {
448  // Shift pending portion to start of the buffer
449  memmove(queue, &queue[*queueStart], (*queueLen) * sampleSize);
450  *queueStart = 0;
451 
452  auto getLen = limitSampleBufferSize(
453  mQueueMaxLen - *queueLen,
454  backwards ? *pos - endPos : endPos - *pos
455  );
456 
457  // Nothing to do if past end of play interval
458  if (getLen > 0) {
459  if (backwards) {
460  auto results =
461  cache.GetFloats(*pos - (getLen - 1), getLen, mMayThrow);
462  if (results)
463  memcpy(&queue[*queueLen], results, sizeof(float) * getLen);
464  else
465  memset(&queue[*queueLen], 0, sizeof(float) * getLen);
466 
467  track->GetEnvelopeValues(mEnvValues.get(),
468  getLen,
469  (*pos - (getLen- 1)).as_double() / trackRate);
470  *pos -= getLen;
471  }
472  else {
473  auto results = cache.GetFloats(*pos, getLen, mMayThrow);
474  if (results)
475  memcpy(&queue[*queueLen], results, sizeof(float) * getLen);
476  else
477  memset(&queue[*queueLen], 0, sizeof(float) * getLen);
478 
479  track->GetEnvelopeValues(mEnvValues.get(),
480  getLen,
481  (*pos).as_double() / trackRate);
482 
483  *pos += getLen;
484  }
485 
486  for (decltype(getLen) i = 0; i < getLen; i++) {
487  queue[(*queueLen) + i] *= mEnvValues[i];
488  }
489 
490  if (backwards)
492  *queueLen, getLen);
493 
494  *queueLen += getLen;
495  }
496  }
497 
498  auto thisProcessLen = mProcessLen;
499  bool last = (*queueLen < (int)mProcessLen);
500  if (last) {
501  thisProcessLen = *queueLen;
502  }
503 
504  double factor = initialWarp;
505  if (mEnvelope)
506  {
507  //TODO-MB: The end time is wrong when the resampler doesn't use all input samples,
508  // as a result of this the warp factor may be slightly wrong, so AudioIO will stop too soon
509  // or too late (resulting in missing sound or inserted silence). This can't be fixed
510  // without changing the way the resampler works, because the number of input samples that will be used
511  // is unpredictable. Maybe it can be compensated later though.
512  if (backwards)
513  factor *= ComputeWarpFactor( *mEnvelope,
514  t - (double)thisProcessLen / trackRate + tstep, t + tstep);
515  else
516  factor *= ComputeWarpFactor( *mEnvelope,
517  t, t + (double)thisProcessLen / trackRate);
518  }
519 
520  auto results = pResample->Process(factor,
521  &queue[*queueStart],
522  thisProcessLen,
523  last,
524  // PRL: Bug2536: crash in soxr happened on Mac, sometimes, when
525  // mMaxOut - out == 1 and &mFloatBuffer[out + 1] was an unmapped
526  // address, because soxr, strangely, fetched an 8-byte (misaligned!)
527  // value from &mFloatBuffer[out], but did nothing with it anyway,
528  // in soxr_output_no_callback.
529  // Now we make the bug go away by allocating a little more space in
530  // the buffer than we need.
531  &mFloatBuffer[out],
532  mMaxOut - out);
533 
534  const auto input_used = results.first;
535  *queueStart += input_used;
536  *queueLen -= input_used;
537  out += results.second;
538  t += (input_used / trackRate) * (backwards ? -1 : 1);
539 
540  if (last) {
541  break;
542  }
543  }
544 
545  for (size_t c = 0; c < mNumChannels; c++) {
546  if (mApplyTrackGains) {
547  mGains[c] = track->GetChannelGain(c);
548  }
549  else {
550  mGains[c] = 1.0;
551  }
552  }
553 
555  channelFlags,
556  mGains.get(),
557  mFloatBuffer.get(),
558  mTemp.get(),
559  out,
560  mInterleaved);
561 
562  return out;
563 }

References anonymous_namespace{Mix.cpp}::ComputeWarpFactor(), floatSample, WaveTrack::GetChannelGain(), WaveTrack::GetEndTime(), WaveTrack::GetEnvelopeValues(), WaveTrackCache::GetFloats(), WaveTrack::GetRate(), WaveTrack::GetStartTime(), WaveTrackCache::GetTrack(), limitSampleBufferSize(), mApplyTrackGains, mEnvelope, mEnvValues, mFloatBuffer, mGains, min(), mInterleaved, MixBuffers(), mMaxOut, mMayThrow, mNumChannels, mProcessLen, mQueueMaxLen, mRate, mSpeed, mT0, mT1, mTemp, Resample::Process(), ReverseSamples(), SAMPLE_SIZE, and WaveTrack::TimeToLongSamples().

Referenced by Process().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Process()

size_t Mixer::Process ( size_t  maxSamples)

Process a maximum of 'maxSamples' samples and put them into a buffer which can be retrieved by calling GetBuffer(). Returns number of output samples, or 0, if there are no more samples that must be processed.

Definition at line 627 of file Mix.cpp.

628 {
629  // MB: this is wrong! mT represented warped time, and mTime is too inaccurate to use
630  // it here. It's also unnecessary I think.
631  //if (mT >= mT1)
632  // return 0;
633 
634  decltype(Process(0)) maxOut = 0;
635  ArrayOf<int> channelFlags{ mNumChannels };
636 
637  mMaxOut = maxToProcess;
638 
639  Clear();
640  for(size_t i=0; i<mNumInputTracks; i++) {
641  const WaveTrack *const track = mInputTrack[i].GetTrack().get();
642  for(size_t j=0; j<mNumChannels; j++)
643  channelFlags[j] = 0;
644 
645  if( mMixerSpec ) {
646  //ignore left and right when downmixing is not required
647  for(size_t j = 0; j < mNumChannels; j++ )
648  channelFlags[ j ] = mMixerSpec->mMap[ i ][ j ] ? 1 : 0;
649  }
650  else {
651  switch(track->GetChannel()) {
652  case Track::MonoChannel:
653  default:
654  for(size_t j=0; j<mNumChannels; j++)
655  channelFlags[j] = 1;
656  break;
657  case Track::LeftChannel:
658  channelFlags[0] = 1;
659  break;
660  case Track::RightChannel:
661  if (mNumChannels >= 2)
662  channelFlags[1] = 1;
663  else
664  channelFlags[0] = 1;
665  break;
666  }
667  }
668  if (mbVariableRates || track->GetRate() != mRate)
669  maxOut = std::max(maxOut,
670  MixVariableRates(channelFlags.get(), mInputTrack[i],
671  &mSamplePos[i], mSampleQueue[i].get(),
672  &mQueueStart[i], &mQueueLen[i], mResample[i].get()));
673  else
674  maxOut = std::max(maxOut,
675  MixSameRate(channelFlags.get(), mInputTrack[i], &mSamplePos[i]));
676 
677  double t = mSamplePos[i].as_double() / (double)track->GetRate();
678  if (mT0 > mT1)
679  // backwards (as possibly in scrubbing)
680  mTime = std::max(std::min(t, mTime), mT1);
681  else
682  // forwards (the usual)
683  mTime = std::min(std::max(t, mTime), mT1);
684  }
685  if(mInterleaved) {
686  for(size_t c=0; c<mNumChannels; c++) {
687  CopySamples((constSamplePtr)(mTemp[0].get() + c),
688  floatSample,
689  mBuffer[0].ptr() + (c * SAMPLE_SIZE(mFormat)),
690  mFormat,
691  maxOut,
693  mNumChannels,
694  mNumChannels);
695  }
696  }
697  else {
698  for(size_t c=0; c<mNumBuffers; c++) {
699  CopySamples((constSamplePtr)mTemp[c].get(),
700  floatSample,
701  mBuffer[c].ptr(),
702  mFormat,
703  maxOut,
705  }
706  }
707  // MB: this doesn't take warping into account, replaced with code based on mSamplePos
708  //mT += (maxOut / mRate);
709 
710  return maxOut;
711 }

References Clear(), CopySamples(), floatSample, WaveTrack::GetChannel(), WaveTrack::GetRate(), gHighQualityDither, gLowQualityDither, Track::LeftChannel, mBuffer, mbVariableRates, mFormat, mHighQuality, min(), mInputTrack, mInterleaved, MixSameRate(), MixVariableRates(), MixerSpec::mMap, mMaxOut, mMixerSpec, mNumBuffers, mNumChannels, mNumInputTracks, Track::MonoChannel, mQueueLen, mQueueStart, mRate, mResample, mSamplePos, mSampleQueue, mT0, mT1, mTemp, mTime, Track::RightChannel, and SAMPLE_SIZE.

Here is the call graph for this function:

◆ Reposition()

void Mixer::Reposition ( double  t,
bool  bSkipping = false 
)

Reposition processing to absolute time next time Process() is called.

Definition at line 746 of file Mix.cpp.

747 {
748  mTime = t;
749  const bool backwards = (mT1 < mT0);
750  if (backwards)
751  mTime = std::max(mT1, (std::min(mT0, mTime)));
752  else
753  mTime = std::max(mT0, (std::min(mT1, mTime)));
754 
755  for(size_t i=0; i<mNumInputTracks; i++) {
756  mSamplePos[i] = mInputTrack[i].GetTrack()->TimeToLongSamples(mTime);
757  mQueueStart[i] = 0;
758  mQueueLen[i] = 0;
759  }
760 
761  // Bug 2025: libsoxr 0.1.3, first used in Audacity 2.3.0, crashes with
762  // constant rate resampling if you try to reuse the resampler after it has
763  // flushed. Should that be considered a bug in sox? This works around it.
764  // (See also bug 1887, and the same work around in Mixer::Restart().)
765  if( bSkipping )
766  MakeResamplers();
767 }

References MakeResamplers(), min(), mInputTrack, mNumInputTracks, mQueueLen, mQueueStart, mSamplePos, mT0, mT1, and mTime.

Referenced by SetSpeedForKeyboardScrubbing(), and SetTimesAndSpeed().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Restart()

void Mixer::Restart ( )

Restart processing at beginning of buffer next time Process() is called.

Definition at line 728 of file Mix.cpp.

729 {
730  mTime = mT0;
731 
732  for(size_t i=0; i<mNumInputTracks; i++)
733  mSamplePos[i] = mInputTrack[i].GetTrack()->TimeToLongSamples(mT0);
734 
735  for(size_t i=0; i<mNumInputTracks; i++) {
736  mQueueStart[i] = 0;
737  mQueueLen[i] = 0;
738  }
739 
740  // Bug 1887: libsoxr 0.1.3, first used in Audacity 2.3.0, crashes with
741  // constant rate resampling if you try to reuse the resampler after it has
742  // flushed. Should that be considered a bug in sox? This works around it:
743  MakeResamplers();
744 }

References MakeResamplers(), mInputTrack, mNumInputTracks, mQueueLen, mQueueStart, mSamplePos, mT0, and mTime.

Here is the call graph for this function:

◆ SetSpeedForKeyboardScrubbing()

void Mixer::SetSpeedForKeyboardScrubbing ( double  speed,
double  startTime 
)

Definition at line 784 of file Mix.cpp.

785 {
786  wxASSERT(std::isfinite(speed));
787 
788  // Check if the direction has changed
789  if ((speed > 0.0 && mT1 < mT0) || (speed < 0.0 && mT1 > mT0)) {
790  // It's safe to use 0 and std::numeric_limits<double>::max(),
791  // because Mixer::MixVariableRates() doesn't sample past the start
792  // or end of the audio in a track.
793  if (speed > 0.0 && mT1 < mT0) {
794  mT0 = 0;
795  mT1 = std::numeric_limits<double>::max();
796  }
797  else {
798  mT0 = std::numeric_limits<double>::max();
799  mT1 = 0;
800  }
801 
802  Reposition(startTime, true);
803  }
804 
805  mSpeed = fabs(speed);
806 }

References mSpeed, mT0, mT1, and Reposition().

Here is the call graph for this function:

◆ SetSpeedForPlayAtSpeed()

void Mixer::SetSpeedForPlayAtSpeed ( double  speed)

Definition at line 778 of file Mix.cpp.

779 {
780  wxASSERT(std::isfinite(speed));
781  mSpeed = fabs(speed);
782 }

References mSpeed.

◆ SetTimesAndSpeed()

void Mixer::SetTimesAndSpeed ( double  t0,
double  t1,
double  speed,
bool  bSkipping = false 
)

Definition at line 769 of file Mix.cpp.

770 {
771  wxASSERT(std::isfinite(speed));
772  mT0 = t0;
773  mT1 = t1;
774  mSpeed = fabs(speed);
775  Reposition(t0, bSkipping);
776 }

References mSpeed, mT0, mT1, and Reposition().

Here is the call graph for this function:

Member Data Documentation

◆ mApplyTrackGains

const bool Mixer::mApplyTrackGains
private

Definition at line 167 of file Mix.h.

Referenced by MixSameRate(), and MixVariableRates().

◆ mBuffer

ArrayOf<SampleBuffer> Mixer::mBuffer
private

Definition at line 189 of file Mix.h.

Referenced by GetBuffer(), and Process().

◆ mBufferSize

size_t Mixer::mBufferSize
private

Definition at line 185 of file Mix.h.

◆ mbVariableRates

bool Mixer::mbVariableRates
private

Definition at line 164 of file Mix.h.

Referenced by Process().

◆ mEnvelope

const BoundedEnvelope* Mixer::mEnvelope
private

Definition at line 165 of file Mix.h.

Referenced by MixVariableRates().

◆ mEnvValues

Doubles Mixer::mEnvValues
private

Definition at line 168 of file Mix.h.

Referenced by MixSameRate(), and MixVariableRates().

◆ mFloatBuffer

Floats Mixer::mFloatBuffer
private

Definition at line 191 of file Mix.h.

Referenced by MixSameRate(), and MixVariableRates().

◆ mFormat

const sampleFormat Mixer::mFormat
private

Definition at line 187 of file Mix.h.

Referenced by Process().

◆ mGains

Floats Mixer::mGains
private

Definition at line 183 of file Mix.h.

Referenced by MixSameRate(), and MixVariableRates().

◆ mHighQuality

bool Mixer::mHighQuality
private

Definition at line 194 of file Mix.h.

Referenced by MakeResamplers(), and Process().

◆ mInputTrack

ArrayOf<WaveTrackCache> Mixer::mInputTrack
private

Definition at line 163 of file Mix.h.

Referenced by Process(), Reposition(), and Restart().

◆ mInterleaved

bool Mixer::mInterleaved
private

Definition at line 188 of file Mix.h.

Referenced by MixSameRate(), MixVariableRates(), and Process().

◆ mInterleavedBufferSize

size_t Mixer::mInterleavedBufferSize
private

Definition at line 186 of file Mix.h.

Referenced by Clear().

◆ mMaxFactor

std::vector<double> Mixer::mMaxFactor
private

Definition at line 195 of file Mix.h.

Referenced by MakeResamplers().

◆ mMaxOut

size_t Mixer::mMaxOut
private

Definition at line 181 of file Mix.h.

Referenced by MixSameRate(), MixVariableRates(), and Process().

◆ mMayThrow

const bool Mixer::mMayThrow
private

Definition at line 197 of file Mix.h.

Referenced by MixSameRate(), and MixVariableRates().

◆ mMinFactor

std::vector<double> Mixer::mMinFactor
private

Definition at line 195 of file Mix.h.

Referenced by MakeResamplers().

◆ mMixerSpec

MixerSpec* Mixer::mMixerSpec
private

Definition at line 178 of file Mix.h.

Referenced by Process().

◆ mNumBuffers

unsigned Mixer::mNumBuffers
private

Definition at line 184 of file Mix.h.

Referenced by Clear(), and Process().

◆ mNumChannels

const unsigned Mixer::mNumChannels
private

Definition at line 182 of file Mix.h.

Referenced by MixSameRate(), MixVariableRates(), and Process().

◆ mNumInputTracks

const size_t Mixer::mNumInputTracks
private

Definition at line 162 of file Mix.h.

Referenced by MakeResamplers(), Process(), Reposition(), and Restart().

◆ mProcessLen

size_t Mixer::mProcessLen
private

Definition at line 177 of file Mix.h.

Referenced by MixVariableRates().

◆ mQueueLen

ArrayOf<int> Mixer::mQueueLen
private

Definition at line 176 of file Mix.h.

Referenced by Process(), Reposition(), and Restart().

◆ mQueueMaxLen

const size_t Mixer::mQueueMaxLen
private

Definition at line 173 of file Mix.h.

Referenced by MixVariableRates().

◆ mQueueStart

ArrayOf<int> Mixer::mQueueStart
private

Definition at line 175 of file Mix.h.

Referenced by Process(), Reposition(), and Restart().

◆ mRate

const double Mixer::mRate
private

Definition at line 192 of file Mix.h.

Referenced by MixSameRate(), MixVariableRates(), and Process().

◆ mResample

ArrayOf<std::unique_ptr<Resample> > Mixer::mResample
private

Definition at line 172 of file Mix.h.

Referenced by MakeResamplers(), and Process().

◆ mSamplePos

ArrayOf<sampleCount> Mixer::mSamplePos
private

Definition at line 166 of file Mix.h.

Referenced by Process(), Reposition(), and Restart().

◆ mSampleQueue

FloatBuffers Mixer::mSampleQueue
private

Definition at line 174 of file Mix.h.

Referenced by Process().

◆ mSpeed

double Mixer::mSpeed
private

◆ mT0

double Mixer::mT0
private

◆ mT1

double Mixer::mT1
private

◆ mTemp

ArrayOf<Floats> Mixer::mTemp
private

Definition at line 190 of file Mix.h.

Referenced by Clear(), MixSameRate(), MixVariableRates(), and Process().

◆ mTime

double Mixer::mTime
private

Definition at line 171 of file Mix.h.

Referenced by MixGetCurrentTime(), Process(), Reposition(), and Restart().


The documentation for this class was generated from the following files:
Mixer::MixSameRate
size_t MixSameRate(int *channelFlags, WaveTrackCache &cache, sampleCount *pos)
Definition: Mix.cpp:565
Mixer::mSampleQueue
FloatBuffers mSampleQueue
Definition: Mix.h:174
WaveTrack
A Track that contains audio waveform data.
Definition: WaveTrack.h:69
Mixer::mInterleaved
bool mInterleaved
Definition: Mix.h:188
Mixer::mInputTrack
ArrayOf< WaveTrackCache > mInputTrack
Definition: Mix.h:163
Mixer::mMixerSpec
MixerSpec * mMixerSpec
Definition: Mix.h:178
Mixer::mFormat
const sampleFormat mFormat
Definition: Mix.h:187
Mixer::mBuffer
ArrayOf< SampleBuffer > mBuffer
Definition: Mix.h:189
Mixer::mMaxOut
size_t mMaxOut
Definition: Mix.h:181
WaveTrack::GetEnvelopeValues
void GetEnvelopeValues(double *buffer, size_t bufferLen, double t0) const
Definition: WaveTrack.cpp:2109
WaveTrack::GetEndTime
double GetEndTime() const override
Get the time at which the last clip in the track ends, plus recorded stuff.
Definition: WaveTrack.cpp:1887
Mixer::mEnvelope
const BoundedEnvelope * mEnvelope
Definition: Mix.h:165
Mixer::mRate
const double mRate
Definition: Mix.h:192
Mixer::mGains
Floats mGains
Definition: Mix.h:183
Mixer::Reposition
void Reposition(double t, bool bSkipping=false)
Definition: Mix.cpp:746
Mixer::mBufferSize
size_t mBufferSize
Definition: Mix.h:185
ArrayOf::reinit
void reinit(Integral count, bool initialize=false)
Definition: MemoryX.h:57
Mixer::MakeResamplers
void MakeResamplers()
Definition: Mix.cpp:350
Mixer::mEnvValues
Doubles mEnvValues
Definition: Mix.h:168
SAMPLE_SIZE
#define SAMPLE_SIZE(SampleFormat)
Definition: SampleFormat.h:44
ReverseSamples
void ReverseSamples(samplePtr dst, sampleFormat format, int start, int len)
Definition: SampleFormat.cpp:84
WaveTrackCache::GetFloats
const float * GetFloats(sampleCount start, size_t len, bool mayThrow)
Retrieve samples as floats from the track or from the memory cache.
Definition: WaveTrack.cpp:2635
floatSample
@ floatSample
Definition: SampleFormat.h:34
MixerSpec::mMap
ArraysOf< bool > mMap
Definition: Mix.h:61
CopySamples
void CopySamples(constSamplePtr src, sampleFormat srcFormat, samplePtr dst, sampleFormat dstFormat, size_t len, DitherType ditherType, unsigned int srcStride, unsigned int dstStride)
Copy samples from any format to any other format; apply dithering only if narrowing the format.
Definition: SampleFormat.cpp:111
Mixer::mFloatBuffer
Floats mFloatBuffer
Definition: Mix.h:191
constSamplePtr
const char * constSamplePtr
Definition: SampleFormat.h:50
Mixer::MixVariableRates
size_t MixVariableRates(int *channelFlags, WaveTrackCache &cache, sampleCount *pos, float *queue, int *queueStart, int *queueLen, Resample *pResample)
Definition: Mix.cpp:410
Mixer::mTime
double mTime
Definition: Mix.h:171
Mixer::mTemp
ArrayOf< Floats > mTemp
Definition: Mix.h:190
MixerSpec::GetNumTracks
unsigned GetNumTracks()
Definition: Mix.h:71
Mixer::mNumInputTracks
const size_t mNumInputTracks
Definition: Mix.h:162
Track::RightChannel
@ RightChannel
Definition: Track.h:277
Mixer::mSamplePos
ArrayOf< sampleCount > mSamplePos
Definition: Mix.h:166
Mixer::mT0
double mT0
Definition: Mix.h:169
WaveTrack::GetStartTime
double GetStartTime() const override
Get the time at which the first clip in the track starts.
Definition: WaveTrack.cpp:1867
Mixer::mMaxFactor
std::vector< double > mMaxFactor
Definition: Mix.h:195
Mixer::mT1
double mT1
Definition: Mix.h:170
BoundedEnvelope::GetRangeLower
double GetRangeLower() const
Definition: Envelope.h:288
Mixer::Clear
void Clear()
Definition: Mix.cpp:356
samplePtr
char * samplePtr
Definition: SampleFormat.h:49
min
int min(int a, int b)
Definition: CompareAudioCommand.cpp:106
Mixer::mQueueLen
ArrayOf< int > mQueueLen
Definition: Mix.h:176
WaveTrackCache::GetTrack
const std::shared_ptr< const WaveTrack > & GetTrack() const
Definition: WaveTrack.h:654
Mixer::mHighQuality
bool mHighQuality
Definition: Mix.h:194
MixBuffers
static void MixBuffers(unsigned numChannels, int *channelFlags, float *gains, const float *src, Floats *dests, int len, bool interleaved)
Definition: Mix.cpp:363
WaveTrack::TimeToLongSamples
sampleCount TimeToLongSamples(double t0) const
Convert correctly between an (absolute) time in seconds and a number of samples.
Definition: WaveTrack.cpp:1857
sampleCount
Positions or offsets within audio files need a wide type.
Definition: SampleCount.h:18
Mixer::mQueueMaxLen
const size_t mQueueMaxLen
Definition: Mix.h:173
Mixer::mResample
ArrayOf< std::unique_ptr< Resample > > mResample
Definition: Mix.h:172
Track::MonoChannel
@ MonoChannel
Definition: Track.h:278
Mixer::mSpeed
double mSpeed
Definition: Mix.h:193
gLowQualityDither
DitherType gLowQualityDither
Definition: SampleFormat.cpp:49
Mixer::mNumBuffers
unsigned mNumBuffers
Definition: Mix.h:184
Mixer::mNumChannels
const unsigned mNumChannels
Definition: Mix.h:182
Resample::Process
std::pair< size_t, size_t > Process(double factor, float *inBuffer, size_t inBufferLen, bool lastFlag, float *outBuffer, size_t outBufferLen)
Main processing function. Resamples from the input buffer to the output buffer.
Definition: Resample.cpp:88
gHighQualityDither
DitherType gHighQualityDither
Definition: SampleFormat.cpp:50
Mixer::mMinFactor
std::vector< double > mMinFactor
Definition: Mix.h:195
Mixer::mMayThrow
const bool mMayThrow
Definition: Mix.h:197
anonymous_namespace{Mix.cpp}::ComputeWarpFactor
double ComputeWarpFactor(const Envelope &env, double t0, double t1)
Compute the integral warp factor between two non-warped time points.
Definition: Mix.cpp:403
WaveTrack::GetChannelGain
float GetChannelGain(int channel) const
Definition: WaveTrack.cpp:505
Mixer::mApplyTrackGains
const bool mApplyTrackGains
Definition: Mix.h:167
MixerSpec::GetNumChannels
unsigned GetNumChannels()
Definition: Mix.h:68
limitSampleBufferSize
size_t limitSampleBufferSize(size_t bufferSize, sampleCount limit)
Definition: SampleCount.cpp:23
BoundedEnvelope::GetRangeUpper
double GetRangeUpper() const
Definition: Envelope.h:289
Track::LeftChannel
@ LeftChannel
Definition: Track.h:276
Mixer::mInterleavedBufferSize
size_t mInterleavedBufferSize
Definition: Mix.h:186
WaveTrack::GetChannel
ChannelType GetChannel() const override
Definition: WaveTrack.cpp:258
Mixer::mQueueStart
ArrayOf< int > mQueueStart
Definition: Mix.h:175
ArrayOf< float >
Mixer::mProcessLen
size_t mProcessLen
Definition: Mix.h:177
Mixer::Process
size_t Process(size_t maxSamples)
Definition: Mix.cpp:627
Mixer::mbVariableRates
bool mbVariableRates
Definition: Mix.h:164
WaveTrack::GetRate
double GetRate() const
Definition: WaveTrack.cpp:457