16#include <wx/statusbr.h>
52 return std::make_shared< ProjectAudioManager >(
project );
82 return XO(
"Actual Rate: %d").Format( rate );
95 int rate = audioManager.mDisplayedRate;
124 double trackTime,
size_t nSamples)
override;
126 bool RepositionPlayback(
128 size_t frames,
size_t available)
override;
132 {
return mReversed ? mGapLeft + mGapLength : mGapLeft; }
134 {
return mReversed ? mGapLeft : mGapLeft + mGapLength; }
136 {
return mReversed ? trackTime1 >= trackTime2 : trackTime1 <= trackTime2; }
142 double mStart = 0, mEnd = 0;
145 double mDuration1 = 0, mDuration2 = 0;
146 double mInitDuration1 = 0, mInitDuration2 = 0;
148 bool mDiscontinuity{
false };
149 bool mReversed{
false };
152CutPreviewPlaybackPolicy::CutPreviewPlaybackPolicy(
153 double gapLeft,
double gapLength)
154: mGapLeft{ gapLeft }, mGapLength{ gapLength }
156 wxASSERT(gapLength >= 0.0);
168 double right =
mEnd = schedule.
mT1;
201 auto space = std::clamp(
mGapLeft - time, 0.0, offset);
235 size_t frames = available;
236 size_t toProduce = frames;
238 if (samples1 > 0 && samples1 < frames)
240 toProduce = frames = samples1.
as_size_t();
241 else if (samples1 == 0) {
243 if (samples2 < frames) {
250 return { available, frames, toProduce };
256 auto realDuration = nSamples /
mRate;
272 return {
mEnd, std::numeric_limits<double>::infinity()};
278 const Mixers &playbackMixers,
size_t,
size_t )
283 for (
auto &pMixer : playbackMixers)
284 pMixer->Reposition(newTime,
true);
297 auto &projectAudioManager = *
this;
298 bool canStop = projectAudioManager.CanStopAudioStream();
310 double t0 = selectedRegion.
t0();
311 double t1 = selectedRegion.
t1();
322 bool success =
false;
325 if (gAudioIO->IsBusy())
329 if (cutpreview && t0==t1)
336 mLastPlayMode = mode;
344 double latestEnd =
tracks.GetEndTime();
349#if defined(EXPERIMENTAL_SEEK_BEHIND_CURSOR)
350 double initSeek = 0.0;
352 double loopOffset = 0.0;
361 if ((t0 > selectedRegion.
t0()) && (t0 < selectedRegion.
t1())) {
362 t0 = selectedRegion.
t0();
363 t1 = selectedRegion.
t1();
368 loopOffset = t0 -
tracks.GetStartTime();
372 pStartTime.emplace(loopOffset);
373 t0 =
tracks.GetStartTime();
379 t0 =
tracks.GetStartTime();
381 else if (t0 >
tracks.GetEndTime()) {
384#if defined(EXPERIMENTAL_SEEK_BEHIND_CURSOR)
388 pStartTime.emplace(initSeek);
389 t0 =
tracks.GetStartTime();
400 t0 = std::max(0.0,
std::min(t0, latestEnd));
401 t1 = std::max(0.0,
std::min(t1, latestEnd));
411 const double tless =
std::min(t0, t1);
412 const double tgreater = std::max(t0, t1);
413 double beforeLen, afterLen;
414 gPrefs->
Read(
wxT(
"/AudioIO/CutPreviewBeforeLen"), &beforeLen, 2.0);
415 gPrefs->
Read(
wxT(
"/AudioIO/CutPreviewAfterLen"), &afterLen, 1.0);
416 double tcp0 = tless-beforeLen;
417 const double diff = tgreater - tless;
418 double tcp1 = tgreater+afterLen;
423 [tless, diff](
auto&) -> std::unique_ptr<PlaybackPolicy> {
424 return std::make_unique<CutPreviewPlaybackPolicy>(tless, diff);
426 token = gAudioIO->StartStream(
428 tcp0, tcp1, tcp1, myOptions);
431 double mixerLimit = t1;
433 mixerLimit = latestEnd;
434 if (pStartTime && *pStartTime >= t1)
437 token = gAudioIO->StartStream(
439 t0, t1, mixerLimit, options);
452 window.CallAfter( [&]{
457 XO(
"Error opening sound device.\nTry changing the audio host, playback device and the project sample rate."),
458 wxT(
"Error_opening_sound_device"),
473 auto &projectAudioManager = *
this;
474 bool canStop = projectAudioManager.CanStopAudioStream();
489 options.envelope =
nullptr;
494 PlayPlayRegion(
SelectedRegion(playRegion.GetStart(), playRegion.GetEnd()),
503 auto &projectAudioManager = *
this;
504 bool canStop = projectAudioManager.CanStopAudioStream();
512 scrubber.StopScrubbing();
517 auto cleanup =
finally( [&]{
518 projectAudioManager.SetStopping(
false );
521 if (stopStream && gAudioIO->IsBusy()) {
523 projectAudioManager.SetStopping(
true );
525 while( wxTheApp->ProcessIdle() )
530 gAudioIO->StopStream();
532 projectAudioManager.SetLooping(
false );
533 projectAudioManager.SetCutting(
false );
535 #ifdef EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT
536 gAudioIO->AILADisable();
539 projectAudioManager.SetPausedOff();
541 gAudioIO->SetPaused(
false );
547 auto meter = projectAudioIO.GetPlaybackMeter();
552 meter = projectAudioIO.GetCaptureMeter();
570 bool strictRules = (recordingChannels <= 2);
589 if (!strictRules && !selectedOnly)
594 std::vector<unsigned> channelCounts;
595 size_t totalChannels = 0;
596 const auto range = trackList.Any<
WaveTrack>();
602 const auto nChannels = candidate->
NChannels();
603 if (strictRules && nChannels > recordingChannels) {
608 channelCounts.clear();
615 nChannels + totalChannels > recordingChannels) {
616 candidates.erase(candidates.begin());
617 auto nOldChannels = channelCounts[0];
618 assert(nOldChannels > 0);
619 channelCounts.erase(channelCounts.begin());
620 totalChannels -= nOldChannels;
622 candidates.push_back(candidate->SharedPointer<
WaveTrack>());
623 channelCounts.push_back(nChannels);
624 totalChannels += nChannels;
625 if (totalChannels >= recordingChannels)
631 if (!strictRules && !candidates.empty())
642 bool bPreferNewTrack;
643 gPrefs->
Read(
"/GUI/PreferNewTrackRecord", &bPreferNewTrack,
false);
644 const bool appendRecord = (altAppearance == bPreferNewTrack);
651 double t0 = selectedRegion.
t0();
652 double t1 = selectedRegion.t1();
664 const bool anySelected{ selectedTracks.anySelected };
665 const bool allSameRate{ selectedTracks.allSameRate };
669 "for recording must all have the same sampling rate"),
670 XO(
"Mismatched Sampling Rates"),
671 wxICON_ERROR | wxCENTRE);
679 existingTracks = ChooseExistingRecordingTracks(*p,
true, rateOfSelected);
680 if (!existingTracks.empty())
685 if (anySelected && rateOfSelected != options.rate) {
687 "Too few tracks are selected for recording at this sample rate.\n"
688 "(Audacity requires two channels at the same sample rate for\n"
689 "each stereo track)"),
690 XO(
"Too Few Compatible Tracks Selected"),
691 wxICON_ERROR | wxCENTRE);
696 existingTracks = ChooseExistingRecordingTracks(*p,
false, options.rate);
697 if (!existingTracks.empty())
699 const auto endTime = accumulate(
700 existingTracks.begin(), existingTracks.end(),
701 std::numeric_limits<double>::lowest(),
702 [](
double acc,
auto &pTrack) {
703 return std::max(acc, pTrack->GetEndTime());
709 t0 = std::max(t0, endTime);
716 if (t1 <= selectedRegion.t0() && selectedRegion.t1() > selectedRegion.t0()) {
717 t1 = selectedRegion.t1();
732 for (
const auto &wt : existingTracks) {
734 auto it = std::find_if(
736 [&wt](
const auto& playbackSequence) {
737 return playbackSequence->FindChannelGroup() ==
738 wt->FindChannelGroup();
745 std::copy(existingTracks.begin(), existingTracks.end(),
749 options.rate = rateOfSelected;
751 DoRecord(*p, transportTracks, t0, t1, altAppearance, options);
759#ifdef EXPERIMENTAL_DA
770 double t0,
double t1,
774 auto &projectAudioManager = *
this;
788 if (gAudioIO->IsBusy())
791 projectAudioManager.SetAppending(!altAppearance);
793 bool success =
false;
795 auto transportSequences = sequences;
805 auto makeNewClipName = [&](
WaveTrack* track) {
806 for (
auto i = 1; ; ++i) {
808 auto name =
XC(
"%s #%d",
"clip name template")
809 .Format(track->GetName(), i).Translation();
810 if (track->FindClipByName(
name) ==
nullptr)
821 if (!(wt =
dynamic_cast<WaveTrack *
>(sequence.get()))) {
827 auto endTime = wt->GetEndTime();
832 const auto shared = wt->SharedPointer<
WaveTrack>();
836 const auto &range = transportSequences.playbackSequences;
837 bool prerollTrack = any_of(range.begin(), range.end(),
838 [&](
const auto &pSequence){
839 return shared.get() == pSequence->FindChannelGroup(); });
841 transportSequences.prerollSequences.push_back(shared);
848 assert(s.IsLeader());
851 auto &src =
static_cast<const WaveTrack&
>(s);
857 const auto pending =
static_cast<WaveTrack*
>(
858 trackList.RegisterPendingChangedTrack(
updater, wt)
869 const auto recordingStart =
870 std::round(t0 * pending->GetRate()) / pending->GetRate();
871 const auto recordingStartsBeforeTrackEnd =
872 lastClip && recordingStart < lastClip->GetPlayEndTime();
877 !recordingStartsBeforeTrackEnd ||
878 lastClip->WithinPlayRegion(recordingStart));
879 if (!recordingStartsBeforeTrackEnd ||
880 !lastClip->StretchRatioEquals(1))
881 pending->CreateWideClip(t0, makeNewClipName(pending));
882 transportSequences.captureSequences
883 .push_back(pending->SharedPointer<
WaveTrack>());
885 trackList.UpdatePendingTracks();
888 if (transportSequences.captureSequences.empty()) {
890 bool recordingNameCustom, useTrackNumber, useDateStamp, useTimeStamp;
891 wxString defaultTrackName, defaultRecordingTrackName;
898 gPrefs->
Read(
wxT(
"/GUI/TrackNames/RecordingNameCustom"), &recordingNameCustom,
false);
899 gPrefs->
Read(
wxT(
"/GUI/TrackNames/TrackNumber"), &useTrackNumber,
false);
900 gPrefs->
Read(
wxT(
"/GUI/TrackNames/DateStamp"), &useDateStamp,
false);
901 gPrefs->
Read(
wxT(
"/GUI/TrackNames/TimeStamp"), &useTimeStamp,
false);
903 gPrefs->
Read(
wxT(
"/GUI/TrackNames/RecodingTrackName"), &defaultRecordingTrackName, defaultTrackName);
905 wxString baseTrackName = recordingNameCustom? defaultRecordingTrackName : defaultTrackName;
908 const auto first = *newTracks->begin();
909 int trackCounter = 0;
910 const auto minimizeChannelView = recordingChannels > 2 &&
912 for (
auto newTrack : newTracks->Any<
WaveTrack>()) {
914 if (newTrack == first) {
916 t0 = newTrack->SnapToSample(t0);
918 t1 = newTrack->SnapToSample(t1);
921 newTrack->MoveTo(t0);
922 wxString nameSuffix = wxString(
wxT(
""));
924 if (useTrackNumber) {
925 nameSuffix += wxString::Format(
wxT(
"%d"), 1 + (
int) numTracks + trackCounter++);
929 if (!nameSuffix.empty()) {
930 nameSuffix +=
wxT(
"_");
932 nameSuffix += wxDateTime::Now().FormatISODate();
936 if (!nameSuffix.empty()) {
937 nameSuffix +=
wxT(
"_");
939 nameSuffix += wxDateTime::Now().FormatISOTime();
943 nameSuffix.Replace(
wxT(
":"),
wxT(
"-"));
945 if (baseTrackName.empty())
946 newTrack->SetName(nameSuffix);
947 else if (nameSuffix.empty())
948 newTrack->SetName(baseTrackName);
950 newTrack->SetName(baseTrackName +
wxT(
"_") + nameSuffix);
953 newTrack->CreateWideClip(t0, makeNewClipName(newTrack));
955 transportSequences.captureSequences.push_back(
956 std::static_pointer_cast<WaveTrack>(newTrack->shared_from_this())
959 for(
auto channel : newTrack->Channels())
964 trackList.RegisterPendingNewTracks(std::move(*newTracks));
967 if (!trackList.empty())
972 #ifdef EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT
973 gAudioIO->AILAInitialize();
977 gAudioIO->StartStream(transportSequences, t0, t1, t1, options);
979 success = (token != 0);
988 auto msg =
XO(
"Error opening recording device.\nError code: %s")
989 .Format( gAudioIO->LastPaErrorString() );
992 XO(
"Error"), msg,
wxT(
"Error_opening_sound_device"),
1002 auto &projectAudioManager = *
this;
1003 bool canStop = projectAudioManager.CanStopAudioStream();
1009 bool paused = !projectAudioManager.Paused();
1014#ifdef EXPERIMENTAL_SCRUBBING_SUPPORT
1021 bool bStopInstead = paused &&
1023 !scrubber.IsSpeedPlaying() &&
1024 !scrubber.IsKeyboardScrubbing();
1032 scrubber.Pause(paused);
1036 gAudioIO->SetPaused(paused);
1043 mPaused.fetch_xor(1, std::memory_order::memory_order_relaxed);
1048 mPaused.store(0, std::memory_order::memory_order_relaxed);
1053 return mPaused.load(std::memory_order_relaxed) == 1;
1059 const auto project = &mProject;
1067 mDisplayedRate = rate;
1088 if (projectAudioIO.GetAudioIOToken() > 0)
1092 if (IsTimerRecordCancelled()) {
1094 history.RollbackState();
1096 ResetTimerRecordCancelled();
1106 history.PushState(
XO(
"Recorded Audio"),
XO(
"Record"), flags);
1111 auto &intervals = gAudioIO->LostCaptureIntervals();
1112 if (intervals.size())
1123 wxTheApp->CallAfter( [&]{ projectFileIO.AutoSave(
true); });
1128 const auto project = &mProject;
1136 if (gAudioIO && &
project == gAudioIO->GetOwningProject().get())
1138 bool canStop = CanStopAudioStream();
1140 gAudioIO->SetPaused(!gAudioIO->IsPaused());
1161 gAudioIO->IsBusy() &&
1162 CanStopAudioStream() &&
1164 !gAudioIO->IsMonitoring() &&
1166 gAudioIO->GetNumCaptureChannels() == 0;
1173 gAudioIO->IsBusy() &&
1174 CanStopAudioStream() &&
1175 gAudioIO->GetNumCaptureChannels() > 0;
1181 return (!gAudioIO->IsStreamActive() ||
1182 gAudioIO->IsMonitoring() ||
1183 gAudioIO->GetOwningProject().get() == &mProject );
1190 bool canStop = projectAudioManager.CanStopAudioStream();
1205 options.loopEnabled = loopEnabled;
1210 options.policyFactory = [&
project, trackEndTime, loopEndTime](
1212 -> std::unique_ptr<PlaybackPolicy>
1214 return std::make_unique<DefaultPlaybackPolicy>(
project,
1215 trackEndTime, loopEndTime,
1216 options.loopEnabled, options.variableSpeed);
1231 auto PlayAtSpeedRate = gAudioIO->GetBestRate(
1236 result.rate = PlayAtSpeedRate;
1253 auto &selection = viewInfo.selectedRegion;
1257 if (scrubber.HasMark() ||
1258 gAudioIO->IsStreamActive(token)) {
1260 auto time = gAudioIO->GetStreamTime();
1263 if (click && (scrubber.WasSpeedPlaying() || scrubber.WasKeyboardScrubbing()))
1267 else if (shift && click) {
1269 auto t0 = selection.t0(), t1 = selection.t1();
1278 if (fabs(t0 - time) < fabs(t1 - time))
1283 selection.setTimes(t0, t1);
1287 time = wxMax( time, 0 );
1289 selection.setTimes(time, time);
1293 selection.setT0(time,
false);
1306 if (DoPlayStopSelect(
false,
false))
1308 else if (!gAudioIO->IsBusy()) {
1312 PlayCurrentRegion(
false);
1337 const auto selectedTracks{
1340 for (
const auto & track : selectedTracks) {
1342 track->GetRate() != rateOfSelection)
1345 rateOfSelection = track->GetRate();
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
IntSetting AudioIORecordChannels
Toolkit-neutral facade for basic user interface services.
constexpr CommandFlag AlwaysEnabledFlag
std::bitset< NCommandFlags > CommandFlag
const ReservedCommandFlag & AudioIONotBusyFlag()
const ReservedCommandFlag & PausedFlag()
const TranslatableString name
constexpr size_t TimeQueueGrainSize
audacity::BasicSettings * gPrefs
std::unique_ptr< const BasicUI::WindowPlacement > ProjectFramePlacement(AudacityProject *project)
Make a WindowPlacement object suitable for project (which may be null)
static TranslatableString FormatRate(int rate)
static ProjectAudioIO::DefaultOptions::Scope sScope
Install an implementation in a library hook.
AudioIOStartStreamOptions DefaultSpeedPlayOptions(AudacityProject &project)
static RegisteredMenuItemEnabler stopIfPaused
static AudacityProject::AttachedObjects::RegisteredFactory sProjectAudioManagerKey
const ReservedCommandFlag & CanStopAudioStreamFlag()
PropertiesOfSelected GetPropertiesOfSelected(const AudacityProject &proj)
std::vector< std::shared_ptr< WritableSampleTrack > > WritableSampleTrackArray
constexpr int RATE_NOT_SELECTED
ProjectFileIOMessage
Subscribe to ProjectFileIO to receive messages; always in idle time.
@ CheckpointFailure
Failure happened in a worker thread.
an object holding per-project preferred sample rate
AUDACITY_DLL_API wxFrame & GetProjectFrame(AudacityProject &project)
Get the top-level window associated with the project (as a wxFrame only, when you do not need to use ...
accessors for certain important windows associated with each project
TransportSequences MakeTransportTracks(TrackList &trackList, bool selectedOnly, bool nonWaveToo)
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
static AudioIOBase * Get()
bool HasRecordingException() const
double GetEndTime() const
Get the maximum of End() values of intervals, or 0 when none.
virtual size_t NChannels() const =0
Report the number of channels.
static ChannelView & Get(Channel &channel)
void SetMinimized(bool minimized)
Client code makes static instance from a factory of attachments; passes it to Get or Find as a retrie...
typename GlobalVariable< DefaultOptions, const std::function< std::remove_pointer_t< decltype(DefaultFunction)> >, Default, Options... >::Scope Scope
Subscription Subscribe(Callback callback)
Connect a callback to the Publisher; later-connected are called earlier.
AudioTrack subclass that can also be audibly replayed by the program.
Directs which parts of tracks to fetch for playback.
std::vector< std::unique_ptr< Mixer > > Mixers
virtual void Initialize(PlaybackSchedule &schedule, double rate)
Called before starting an audio stream.
static AudioIOStartStreamOptions DefaultOptionsFactory(AudacityProject &project, bool newDefaults)
Default factory function ignores the second argument.
int GetAudioIOToken() const
void SetAudioIOToken(int token)
static AudioIOStartStreamOptions GetDefaultOptions(AudacityProject &project, bool newDefaults=false)
Invoke the global hook, supplying a default argument.
static ProjectAudioIO & Get(AudacityProject &project)
Observer::Subscription mCheckpointFailureSubcription
void Stop(bool stopStream=true)
static std::pair< TranslatableStrings, unsigned > StatusWidthFunction(const AudacityProject &project, StatusBarField field)
bool CanStopAudioStream() const
void OnAudioIONewBlocks() override
void OnAudioIOStartRecording() override
void OnCommitRecording() override
static WritableSampleTrackArray ChooseExistingRecordingTracks(AudacityProject &proj, bool selectedOnly, double targetRate=RATE_NOT_SELECTED)
void OnAudioIORate(int rate) override
static ProjectAudioManager & Get(AudacityProject &project)
void OnCheckpointFailure(ProjectFileIOMessage)
void OnAudioIOStopRecording() override
~ProjectAudioManager() override
ProjectAudioManager(AudacityProject &project)
int PlayPlayRegion(const SelectedRegion &selectedRegion, const AudioIOStartStreamOptions &options, PlayMode playMode, bool backwards=false)
bool DoRecord(AudacityProject &project, const TransportSequences &transportSequences, double t0, double t1, bool altAppearance, const AudioIOStartStreamOptions &options)
void PlayCurrentRegion(bool newDefault=false, bool cutpreview=false)
void OnRecord(bool altAppearance)
void OnSoundActivationThreshold() override
static ProjectFileIO & Get(AudacityProject &project)
void ModifyState(bool bWantsAutoSave)
static ProjectHistory & Get(AudacityProject &project)
static ProjectRate & Get(AudacityProject &project)
static ProjectSettings & Get(AudacityProject &project)
bool GetTracksFitVerticallyZoomed() const
std::pair< std::vector< TranslatableString >, unsigned > StatusWidthResult
static ProjectStatus & Get(AudacityProject &project)
void Set(const TranslatableString &msg, StatusBarField field=mainStatusBarField)
static Scrubber & Get(AudacityProject &project)
Defines a selected portion of a project.
bool Read(T *pVar) const
overload of Read returning a boolean that is true if the value was previously defined */
Abstract base class for an object holding data associated with points on a time axis.
bool IsLeader() const override
double GetEndTime() const
Return the greatest end time of the tracks, or 0 when no tracks.
bool ApplyPendingTracks()
static TrackList & Get(AudacityProject &project)
void ClearPendingTracks(ListOfTracks *pAdded=nullptr)
auto Selected() -> TrackIterRange< TrackType >
Holds a msgid for the translation catalog; may also bind format arguments.
NotifyingSelectedRegion selectedRegion
static ViewInfo & Get(AudacityProject &project)
std::shared_ptr< WaveTrack > Create()
Creates an unnamed empty WaveTrack with default sample format and default rate.
static WaveTrackFactory & Get(AudacityProject &project)
A Track that contains audio waveform data.
void Reinit(const WaveTrack &orig)
static wxString GetDefaultAudioTrackNamePreference()
const WaveClip * GetRightmostClip() const
size_t NChannels() const override
May report more than one only when this is a leader track.
std::pair< double, double > AdvancedTrackTime(PlaybackSchedule &schedule, double trackTime, size_t nSamples) override
Compute a new point in a track's timeline from an old point and a real duration.
PlaybackSlice GetPlaybackSlice(PlaybackSchedule &schedule, size_t available) override
Choose length of one fetch of samples from tracks in a call to AudioIO::FillPlayBuffers.
double OffsetSequenceTime(PlaybackSchedule &schedule, double offset) override
Called when the play head needs to jump a certain distance.
void Initialize(PlaybackSchedule &schedule, double rate) override
Called before starting an audio stream.
double mStart
Starting and ending track times set in Initialize()
bool Done(PlaybackSchedule &schedule, unsigned long) override
Returns true if schedule.GetSequenceTime() has reached the end of playback.
~CutPreviewPlaybackPolicy() override
bool RepositionPlayback(PlaybackSchedule &schedule, const Mixers &playbackMixers, size_t frames, size_t available) override
AudioIO::FillPlayBuffers calls this to update its cursors into tracks for changes of position or spee...
const double mGapLeft
Fixed at construction time; these are a track time and duration.
bool AtOrBefore(double trackTime1, double trackTime2) const
virtual bool Read(const wxString &key, bool *value) const =0
Positions or offsets within audio files need a wide type.
void ShowErrorDialog(const WindowPlacement &placement, const TranslatableString &dlogTitle, const TranslatableString &message, const ManualPageID &helpPage, const ErrorDialogOptions &options={})
Show an error dialog with a link to the manual for further help.
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
void swap(std::unique_ptr< Alg_seq > &a, std::unique_ptr< Alg_seq > &b)
double GetRate(const Track &track)
fastfloat_really_inline void round(adjusted_mantissa &am, callback cb) noexcept
void copy(const T *src, T *dst, int32_t n)
struct holding stream options, including a pointer to the time warp info and AudioIOListener and whet...
PolicyFactory policyFactory
std::optional< double > pStartTime
Options for variations of error dialogs; the default is for modal dialogs.
double mT0
Playback starts at offset of mT0, which is measured in seconds.
double mT1
Playback ends at offset of mT1, which is measured in seconds. Note that mT1 may be less than mT0 duri...
double SolveWarpedLength(double t0, double length) const
Compute how much unwarped time must have elapsed if length seconds of warped time has elapsed,...
double GetSequenceTime() const
Get current track time value, unadjusted.
double ComputeWarpedLength(double t0, double t1) const
Compute signed duration (in seconds at playback) of the specified region of the track.
Describes an amount of contiguous (but maybe time-warped) data to be extracted from tracks to play.
Notification, after recording has stopped, when dropouts have been detected.
static bool IsScrubbing()
RecordableSequences captureSequences
ConstPlayableSequences playbackSequences