mirror of
https://github.com/cookiengineer/audacity
synced 2025-05-01 16:19:43 +02:00
Disallow punch and roll from t=0.0
Punch and roll from 0.0 deletes the whole track before punch and rolling. That is unlikely to be what the user intended, since there is then no audio cue, so disallow it. Also reduced indentation.
This commit is contained in:
parent
ed34e6b029
commit
66a87ecaa9
153
src/Menus.cpp
153
src/Menus.cpp
@ -8518,88 +8518,91 @@ int AudacityProject::DialogForLabelName(const wxString& initialValue, wxString&
|
||||
#ifdef EXPERIMENTAL_PUNCH_AND_ROLL
|
||||
void AudacityProject::OnPunchAndRoll(const CommandContext &WXUNUSED(context))
|
||||
{
|
||||
if (!gAudioIO->IsBusy()) {
|
||||
if (gAudioIO->IsBusy())
|
||||
return;
|
||||
|
||||
// Ignore all but left edge of the selection.
|
||||
mViewInfo.selectedRegion.collapseToT0();
|
||||
const double t1 = std::max(0.0, mViewInfo.selectedRegion.t1());
|
||||
// Ignore all but left edge of the selection.
|
||||
mViewInfo.selectedRegion.collapseToT0();
|
||||
const double t1 = std::max(0.0, mViewInfo.selectedRegion.t1());
|
||||
|
||||
// Decide which tracks to record in.
|
||||
auto pBar = GetControlToolBar();
|
||||
auto tracks = pBar->ChooseExistingRecordingTracks(*this, true);
|
||||
if (tracks.empty()) {
|
||||
int recordingChannels =
|
||||
std::max(0L, gPrefs->Read(wxT("/AudioIO/RecordChannels"), 2));
|
||||
auto format = wxPLURAL(
|
||||
"Please select at least %d channel.",
|
||||
"Please select at least %d channels.",
|
||||
recordingChannels
|
||||
);
|
||||
auto message =
|
||||
wxString::Format(format, recordingChannels);
|
||||
// Decide which tracks to record in.
|
||||
auto pBar = GetControlToolBar();
|
||||
auto tracks = pBar->ChooseExistingRecordingTracks(*this, true);
|
||||
if (tracks.empty()) {
|
||||
int recordingChannels =
|
||||
std::max(0L, gPrefs->Read(wxT("/AudioIO/RecordChannels"), 2));
|
||||
auto format = wxPLURAL(
|
||||
"Please select at least %d channel.",
|
||||
"Please select at least %d channels.",
|
||||
recordingChannels
|
||||
);
|
||||
auto message =
|
||||
wxString::Format(format, recordingChannels);
|
||||
AudacityMessageBox(message);
|
||||
return;
|
||||
}
|
||||
|
||||
// Delete the portion of the target tracks right of the selection, but first,
|
||||
// remember a part of the deletion for crossfading with the new recording.
|
||||
PRCrossfadeData crossfadeData;
|
||||
const double crossFadeDuration =
|
||||
gPrefs->Read(AUDIO_ROLL_CROSSFADE_KEY, DEFAULT_ROLL_CROSSFADE_MS)
|
||||
/ 1000.0;
|
||||
for (const auto &wt : tracks) {
|
||||
// The test for t1 == 0.0 stops punch and roll deleting everything where the
|
||||
// selection is at zero. There wouldn't be any cued audio to play in
|
||||
// that case, so a normal record, not a punch and roll, is called for.
|
||||
if (!wt->GetClipAtSample(sampleCount(floor(t1 * wt->GetRate()))) || t1 ==0.0) {
|
||||
auto message = _("Please select a time within a clip.");
|
||||
AudacityMessageBox(message);
|
||||
return;
|
||||
}
|
||||
|
||||
// Delete the portion of the target tracks right of the selection, but first,
|
||||
// remember a part of the deletion for crossfading with the new recording.
|
||||
PRCrossfadeData crossfadeData;
|
||||
const double crossFadeDuration =
|
||||
gPrefs->Read(AUDIO_ROLL_CROSSFADE_KEY, DEFAULT_ROLL_CROSSFADE_MS)
|
||||
/ 1000.0;
|
||||
for (const auto &wt : tracks) {
|
||||
if (!wt->GetClipAtSample(sampleCount(floor(t1 * wt->GetRate())))) {
|
||||
auto message = _("Please select a time within a clip.");
|
||||
AudacityMessageBox(message);
|
||||
return;
|
||||
}
|
||||
const auto endTime = wt->GetEndTime();
|
||||
const auto duration = std::max(0.0, std::min(crossFadeDuration, endTime - t1));
|
||||
const size_t getLen = floor(duration * wt->GetRate());
|
||||
std::vector<float> data(getLen);
|
||||
if (getLen > 0) {
|
||||
float *const samples = data.data();
|
||||
const sampleCount pos = wt->TimeToLongSamples(t1);
|
||||
wt->Get((samplePtr)samples, floatSample, pos, getLen);
|
||||
}
|
||||
crossfadeData.push_back(std::move(data));
|
||||
const auto endTime = wt->GetEndTime();
|
||||
const auto duration = std::max(0.0, std::min(crossFadeDuration, endTime - t1));
|
||||
const size_t getLen = floor(duration * wt->GetRate());
|
||||
std::vector<float> data(getLen);
|
||||
if (getLen > 0) {
|
||||
float *const samples = data.data();
|
||||
const sampleCount pos = wt->TimeToLongSamples(t1);
|
||||
wt->Get((samplePtr)samples, floatSample, pos, getLen);
|
||||
}
|
||||
|
||||
// Change tracks only after passing the error checks above
|
||||
for (const auto &wt : tracks) {
|
||||
wt->Clear(t1, wt->GetEndTime());
|
||||
}
|
||||
|
||||
// Choose the tracks for playback.
|
||||
TransportTracks transportTracks;
|
||||
const auto duplex = ControlToolBar::UseDuplex();
|
||||
if (duplex)
|
||||
// play all
|
||||
transportTracks = GetAllPlaybackTracks(*GetTracks(), false, true);
|
||||
else
|
||||
// play recording tracks only
|
||||
std::copy(tracks.begin(), tracks.end(), std::back_inserter(transportTracks.playbackTracks));
|
||||
|
||||
// Unlike with the usual recording, a track may be chosen both for playback and recording.
|
||||
transportTracks.captureTracks = std::move(tracks);
|
||||
|
||||
// Try to start recording
|
||||
AudioIOStartStreamOptions options(GetDefaultPlayOptions());
|
||||
options.preRoll = gPrefs->Read(AUDIO_PRE_ROLL_KEY, DEFAULT_PRE_ROLL_SECONDS);
|
||||
options.pCrossfadeData = &crossfadeData;
|
||||
bool success = GetControlToolBar()->DoRecord(*this,
|
||||
transportTracks,
|
||||
t1, DBL_MAX,
|
||||
false, // altAppearance
|
||||
options);
|
||||
|
||||
if (success)
|
||||
// Undo state will get pushed elsewhere, when record finishes
|
||||
;
|
||||
else
|
||||
// Roll back the deletions
|
||||
RollbackState();
|
||||
crossfadeData.push_back(std::move(data));
|
||||
}
|
||||
|
||||
// Change tracks only after passing the error checks above
|
||||
for (const auto &wt : tracks) {
|
||||
wt->Clear(t1, wt->GetEndTime());
|
||||
}
|
||||
|
||||
// Choose the tracks for playback.
|
||||
TransportTracks transportTracks;
|
||||
const auto duplex = ControlToolBar::UseDuplex();
|
||||
if (duplex)
|
||||
// play all
|
||||
transportTracks = GetAllPlaybackTracks(*GetTracks(), false, true);
|
||||
else
|
||||
// play recording tracks only
|
||||
std::copy(tracks.begin(), tracks.end(), std::back_inserter(transportTracks.playbackTracks));
|
||||
|
||||
// Unlike with the usual recording, a track may be chosen both for playback and recording.
|
||||
transportTracks.captureTracks = std::move(tracks);
|
||||
|
||||
// Try to start recording
|
||||
AudioIOStartStreamOptions options(GetDefaultPlayOptions());
|
||||
options.preRoll = gPrefs->Read(AUDIO_PRE_ROLL_KEY, DEFAULT_PRE_ROLL_SECONDS);
|
||||
options.pCrossfadeData = &crossfadeData;
|
||||
bool success = GetControlToolBar()->DoRecord(*this,
|
||||
transportTracks,
|
||||
t1, DBL_MAX,
|
||||
false, // altAppearance
|
||||
options);
|
||||
|
||||
if (success)
|
||||
// Undo state will get pushed elsewhere, when record finishes
|
||||
;
|
||||
else
|
||||
// Roll back the deletions
|
||||
RollbackState();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user