1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-07-17 00:57:40 +02:00

Rewrite logic for choosing append-record tracks...

... If recording one or two channels, use first unbroken subsequence within the
selected wave tracks for which the total of channels matches exactly; failing
that, use such a sequence among all wave tracks; failing that, record to
new tracks.

If recording more than two channels, and there is at least one selected wave
track, then use the topmost selected wave channels, up to the number of
recording channels, and if fewer channels are selected, just drop the extra
input channels.

If recording more than two, and no wave tracks are selected, ignore existing
wave tracks and record to new tracks.

In any case, the tracks chosen for append-record might not be consecutive
among all the tracks, because non-wave or non-selected tracks may come between.
This commit is contained in:
Paul Licameli 2018-06-09 13:05:34 -04:00
parent 5fc2100147
commit e40420ba72

View File

@ -897,69 +897,93 @@ void ControlToolBar::Pause()
} }
} }
WaveTrackArray ControlToolBar::ChooseExistingRecordingTracks(AudacityProject &proj, bool selectedOnly) WaveTrackArray ControlToolBar::ChooseExistingRecordingTracks(
AudacityProject &proj, bool selectedOnly)
{ {
auto p = &proj; auto p = &proj;
TrackList *trackList = p->GetTracks(); size_t recordingChannels =
TrackListIterator it(trackList); std::max(0L, gPrefs->Read(wxT("/AudioIO/RecordChannels"), 2));
bool strictRules = (recordingChannels <= 2);
bool hasWave = false; // Iterate over all wave tracks, or over selected wave tracks only.
for (auto t = it.First(); t; t = it.Next()) { //
if (t->GetKind() == Track::Wave) { // In the usual cases of one or two recording channels, seek a first-fit
hasWave = true; // unbroken sub-sequence for which the total number of channels matches the
break; // required number exactly. Never drop inputs or fill only some channels
} // of a track.
} //
if (!hasWave) // In case of more than two recording channels, choose tracks only among the
// Treat append-record like record to new, when there are // selected. Simply take the earliest wave tracks, until the number of
// no wave tracks to append onto. // channels is enough. If there are fewer channels than inputs, but at least
// one channel, then some of the input channels will be dropped.
//
// Resulting tracks may be non-consecutive within the list of all tracks
// (there may be non-wave tracks between, or non-selected tracks when
// considering selected tracks only.)
if (!strictRules && !selectedOnly)
return {}; return {};
size_t recordingChannels = std::max(0L, gPrefs->Read(wxT("/AudioIO/RecordChannels"), 2)); auto trackList = p->GetTracks();
TrackListIterator it(trackList);
std::vector<unsigned> channelCounts;
WaveTrackArray candidates; WaveTrackArray candidates;
auto addCandidates = [&](WaveTrack *candidate){ for (Track *tt = it.First(); tt; tt = it.Next()) {
if (candidates.size() == recordingChannels) // Eliminate certain tracks from consideration
// nothing left to do if (tt->GetKind() != Track::Wave)
return; continue;
WaveTrack *candidate = static_cast<WaveTrack *>(tt);
if (candidate->GetLink() && !candidate->GetLinked()) if (candidate->GetLink() && !candidate->GetLinked())
return; // Don't re-consider right channel apart from the left
continue;
if (selectedOnly && !candidate->GetSelected())
continue;
// count channels in this track
unsigned nChannels = 0;
// This is written with odd seeming generality, looking forward to // This is written with odd seeming generality, looking forward to
// the rewrite that removes assumption of at-most-stereo // the rewrite that removes assumption of at-most-stereo
// count channels
unsigned nChannels = 0;
for (auto channel = candidate; channel; for (auto channel = candidate; channel;
channel = channel->GetLinked() channel = channel->GetLinked()
? static_cast<WaveTrack*>(channel->GetLink()) : nullptr) ? static_cast<WaveTrack*>(channel->GetLink()) : nullptr)
++nChannels; ++nChannels;
// Accumulate consecutive single channel tracks, or else one track of if (strictRules && nChannels > recordingChannels) {
// the exact number of channels // The recording would under-fill this track's channels
if (nChannels > 1) // Can't use any partial accumulated results
// either. Keep looking.
candidates.clear(); candidates.clear();
channelCounts.clear();
if (nChannels == 1 || // <- comment this out to disallow recording continue;
// stereo into two adjacent mono tracks
nChannels == recordingChannels) {
for (auto channel = candidate; channel;
channel = channel->GetLinked()
? static_cast<WaveTrack*>(channel->GetLink()) : nullptr)
candidates.push_back(Track::Pointer<WaveTrack>(channel));
} }
}; else {
// Might use this but may have to discard some of the accumulated
for (Track *tt = it.First(); tt; tt = it.Next()) { while(strictRules &&
if (tt->GetKind() == Track::Wave) { nChannels + candidates.size() > recordingChannels) {
WaveTrack *wt = static_cast<WaveTrack *>(tt); auto nOldChannels = channelCounts[0];
if (!selectedOnly || wt->GetSelected()) wxASSERT(nOldChannels > 0);
addCandidates(wt); channelCounts.erase(channelCounts.begin());
candidates.erase(candidates.begin(),
candidates.begin() + nOldChannels);
}
channelCounts.push_back(nChannels);
for (auto channel = candidate; channel;
channel = channel->GetLinked()
? static_cast<WaveTrack*>(channel->GetLink()) : nullptr) {
candidates.push_back(Track::Pointer<WaveTrack>(channel));
if(candidates.size() == recordingChannels)
// Done!
return candidates;
}
} }
} }
return candidates; if (!strictRules && !candidates.empty())
// good enough
return candidates;
// If the loop didn't exit early, we could not find enough channels
return {};
} }
void ControlToolBar::OnRecord(wxCommandEvent &evt) void ControlToolBar::OnRecord(wxCommandEvent &evt)