mirror of
https://github.com/cookiengineer/audacity
synced 2025-07-31 16:09:28 +02:00
Don't pass whole TimeTrack to Ruler or Mixer...
... they need only the information in a (Bounded)Envelope.
This commit is contained in:
parent
5ae606cf53
commit
46bf5a82fc
@ -1626,7 +1626,7 @@ void AdornedRulerPanel::StartQPPlay(bool looped, bool cutPreview)
|
||||
if (!cutPreview)
|
||||
options.pStartTime = &oldStart;
|
||||
else
|
||||
options.timeTrack = NULL;
|
||||
options.envelope = nullptr;
|
||||
|
||||
auto mode =
|
||||
cutPreview ? PlayMode::cutPreviewPlay
|
||||
|
@ -409,7 +409,7 @@ callbacks for these events.
|
||||
|
||||
\class AudioIOStartStreamOptions
|
||||
\brief struct holding stream options, including a pointer to the
|
||||
TimeTrack and AudioIOListener and whether the playback is looped.
|
||||
time warp info and AudioIOListener and whether the playback is looped.
|
||||
|
||||
*//*******************************************************************/
|
||||
|
||||
@ -458,7 +458,7 @@ TimeTrack and AudioIOListener and whether the playback is looped.
|
||||
#include "Prefs.h"
|
||||
#include "Project.h"
|
||||
#include "ProjectWindow.h"
|
||||
#include "TimeTrack.h"
|
||||
#include "Envelope.h"
|
||||
#include "WaveTrack.h"
|
||||
#include "AutoRecovery.h"
|
||||
|
||||
@ -2143,7 +2143,7 @@ bool AudioIO::AllocateBuffers(
|
||||
ScrubbingOptions::MaxAllowedScrubSpeed())
|
||||
:
|
||||
#endif
|
||||
Mixer::WarpOptions(mPlaybackSchedule.mTimeTrack);
|
||||
Mixer::WarpOptions(mPlaybackSchedule.mEnvelope);
|
||||
|
||||
mPlaybackQueueMinimum = mPlaybackSamplesToCopy;
|
||||
if (scrubbing)
|
||||
@ -2806,9 +2806,9 @@ void AudioIO::PlaybackSchedule::Init(
|
||||
// the existing audio. (Unless we figured out the inverse warp of the
|
||||
// captured samples in real time.)
|
||||
// So just quietly ignore the time track.
|
||||
mTimeTrack = nullptr;
|
||||
mEnvelope = nullptr;
|
||||
else
|
||||
mTimeTrack = options.timeTrack;
|
||||
mEnvelope = options.envelope;
|
||||
|
||||
mT0 = t0;
|
||||
if (pRecordingSchedule)
|
||||
@ -2838,7 +2838,7 @@ void AudioIO::PlaybackSchedule::Init(
|
||||
const auto &scrubOptions = *options.pScrubbingOptions;
|
||||
if (pRecordingSchedule ||
|
||||
Looping() ||
|
||||
mTimeTrack != NULL ||
|
||||
mEnvelope ||
|
||||
scrubOptions.maxSpeed < ScrubbingOptions::MinAllowedScrubSpeed()) {
|
||||
wxASSERT(false);
|
||||
scrubbing = false;
|
||||
@ -4173,7 +4173,7 @@ static Alg_update gAllNotesOff; // special event for loop ending
|
||||
double AudioIO::UncorrectedMidiEventTime()
|
||||
{
|
||||
double time;
|
||||
if (mPlaybackSchedule.mTimeTrack)
|
||||
if (mPlaybackSchedule.mEnvelope)
|
||||
time =
|
||||
mPlaybackSchedule.RealDuration(mNextEventTime - MidiLoopOffset())
|
||||
+ mPlaybackSchedule.mT0 + (mMidiLoopPasses *
|
||||
@ -5633,6 +5633,35 @@ bool AudioIO::PlaybackSchedule::Overruns( double trackTime ) const
|
||||
return (ReversedTime() ? trackTime <= mT1 : trackTime >= mT1);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
/** @brief Compute the duration (in seconds at playback) of the specified region of the track.
|
||||
*
|
||||
* Takes a region of the time track (specified by the unwarped time points in the project), and
|
||||
* calculates how long it will actually take to play this region back, taking the time track's
|
||||
* warping effects into account.
|
||||
* @param t0 unwarped time to start calculation from
|
||||
* @param t1 unwarped time to stop calculation at
|
||||
* @return the warped duration in seconds
|
||||
*/
|
||||
double ComputeWarpedLength(const Envelope &env, double t0, double t1)
|
||||
{
|
||||
return env.IntegralOfInverse(t0, t1);
|
||||
}
|
||||
|
||||
/** @brief Compute how much unwarped time must have elapsed if length seconds of warped time has
|
||||
* elapsed
|
||||
*
|
||||
* @param t0 The unwarped time (seconds from project start) at which to start
|
||||
* @param length How many seconds of warped time went past.
|
||||
* @return The end point (in seconds from project start) as unwarped time
|
||||
*/
|
||||
double SolveWarpedLength(const Envelope &env, double t0, double length)
|
||||
{
|
||||
return env.SolveIntegralOfInverse(t0, length);
|
||||
}
|
||||
}
|
||||
|
||||
double AudioIO::PlaybackSchedule::AdvancedTrackTime(
|
||||
double time, double realElapsed, double speed ) const
|
||||
{
|
||||
@ -5643,7 +5672,7 @@ double AudioIO::PlaybackSchedule::AdvancedTrackTime(
|
||||
if ( fabs(mT0 - mT1) < 1e-9 )
|
||||
return mT0;
|
||||
|
||||
if (mTimeTrack) {
|
||||
if (mEnvelope) {
|
||||
wxASSERT( speed == 1.0 );
|
||||
|
||||
double total=0.0;
|
||||
@ -5654,7 +5683,7 @@ double AudioIO::PlaybackSchedule::AdvancedTrackTime(
|
||||
// Avoid SolveWarpedLength
|
||||
time = mT1;
|
||||
else
|
||||
time = mTimeTrack->SolveWarpedLength(time, realElapsed);
|
||||
time = SolveWarpedLength(*mEnvelope, time, realElapsed);
|
||||
|
||||
if (!Looping() || !Overruns( time ))
|
||||
break;
|
||||
@ -5666,7 +5695,7 @@ double AudioIO::PlaybackSchedule::AdvancedTrackTime(
|
||||
// Avoid integrating again
|
||||
delta = total;
|
||||
else {
|
||||
delta = mTimeTrack->ComputeWarpedLength(oldTime, mT1);
|
||||
delta = ComputeWarpedLength(*mEnvelope, oldTime, mT1);
|
||||
if (oldTime == mT0)
|
||||
foundTotal = true, total = delta;
|
||||
}
|
||||
@ -5762,8 +5791,8 @@ double AudioIO::TimeQueue::Consumer( size_t nSamples, double rate )
|
||||
|
||||
double AudioIO::PlaybackSchedule::TrackDuration(double realElapsed) const
|
||||
{
|
||||
if (mTimeTrack)
|
||||
return mTimeTrack->SolveWarpedLength(mT0, realElapsed);
|
||||
if (mEnvelope)
|
||||
return SolveWarpedLength(*mEnvelope, mT0, realElapsed);
|
||||
else
|
||||
return realElapsed;
|
||||
}
|
||||
@ -5771,8 +5800,8 @@ double AudioIO::PlaybackSchedule::TrackDuration(double realElapsed) const
|
||||
double AudioIO::PlaybackSchedule::RealDuration(double trackTime1) const
|
||||
{
|
||||
double duration;
|
||||
if (mTimeTrack)
|
||||
duration = mTimeTrack->ComputeWarpedLength(mT0, trackTime1);
|
||||
if (mEnvelope)
|
||||
duration = ComputeWarpedLength(*mEnvelope, mT0, trackTime1);
|
||||
else
|
||||
duration = trackTime1 - mT0;
|
||||
return fabs(duration);
|
||||
|
@ -57,7 +57,7 @@ class AudioIO;
|
||||
class RingBuffer;
|
||||
class Mixer;
|
||||
class Resample;
|
||||
class TimeTrack;
|
||||
class BoundedEnvelope;
|
||||
class AudioThread;
|
||||
class MeterPanel;
|
||||
class SelectedRegion;
|
||||
@ -118,7 +118,7 @@ struct AudioIOStartStreamOptions
|
||||
explicit
|
||||
AudioIOStartStreamOptions(AudacityProject *pProject_, double rate_)
|
||||
: pProject{ pProject_ }
|
||||
, timeTrack(NULL)
|
||||
, envelope(nullptr)
|
||||
, listener(NULL)
|
||||
, rate(rate_)
|
||||
, playLooped(false)
|
||||
@ -130,7 +130,7 @@ struct AudioIOStartStreamOptions
|
||||
|
||||
AudacityProject *pProject{};
|
||||
MeterPanel *captureMeter{}, *playbackMeter{};
|
||||
TimeTrack *timeTrack;
|
||||
BoundedEnvelope *envelope; // for time warping
|
||||
AudioIOListener* listener;
|
||||
double rate;
|
||||
bool playLooped;
|
||||
@ -668,7 +668,7 @@ protected:
|
||||
// with ComputeWarpedLength, it is now possible the calculate the warped length with 100% accuracy
|
||||
// (ignoring accumulated rounding errors during playback) which fixes the 'missing sound at the end' bug
|
||||
|
||||
const TimeTrack *mTimeTrack;
|
||||
const BoundedEnvelope *mEnvelope;
|
||||
|
||||
volatile enum {
|
||||
PLAY_STRAIGHT,
|
||||
|
44
src/Mix.cpp
44
src/Mix.cpp
@ -31,6 +31,7 @@
|
||||
#include <wx/timer.h>
|
||||
#include <wx/intl.h>
|
||||
|
||||
#include "Envelope.h"
|
||||
#include "WaveTrack.h"
|
||||
#include "Prefs.h"
|
||||
#include "Resample.h"
|
||||
@ -143,10 +144,11 @@ void MixAndRender(TrackList *tracks, TrackFactory *trackFactory,
|
||||
endTime = mixEndTime;
|
||||
}
|
||||
|
||||
auto timeTrack = tracks->GetTimeTrack();
|
||||
Mixer mixer(waveArray,
|
||||
// Throw to abort mix-and-render if read fails:
|
||||
true,
|
||||
Mixer::WarpOptions(tracks->GetTimeTrack()),
|
||||
Mixer::WarpOptions(timeTrack ? timeTrack->GetEnvelope() : nullptr),
|
||||
startTime, endTime, mono ? 1 : 2, maxBlockLen, false,
|
||||
rate, format);
|
||||
|
||||
@ -204,7 +206,7 @@ void MixAndRender(TrackList *tracks, TrackFactory *trackFactory,
|
||||
}
|
||||
|
||||
Mixer::WarpOptions::WarpOptions(double min, double max)
|
||||
: timeTrack(0), minSpeed(min), maxSpeed(max)
|
||||
: minSpeed(min), maxSpeed(max)
|
||||
{
|
||||
if (minSpeed < 0)
|
||||
{
|
||||
@ -253,7 +255,7 @@ Mixer::Mixer(const WaveTrackConstArray &inputTracks,
|
||||
mInputTrack[i].SetTrack(inputTracks[i]);
|
||||
mSamplePos[i] = inputTracks[i]->TimeToLongSamples(startTime);
|
||||
}
|
||||
mTimeTrack = warpOptions.timeTrack;
|
||||
mEnvelope = warpOptions.envelope;
|
||||
mT0 = startTime;
|
||||
mT1 = stopTime;
|
||||
mTime = startTime;
|
||||
@ -301,11 +303,11 @@ Mixer::Mixer(const WaveTrackConstArray &inputTracks,
|
||||
mMaxFactor.resize(mNumInputTracks);
|
||||
for (size_t i = 0; i<mNumInputTracks; i++) {
|
||||
double factor = (mRate / mInputTrack[i].GetTrack()->GetRate());
|
||||
if (mTimeTrack) {
|
||||
if (mEnvelope) {
|
||||
// variable rate resampling
|
||||
mbVariableRates = true;
|
||||
mMinFactor[i] = factor / mTimeTrack->GetRangeUpper();
|
||||
mMaxFactor[i] = factor / mTimeTrack->GetRangeLower();
|
||||
mMinFactor[i] = factor / mEnvelope->GetRangeUpper();
|
||||
mMaxFactor[i] = factor / mEnvelope->GetRangeLower();
|
||||
}
|
||||
else if (warpOptions.minSpeed > 0.0 && warpOptions.maxSpeed > 0.0) {
|
||||
// variable rate resampling
|
||||
@ -380,6 +382,26 @@ void MixBuffers(unsigned numChannels, int *channelFlags, float *gains,
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
//Note: The meaning of this function has changed (December 2012)
|
||||
//Previously this function did something that was close to the opposite (but not entirely accurate).
|
||||
/** @brief Compute the integral warp factor between two non-warped time points
|
||||
*
|
||||
* Calculate the relative length increase of the chosen segment from the original sound.
|
||||
* So if this time track has a low value (i.e. makes the sound slower), the NEW warped
|
||||
* sound will be *longer* than the original sound, so the return value of this function
|
||||
* is larger.
|
||||
* @param t0 The starting time to calculate from
|
||||
* @param t1 The ending time to calculate to
|
||||
* @return The relative length increase of the chosen segment from the original sound.
|
||||
*/
|
||||
double ComputeWarpFactor(const Envelope &env, double t0, double t1)
|
||||
{
|
||||
return env.AverageOfInverse(t0, t1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
size_t Mixer::MixVariableRates(int *channelFlags, WaveTrackCache &cache,
|
||||
sampleCount *pos, float *queue,
|
||||
int *queueStart, int *queueLen,
|
||||
@ -474,7 +496,7 @@ size_t Mixer::MixVariableRates(int *channelFlags, WaveTrackCache &cache,
|
||||
}
|
||||
|
||||
double factor = initialWarp;
|
||||
if (mTimeTrack)
|
||||
if (mEnvelope)
|
||||
{
|
||||
//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
|
||||
@ -482,11 +504,11 @@ size_t Mixer::MixVariableRates(int *channelFlags, WaveTrackCache &cache,
|
||||
// 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);
|
||||
factor *= ComputeWarpFactor( *mEnvelope,
|
||||
t - (double)thisProcessLen / trackRate + tstep, t + tstep);
|
||||
else
|
||||
factor *= mTimeTrack->ComputeWarpFactor
|
||||
(t, t + (double)thisProcessLen / trackRate);
|
||||
factor *= ComputeWarpFactor( *mEnvelope,
|
||||
t, t + (double)thisProcessLen / trackRate);
|
||||
}
|
||||
|
||||
auto results = pResample->Process(factor,
|
||||
|
10
src/Mix.h
10
src/Mix.h
@ -25,7 +25,7 @@
|
||||
|
||||
class Resample;
|
||||
class DirManager;
|
||||
class TimeTrack;
|
||||
class BoundedEnvelope;
|
||||
class TrackFactory;
|
||||
class TrackList;
|
||||
class WaveTrack;
|
||||
@ -83,15 +83,15 @@ class AUDACITY_DLL_API Mixer {
|
||||
class WarpOptions
|
||||
{
|
||||
public:
|
||||
explicit WarpOptions(const TimeTrack *t)
|
||||
: timeTrack(t), minSpeed(0.0), maxSpeed(0.0)
|
||||
explicit WarpOptions(const BoundedEnvelope *e)
|
||||
: envelope(e), minSpeed(0.0), maxSpeed(0.0)
|
||||
{}
|
||||
|
||||
WarpOptions(double min, double max);
|
||||
|
||||
private:
|
||||
friend class Mixer;
|
||||
const TimeTrack *timeTrack;
|
||||
const BoundedEnvelope *envelope = nullptr;
|
||||
double minSpeed, maxSpeed;
|
||||
};
|
||||
|
||||
@ -164,7 +164,7 @@ class AUDACITY_DLL_API Mixer {
|
||||
size_t mNumInputTracks;
|
||||
ArrayOf<WaveTrackCache> mInputTrack;
|
||||
bool mbVariableRates;
|
||||
const TimeTrack *mTimeTrack;
|
||||
const BoundedEnvelope *mEnvelope;
|
||||
ArrayOf<sampleCount> mSamplePos;
|
||||
bool mApplyTrackGains;
|
||||
Doubles mEnvValues;
|
||||
|
@ -24,6 +24,7 @@ Paul Licameli split from ProjectManager.cpp
|
||||
#include "ProjectHistory.h"
|
||||
#include "ProjectSettings.h"
|
||||
#include "ProjectWindow.h"
|
||||
#include "TimeTrack.h"
|
||||
#include "toolbars/ControlToolBar.h"
|
||||
#include "widgets/ErrorDialog.h"
|
||||
#include "widgets/Warning.h"
|
||||
@ -174,7 +175,8 @@ DefaultPlayOptions( AudacityProject &project )
|
||||
ProjectSettings::Get( project ).GetRate() };
|
||||
options.captureMeter = projectAudioIO.GetCaptureMeter();
|
||||
options.playbackMeter = projectAudioIO.GetPlaybackMeter();
|
||||
options.timeTrack = TrackList::Get( project ).GetTimeTrack();
|
||||
auto timeTrack = TrackList::Get( project ).GetTimeTrack();
|
||||
options.envelope = timeTrack ? timeTrack->GetEnvelope() : nullptr;
|
||||
options.listener = &ProjectAudioManager::Get( project );
|
||||
return options;
|
||||
}
|
||||
@ -191,7 +193,8 @@ DefaultSpeedPlayOptions( AudacityProject &project )
|
||||
AudioIOStartStreamOptions options{ &project, PlayAtSpeedRate };
|
||||
options.captureMeter = projectAudioIO.GetCaptureMeter();
|
||||
options.playbackMeter = projectAudioIO.GetPlaybackMeter();
|
||||
options.timeTrack = TrackList::Get( project ).GetTimeTrack();
|
||||
auto timeTrack = TrackList::Get( project ).GetTimeTrack();
|
||||
options.envelope = timeTrack ? timeTrack->GetEnvelope() : nullptr;
|
||||
options.listener = &ProjectAudioManager::Get( project );
|
||||
return options;
|
||||
}
|
||||
|
@ -58,11 +58,12 @@ TimeTrack::TimeTrack(const std::shared_ptr<DirManager> &projDirManager, const Zo
|
||||
{
|
||||
mHeight = 100;
|
||||
|
||||
mEnvelope = std::make_unique<BoundedEnvelope>(true, TIMETRACK_MIN, TIMETRACK_MAX, 1.0);
|
||||
|
||||
SetRangeLower( 0.9 );
|
||||
SetRangeUpper( 1.1 );
|
||||
mDisplayLog = false;
|
||||
|
||||
mEnvelope = std::make_unique<BoundedEnvelope>(true, TIMETRACK_MIN, TIMETRACK_MAX, 1.0);
|
||||
mEnvelope->SetTrackLen(DBL_MAX);
|
||||
mEnvelope->SetOffset(0);
|
||||
|
||||
@ -88,6 +89,10 @@ TimeTrack::TimeTrack(const TimeTrack &orig, double *pT0, double *pT1)
|
||||
}
|
||||
else
|
||||
mEnvelope = std::make_unique<BoundedEnvelope>( *orig.mEnvelope );
|
||||
|
||||
SetRangeLower(orig.GetRangeLower());
|
||||
SetRangeUpper(orig.GetRangeUpper());
|
||||
|
||||
mEnvelope->SetTrackLen( len );
|
||||
mEnvelope->SetOffset(0);
|
||||
|
||||
@ -104,8 +109,6 @@ void TimeTrack::Init(const TimeTrack &orig)
|
||||
Track::Init(orig);
|
||||
SetDefaultName(orig.GetDefaultName());
|
||||
SetName(orig.GetName());
|
||||
SetRangeLower(orig.GetRangeLower());
|
||||
SetRangeUpper(orig.GetRangeUpper());
|
||||
SetDisplayLog(orig.GetDisplayLog());
|
||||
}
|
||||
|
||||
@ -188,22 +191,6 @@ void TimeTrack::SetInterpolateLog(bool interpolateLog) {
|
||||
mEnvelope->SetExponential(interpolateLog);
|
||||
}
|
||||
|
||||
//Compute the (average) warp factor between two non-warped time points
|
||||
double TimeTrack::ComputeWarpFactor(double t0, double t1) const
|
||||
{
|
||||
return GetEnvelope()->AverageOfInverse(t0, t1);
|
||||
}
|
||||
|
||||
double TimeTrack::ComputeWarpedLength(double t0, double t1) const
|
||||
{
|
||||
return GetEnvelope()->IntegralOfInverse(t0, t1);
|
||||
}
|
||||
|
||||
double TimeTrack::SolveWarpedLength(double t0, double length) const
|
||||
{
|
||||
return GetEnvelope()->SolveIntegralOfInverse(t0, length);
|
||||
}
|
||||
|
||||
bool TimeTrack::HandleXMLTag(const wxChar *tag, const wxChar **attrs)
|
||||
{
|
||||
if (!wxStrcmp(tag, wxT("timetrack"))) {
|
||||
@ -335,7 +322,7 @@ void TimeTrack::Draw
|
||||
// than the current value.
|
||||
mRuler->SetFlip(GetHeight() > 75 ? true : true); // MB: so why don't we just call Invalidate()? :)
|
||||
mRuler->SetTickColour( theTheme.Colour( clrTrackPanelText ));
|
||||
mRuler->Draw(dc, this);
|
||||
mRuler->Draw(dc, GetEnvelope());
|
||||
|
||||
Doubles envValues{ size_t(mid.width) };
|
||||
EnvelopeEditor::GetValues( *GetEnvelope(),
|
||||
|
@ -83,38 +83,6 @@ class TimeTrack final : public Track {
|
||||
BoundedEnvelope *GetEnvelope() { return mEnvelope.get(); }
|
||||
const BoundedEnvelope *GetEnvelope() const { return mEnvelope.get(); }
|
||||
|
||||
//Note: The meaning of this function has changed (December 2012)
|
||||
//Previously this function did something that was close to the opposite (but not entirely accurate).
|
||||
/** @brief Compute the integral warp factor between two non-warped time points
|
||||
*
|
||||
* Calculate the relative length increase of the chosen segment from the original sound.
|
||||
* So if this time track has a low value (i.e. makes the sound slower), the NEW warped
|
||||
* sound will be *longer* than the original sound, so the return value of this function
|
||||
* is larger.
|
||||
* @param t0 The starting time to calculate from
|
||||
* @param t1 The ending time to calculate to
|
||||
* @return The relative length increase of the chosen segment from the original sound.
|
||||
*/
|
||||
double ComputeWarpFactor(double t0, double t1) const;
|
||||
/** @brief Compute the duration (in seconds at playback) of the specified region of the track.
|
||||
*
|
||||
* Takes a region of the time track (specified by the unwarped time points in the project), and
|
||||
* calculates how long it will actually take to play this region back, taking the time track's
|
||||
* warping effects into account.
|
||||
* @param t0 unwarped time to start calculation from
|
||||
* @param t1 unwarped time to stop calculation at
|
||||
* @return the warped duration in seconds
|
||||
*/
|
||||
double ComputeWarpedLength(double t0, double t1) const;
|
||||
/** @brief Compute how much unwarped time must have elapsed if length seconds of warped time has
|
||||
* elapsed
|
||||
*
|
||||
* @param t0 The unwarped time (seconds from project start) at which to start
|
||||
* @param length How many seconds of warped time went past.
|
||||
* @return The end point (in seconds from project start) as unwarped time
|
||||
*/
|
||||
double SolveWarpedLength(double t0, double length) const;
|
||||
|
||||
// Get/Set the speed-warping range, as percentage of original speed (e.g. 90%-110%)
|
||||
|
||||
double GetRangeLower() const;
|
||||
|
@ -68,6 +68,7 @@
|
||||
#include "../ProjectSettings.h"
|
||||
#include "../ProjectWindow.h"
|
||||
#include "../ShuttleGui.h"
|
||||
#include "../TimeTrack.h"
|
||||
#include "../WaveTrack.h"
|
||||
#include "../widgets/AudacityMessageBox.h"
|
||||
#include "../widgets/Warning.h"
|
||||
@ -250,11 +251,12 @@ std::unique_ptr<Mixer> ExportPlugin::CreateMixer(const TrackList &tracks,
|
||||
const WaveTrackConstArray inputTracks =
|
||||
tracks.GetWaveTrackConstArray(selectionOnly, false);
|
||||
const TimeTrack *timeTrack = tracks.GetTimeTrack();
|
||||
auto envelope = timeTrack ? timeTrack->GetEnvelope() : nullptr;
|
||||
// MB: the stop time should not be warped, this was a bug.
|
||||
return std::make_unique<Mixer>(inputTracks,
|
||||
// Throw, to stop exporting, if read fails:
|
||||
true,
|
||||
Mixer::WarpOptions(timeTrack),
|
||||
Mixer::WarpOptions(envelope),
|
||||
startTime, stopTime,
|
||||
numOutChannels, outBufferSize, outInterleaved,
|
||||
outRate, outFormat,
|
||||
|
@ -29,7 +29,6 @@ class Tags;
|
||||
class TrackList;
|
||||
class MixerSpec;
|
||||
class ProgressDialog;
|
||||
class TimeTrack;
|
||||
class Mixer;
|
||||
using WaveTrackConstArray = std::vector < std::shared_ptr < const WaveTrack > >;
|
||||
enum class ProgressResult : unsigned;
|
||||
|
@ -713,12 +713,6 @@ int ControlToolBar::PlayPlayRegion(const SelectedRegion &selectedRegion,
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
// Lifted the following into AudacityProject::GetDefaultPlayOptions()
|
||||
/*
|
||||
if (!timetrack) {
|
||||
timetrack = t->GetTimeTrack();
|
||||
}
|
||||
*/
|
||||
token = gAudioIO->StartStream(
|
||||
GetAllPlaybackTracks( tracks, false, useMidi ),
|
||||
t0, t1, options);
|
||||
@ -775,7 +769,7 @@ void ControlToolBar::PlayCurrentRegion(bool looped /* = false */,
|
||||
auto options = DefaultPlayOptions( *p );
|
||||
options.playLooped = looped;
|
||||
if (cutpreview)
|
||||
options.timeTrack = NULL;
|
||||
options.envelope = nullptr;
|
||||
auto mode =
|
||||
cutpreview ? PlayMode::cutPreviewPlay
|
||||
: options.playLooped ? PlayMode::loopedPlay
|
||||
|
@ -28,7 +28,6 @@ class wxStatusBar;
|
||||
class AButton;
|
||||
class AudacityProject;
|
||||
class TrackList;
|
||||
class TimeTrack;
|
||||
|
||||
struct AudioIOStartStreamOptions;
|
||||
class SelectedRegion;
|
||||
|
@ -40,7 +40,7 @@
|
||||
#include "../KeyboardCapture.h"
|
||||
#include "../Project.h"
|
||||
#include "../ProjectAudioManager.h"
|
||||
#include "../TimeTrack.h"
|
||||
#include "../Envelope.h"
|
||||
#include "../ViewInfo.h"
|
||||
#include "../WaveTrack.h"
|
||||
#include "../widgets/AButton.h"
|
||||
@ -443,6 +443,11 @@ void TranscriptionToolBar::GetSamples(
|
||||
*slen = ss1 - ss0;
|
||||
}
|
||||
|
||||
// PRL: duplicating constants from TimeTrack.cpp
|
||||
//TODO-MB: are these sensible values?
|
||||
#define TIMETRACK_MIN 0.01
|
||||
#define TIMETRACK_MAX 10.0
|
||||
|
||||
// Come here from button clicks, or commands
|
||||
void TranscriptionToolBar::PlayAtSpeed(bool looped, bool cutPreview)
|
||||
{
|
||||
@ -464,17 +469,16 @@ void TranscriptionToolBar::PlayAtSpeed(bool looped, bool cutPreview)
|
||||
bFixedSpeedPlay = bFixedSpeedPlay || looped || cutPreview;
|
||||
if (bFixedSpeedPlay)
|
||||
{
|
||||
// Create a TimeTrack if we haven't done so already
|
||||
if (!mTimeTrack) {
|
||||
mTimeTrack = TrackFactory::Get( *p ).NewTimeTrack();
|
||||
if (!mTimeTrack) {
|
||||
return;
|
||||
}
|
||||
// Create a BoundedEnvelope if we haven't done so already
|
||||
if (!mEnvelope) {
|
||||
mEnvelope =
|
||||
std::make_unique<BoundedEnvelope>(
|
||||
true, TIMETRACK_MIN, TIMETRACK_MAX, 1.0);
|
||||
}
|
||||
// Set the speed range
|
||||
//mTimeTrack->SetRangeUpper((double)mPlaySpeed / 100.0);
|
||||
//mTimeTrack->SetRangeLower((double)mPlaySpeed / 100.0);
|
||||
mTimeTrack->GetEnvelope()->Flatten((double)mPlaySpeed / 100.0);
|
||||
mEnvelope->Flatten((double)mPlaySpeed / 100.0);
|
||||
}
|
||||
|
||||
// Pop up the button
|
||||
@ -498,7 +502,7 @@ void TranscriptionToolBar::PlayAtSpeed(bool looped, bool cutPreview)
|
||||
auto options = DefaultPlayOptions( *p );
|
||||
options.playLooped = looped;
|
||||
// No need to set cutPreview options.
|
||||
options.timeTrack = mTimeTrack.get();
|
||||
options.envelope = mEnvelope.get();
|
||||
auto mode =
|
||||
cutPreview ? PlayMode::cutPreviewPlay
|
||||
: options.playLooped ? PlayMode::loopedPlay
|
||||
|
@ -29,7 +29,7 @@ class wxKeyEvent;
|
||||
class AButton;
|
||||
class ASlider;
|
||||
class AudacityProject;
|
||||
class TimeTrack;
|
||||
class BoundedEnvelope;
|
||||
class WaveTrack;
|
||||
|
||||
#ifdef EXPERIMENTAL_VOICE_DETECTION
|
||||
@ -152,7 +152,7 @@ class TranscriptionToolBar final : public ToolBar {
|
||||
int mBackgroundWidth;
|
||||
int mBackgroundHeight;
|
||||
|
||||
std::shared_ptr<TimeTrack> mTimeTrack;
|
||||
std::shared_ptr<BoundedEnvelope> mEnvelope;
|
||||
|
||||
public:
|
||||
|
||||
|
@ -387,7 +387,7 @@ bool Scrubber::MaybeStartScrubbing(wxCoord xx)
|
||||
auto options =
|
||||
DefaultPlayOptions( *mProject );
|
||||
options.pScrubbingOptions = &mOptions;
|
||||
options.timeTrack = NULL;
|
||||
options.envelope = nullptr;
|
||||
mOptions.delay = (ScrubPollInterval_ms / 1000.0);
|
||||
mOptions.isPlayingAtSpeed = false;
|
||||
mOptions.minSpeed = 0.0;
|
||||
@ -487,7 +487,7 @@ bool Scrubber::StartSpeedPlay(double speed, double time0, double time1)
|
||||
|
||||
auto options = DefaultSpeedPlayOptions( *mProject );
|
||||
options.pScrubbingOptions = &mOptions;
|
||||
options.timeTrack = NULL;
|
||||
options.envelope = nullptr;
|
||||
mOptions.delay = (ScrubPollInterval_ms / 1000.0);
|
||||
mOptions.minSpeed = speed -0.01;
|
||||
mOptions.maxSpeed = speed +0.01;
|
||||
|
@ -64,8 +64,8 @@ array of Ruler::Label.
|
||||
|
||||
#include "../AColor.h"
|
||||
#include "../AllThemeResources.h"
|
||||
#include "../Envelope.h"
|
||||
#include "../NumberScale.h"
|
||||
#include "../TimeTrack.h"
|
||||
#include "../ViewInfo.h"
|
||||
|
||||
using std::min;
|
||||
@ -954,7 +954,19 @@ void Ruler::Update()
|
||||
Update(NULL);
|
||||
}
|
||||
|
||||
void Ruler::Update(const TimeTrack* timetrack)// Envelope *speedEnv, long minSpeed, long maxSpeed )
|
||||
namespace {
|
||||
double ComputeWarpedLength(const Envelope &env, double t0, double t1)
|
||||
{
|
||||
return env.IntegralOfInverse(t0, t1);
|
||||
}
|
||||
|
||||
double SolveWarpedLength(const Envelope &env, double t0, double length)
|
||||
{
|
||||
return env.SolveIntegralOfInverse(t0, length);
|
||||
}
|
||||
}
|
||||
|
||||
void Ruler::Update(const Envelope* envelope)// Envelope *speedEnv, long minSpeed, long maxSpeed )
|
||||
{
|
||||
const ZoomInfo *zoomInfo = NULL;
|
||||
if (!mLog && mOrientation == wxHORIZONTAL)
|
||||
@ -1115,8 +1127,8 @@ void Ruler::Update(const TimeTrack* timetrack)// Envelope *speedEnv, long minSpe
|
||||
}
|
||||
else
|
||||
d = mMin - UPP / 2;
|
||||
if (timetrack)
|
||||
warpedD = timetrack->ComputeWarpedLength(0.0, d);
|
||||
if (envelope)
|
||||
warpedD = ComputeWarpedLength(*envelope, 0.0, d);
|
||||
else
|
||||
warpedD = d;
|
||||
// using ints doesn't work, as
|
||||
@ -1133,8 +1145,8 @@ void Ruler::Update(const TimeTrack* timetrack)// Envelope *speedEnv, long minSpe
|
||||
}
|
||||
else
|
||||
nextD = d + UPP;
|
||||
if (timetrack)
|
||||
warpedD += timetrack->ComputeWarpedLength(d, nextD);
|
||||
if (envelope)
|
||||
warpedD += ComputeWarpedLength(*envelope, d, nextD);
|
||||
else
|
||||
warpedD = nextD;
|
||||
d = nextD;
|
||||
@ -1290,14 +1302,14 @@ void Ruler::Draw(wxDC& dc)
|
||||
Draw( dc, NULL);
|
||||
}
|
||||
|
||||
void Ruler::Draw(wxDC& dc, const TimeTrack* timetrack)
|
||||
void Ruler::Draw(wxDC& dc, const Envelope* envelope)
|
||||
{
|
||||
mDC = &dc;
|
||||
if( mLength <=0 )
|
||||
return;
|
||||
|
||||
if (!mValid)
|
||||
Update(timetrack);
|
||||
Update(envelope);
|
||||
|
||||
mDC->SetTextForeground( mTickColour );
|
||||
#ifdef EXPERIMENTAL_THEMING
|
||||
|
@ -21,7 +21,7 @@ class wxDC;
|
||||
class wxFont;
|
||||
|
||||
class NumberScale;
|
||||
class TimeTrack;
|
||||
class Envelope;
|
||||
class ZoomInfo;
|
||||
|
||||
class AUDACITY_DLL_API Ruler {
|
||||
@ -136,7 +136,7 @@ class AUDACITY_DLL_API Ruler {
|
||||
|
||||
// Note that it will not erase for you...
|
||||
void Draw(wxDC& dc);
|
||||
void Draw(wxDC& dc, const TimeTrack* timetrack);
|
||||
void Draw(wxDC& dc, const Envelope* envelope);
|
||||
// If length <> 0, draws lines perpendiculars to ruler corresponding
|
||||
// to selected ticks (major, minor, or both), in an adjacent window.
|
||||
// You may need to use the offsets if you are using part of the dc for rulers, borders etc.
|
||||
@ -151,7 +151,7 @@ class AUDACITY_DLL_API Ruler {
|
||||
|
||||
private:
|
||||
void Update();
|
||||
void Update(const TimeTrack* timetrack);
|
||||
void Update(const Envelope* envelope);
|
||||
void FindTickSizes();
|
||||
void FindLinearTickSizes(double UPP);
|
||||
wxString LabelString(double d, bool major);
|
||||
|
Loading…
x
Reference in New Issue
Block a user