2010-01-23 19:44:49 +00:00
|
|
|
/**********************************************************************
|
|
|
|
|
|
|
|
Audacity: A Digital Audio Editor
|
|
|
|
|
|
|
|
Mix.h
|
|
|
|
|
|
|
|
Dominic Mazzoni
|
|
|
|
Markus Meyer
|
|
|
|
|
2017-11-09 18:32:29 +00:00
|
|
|
********************************************************************//**
|
|
|
|
|
|
|
|
\class ArrayOf
|
|
|
|
\brief Memory.h template class for making an array of float, bool, etc.
|
|
|
|
|
|
|
|
\class ArraysOf
|
|
|
|
\brief memory.h template class for making an array of arrays.
|
|
|
|
|
|
|
|
*//********************************************************************/
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
#ifndef __AUDACITY_MIX__
|
|
|
|
#define __AUDACITY_MIX__
|
|
|
|
|
|
|
|
#include "SampleFormat.h"
|
2017-08-24 15:44:36 +00:00
|
|
|
#include <vector>
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2016-05-15 15:06:51 +00:00
|
|
|
class Resample;
|
2010-01-23 19:44:49 +00:00
|
|
|
class DirManager;
|
2019-06-06 13:21:01 +00:00
|
|
|
class BoundedEnvelope;
|
2015-07-03 04:20:21 +00:00
|
|
|
class TrackFactory;
|
|
|
|
class TrackList;
|
|
|
|
class WaveTrack;
|
2017-08-24 15:44:36 +00:00
|
|
|
using WaveTrackConstArray = std::vector < std::shared_ptr < const WaveTrack > >;
|
2016-05-15 15:06:51 +00:00
|
|
|
class WaveTrackCache;
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2011-08-28 19:42:17 +00:00
|
|
|
/** @brief Mixes together all input tracks, applying any envelopes, amplitude
|
|
|
|
* gain, panning, and real-time effects in the process.
|
|
|
|
*
|
|
|
|
* Takes one or more tracks as input; of all the WaveTrack s that are selected,
|
|
|
|
* it mixes them together, applying any envelopes, amplitude gain, panning, and
|
|
|
|
* real-time effects in the process. The resulting pair of tracks (stereo) are
|
2014-06-03 20:30:19 +00:00
|
|
|
* "rendered" and have no effects, gain, panning, or envelopes. Other sorts of
|
2011-08-28 19:42:17 +00:00
|
|
|
* tracks are ignored.
|
2014-06-03 20:30:19 +00:00
|
|
|
* If the start and end times passed are the same this is taken as meaning
|
2011-08-28 19:42:17 +00:00
|
|
|
* no explicit time range to process, and the whole occupied length of the
|
|
|
|
* input tracks is processed.
|
|
|
|
*/
|
2016-03-31 03:24:39 +00:00
|
|
|
void MixAndRender(TrackList * tracks, TrackFactory *factory,
|
2010-01-23 19:44:49 +00:00
|
|
|
double rate, sampleFormat format,
|
2016-03-31 03:24:39 +00:00
|
|
|
double startTime, double endTime,
|
2018-11-19 04:07:05 +00:00
|
|
|
std::shared_ptr<WaveTrack> &uLeft,
|
|
|
|
std::shared_ptr<WaveTrack> &uRight);
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2016-09-02 19:53:09 +00:00
|
|
|
void MixBuffers(unsigned numChannels, int *channelFlags, float *gains,
|
2010-01-23 19:44:49 +00:00
|
|
|
samplePtr src,
|
|
|
|
samplePtr *dests, int len, bool interleaved);
|
|
|
|
|
|
|
|
class AUDACITY_DLL_API MixerSpec
|
|
|
|
{
|
2016-09-02 19:53:09 +00:00
|
|
|
unsigned mNumTracks, mNumChannels, mMaxNumChannels;
|
2014-06-03 20:30:19 +00:00
|
|
|
|
2010-01-23 19:44:49 +00:00
|
|
|
void Alloc();
|
|
|
|
|
2016-04-14 15:54:59 +00:00
|
|
|
public:
|
|
|
|
ArraysOf<bool> mMap;
|
2014-06-03 20:30:19 +00:00
|
|
|
|
2016-09-02 19:53:09 +00:00
|
|
|
MixerSpec( unsigned numTracks, unsigned maxNumChannels );
|
2010-01-23 19:44:49 +00:00
|
|
|
MixerSpec( const MixerSpec &mixerSpec );
|
|
|
|
virtual ~MixerSpec();
|
|
|
|
|
2016-09-02 19:53:09 +00:00
|
|
|
bool SetNumChannels( unsigned numChannels );
|
|
|
|
unsigned GetNumChannels() { return mNumChannels; }
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2016-09-02 19:53:09 +00:00
|
|
|
unsigned GetMaxNumChannels() { return mMaxNumChannels; }
|
|
|
|
unsigned GetNumTracks() { return mNumTracks; }
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
MixerSpec& operator=( const MixerSpec &mixerSpec );
|
|
|
|
};
|
|
|
|
|
|
|
|
class AUDACITY_DLL_API Mixer {
|
|
|
|
public:
|
2015-04-14 18:52:22 +00:00
|
|
|
|
|
|
|
// An argument to Mixer's constructor
|
|
|
|
class WarpOptions
|
|
|
|
{
|
|
|
|
public:
|
2019-06-06 13:21:01 +00:00
|
|
|
explicit WarpOptions(const BoundedEnvelope *e)
|
|
|
|
: envelope(e), minSpeed(0.0), maxSpeed(0.0)
|
2015-04-14 18:52:22 +00:00
|
|
|
{}
|
|
|
|
|
|
|
|
WarpOptions(double min, double max);
|
|
|
|
|
|
|
|
private:
|
|
|
|
friend class Mixer;
|
2019-06-06 13:21:01 +00:00
|
|
|
const BoundedEnvelope *envelope = nullptr;
|
2015-04-14 18:52:22 +00:00
|
|
|
double minSpeed, maxSpeed;
|
|
|
|
};
|
|
|
|
|
|
|
|
//
|
2010-01-23 19:44:49 +00:00
|
|
|
// Constructor / Destructor
|
|
|
|
//
|
|
|
|
|
2016-12-22 22:08:29 +00:00
|
|
|
Mixer(const WaveTrackConstArray &inputTracks, bool mayThrow,
|
2015-04-14 18:52:22 +00:00
|
|
|
const WarpOptions &warpOptions,
|
2010-01-23 19:44:49 +00:00
|
|
|
double startTime, double stopTime,
|
2016-09-06 13:19:27 +00:00
|
|
|
unsigned numOutChannels, size_t outBufferSize, bool outInterleaved,
|
2010-01-23 19:44:49 +00:00
|
|
|
double outRate, sampleFormat outFormat,
|
|
|
|
bool highQuality = true, MixerSpec *mixerSpec = NULL);
|
|
|
|
|
|
|
|
virtual ~ Mixer();
|
|
|
|
|
|
|
|
//
|
|
|
|
// Setup
|
|
|
|
//
|
|
|
|
|
|
|
|
void ApplyTrackGains(bool apply = true); // True by default
|
|
|
|
|
|
|
|
//
|
|
|
|
// Processing
|
|
|
|
//
|
|
|
|
|
|
|
|
/// 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.
|
2016-09-06 13:19:27 +00:00
|
|
|
size_t Process(size_t maxSamples);
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
/// Restart processing at beginning of buffer next time
|
|
|
|
/// Process() is called.
|
|
|
|
void Restart();
|
|
|
|
|
|
|
|
/// Reposition processing to absolute time next time
|
|
|
|
/// Process() is called.
|
2018-12-03 21:04:50 +00:00
|
|
|
void Reposition(double t, bool bSkipping = false);
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2015-04-17 01:31:10 +00:00
|
|
|
// Used in scrubbing.
|
|
|
|
void SetTimesAndSpeed(double t0, double t1, double speed);
|
Bug 1954: Clicks may occur starting/pausing play-at-speed or Scrub
Problem:
On Windows, after 50ms, there is a short period of roughly zero introduced into the output. On Linux, there is also a spike which sounds like a crackle.
In AudioIO::FillBuffers(), Mixer::SetTimesAndSpeed() is called, which sets mT0 and mT1 to a small interval.
In Mixer::MixVariableRates(), all the samples in the interval are used, which means the Resample::Process() is called with last equal to true.
So when Mixer::MixVariableRates() is called again, the resampler is being reused after a call to Process() in which last is true.
It is not stated in the soxr documentation if the resampler will produce valid results in this case, and it's only the scrubbing code which does this.
I think this is the problem, and so the partial fix below avoids this happening.
Partial fix for play-at-speed and keyboard scrubbing:
For these, there is no need to reset the values of mT0 and mT1. (There is no need to allow for the sample position being used to potentially jump around.)
So for these cases, Mixer::SetSpeed() is called, rather than Mixer::SetTimesAndSpeed().
2020-01-15 11:12:40 +00:00
|
|
|
void SetSpeed(double speed);
|
2015-04-17 01:31:10 +00:00
|
|
|
|
2012-12-19 21:49:25 +00:00
|
|
|
/// 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.
|
2010-01-23 19:44:49 +00:00
|
|
|
double MixGetCurrentTime();
|
|
|
|
|
|
|
|
/// Retrieve the main buffer or the interleaved buffer
|
|
|
|
samplePtr GetBuffer();
|
|
|
|
|
|
|
|
/// Retrieve one of the non-interleaved buffers
|
|
|
|
samplePtr GetBuffer(int channel);
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
void Clear();
|
2016-09-06 13:19:27 +00:00
|
|
|
size_t MixSameRate(int *channelFlags, WaveTrackCache &cache,
|
2010-01-23 19:44:49 +00:00
|
|
|
sampleCount *pos);
|
|
|
|
|
2016-09-06 13:19:27 +00:00
|
|
|
size_t MixVariableRates(int *channelFlags, WaveTrackCache &cache,
|
2010-01-23 19:44:49 +00:00
|
|
|
sampleCount *pos, float *queue,
|
|
|
|
int *queueStart, int *queueLen,
|
2012-11-04 04:44:10 +00:00
|
|
|
Resample * pResample);
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2018-06-11 18:05:00 +00:00
|
|
|
void MakeResamplers();
|
|
|
|
|
2010-01-23 19:44:49 +00:00
|
|
|
private:
|
2016-05-15 15:06:51 +00:00
|
|
|
|
2016-04-14 15:54:59 +00:00
|
|
|
// Input
|
|
|
|
size_t mNumInputTracks;
|
|
|
|
ArrayOf<WaveTrackCache> mInputTrack;
|
2015-04-14 18:52:22 +00:00
|
|
|
bool mbVariableRates;
|
2019-06-06 13:21:01 +00:00
|
|
|
const BoundedEnvelope *mEnvelope;
|
2016-04-14 15:54:59 +00:00
|
|
|
ArrayOf<sampleCount> mSamplePos;
|
2010-01-23 19:44:49 +00:00
|
|
|
bool mApplyTrackGains;
|
2016-04-14 15:54:59 +00:00
|
|
|
Doubles mEnvValues;
|
2010-01-23 19:44:49 +00:00
|
|
|
double mT0; // Start time
|
2014-06-03 20:30:19 +00:00
|
|
|
double mT1; // Stop time (none if mT0==mT1)
|
2012-12-19 21:49:25 +00:00
|
|
|
double mTime; // Current time (renamed from mT to mTime for consistency with AudioIO - mT represented warped time there)
|
2016-04-14 15:54:59 +00:00
|
|
|
ArrayOf<std::unique_ptr<Resample>> mResample;
|
2016-09-06 13:19:27 +00:00
|
|
|
size_t mQueueMaxLen;
|
2016-04-14 15:54:59 +00:00
|
|
|
FloatBuffers mSampleQueue;
|
|
|
|
ArrayOf<int> mQueueStart;
|
|
|
|
ArrayOf<int> mQueueLen;
|
2016-09-06 13:19:27 +00:00
|
|
|
size_t mProcessLen;
|
2010-01-23 19:44:49 +00:00
|
|
|
MixerSpec *mMixerSpec;
|
|
|
|
|
|
|
|
// Output
|
2016-09-06 13:19:27 +00:00
|
|
|
size_t mMaxOut;
|
2016-09-02 19:53:09 +00:00
|
|
|
unsigned mNumChannels;
|
2016-04-14 15:54:59 +00:00
|
|
|
Floats mGains;
|
2016-09-02 19:53:09 +00:00
|
|
|
unsigned mNumBuffers;
|
2016-09-06 13:19:27 +00:00
|
|
|
size_t mBufferSize;
|
|
|
|
size_t mInterleavedBufferSize;
|
2010-01-23 19:44:49 +00:00
|
|
|
sampleFormat mFormat;
|
|
|
|
bool mInterleaved;
|
2016-04-14 15:54:59 +00:00
|
|
|
ArrayOf<SampleBuffer> mBuffer, mTemp;
|
|
|
|
Floats mFloatBuffer;
|
2010-01-23 19:44:49 +00:00
|
|
|
double mRate;
|
2015-04-17 01:31:10 +00:00
|
|
|
double mSpeed;
|
2013-09-16 02:32:43 +00:00
|
|
|
bool mHighQuality;
|
2018-06-11 18:05:00 +00:00
|
|
|
std::vector<double> mMinFactor, mMaxFactor;
|
2016-12-22 22:08:29 +00:00
|
|
|
|
|
|
|
bool mMayThrow;
|
2010-01-23 19:44:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|