1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-06-23 15:50:05 +02:00

Remove GetLink(ed) in various other places

This commit is contained in:
Paul Licameli 2017-04-16 16:36:46 -04:00
parent c107fb298b
commit 4aa990e835
9 changed files with 144 additions and 156 deletions

View File

@ -1891,20 +1891,17 @@ int AudioIO::StartStream(const TransportTracks &tracks,
// group determination should mimic what is done in audacityAudioCallback() // group determination should mimic what is done in audacityAudioCallback()
// when calling RealtimeProcess(). // when calling RealtimeProcess().
int group = 0; int group = 0;
for (size_t i = 0, cnt = mPlaybackTracks.size(); i < cnt; i++) for (size_t i = 0, cnt = mPlaybackTracks.size(); i < cnt;)
{ {
const WaveTrack *vt = mPlaybackTracks[i].get(); const WaveTrack *vt = mPlaybackTracks[i].get();
unsigned chanCnt = 1; // TODO: more-than-two-channels
if (vt->GetLinked()) unsigned chanCnt = TrackList::Channels(vt).size();
{ i += chanCnt;
i++;
chanCnt++;
}
// Setup for realtime playback at the rate of the realtime // Setup for realtime playback at the rate of the realtime
// stream, not the rate of the track. // stream, not the rate of the track.
em.RealtimeAddProcessor(group++, chanCnt, mRate); em.RealtimeAddProcessor(group++, std::min(2u, chanCnt), mRate);
} }
} }
@ -4992,26 +4989,38 @@ int AudioIO::AudioCallback(const void *inputBuffer, void *outputBuffer,
bool drop = false; bool drop = false;
bool dropQuickly = false; bool dropQuickly = false;
bool linkFlag = false;
for (unsigned t = 0; t < numPlaybackTracks; t++) for (unsigned t = 0; t < numPlaybackTracks; t++)
{ {
WaveTrack *vt = mPlaybackTracks[t].get(); WaveTrack *vt = mPlaybackTracks[t].get();
chans[chanCnt] = vt; chans[chanCnt] = vt;
if ( linkFlag ) { // TODO: more-than-two-channels
linkFlag = false; auto nextTrack =
t + 1 < numPlaybackTracks
? mPlaybackTracks[t + 1].get()
: nullptr;
bool firstChannel = vt->IsLeader();
bool lastChannel = !nextTrack || nextTrack->IsLeader();
if ( ! firstChannel )
dropQuickly = dropQuickly && doneMicrofading( *vt ); dropQuickly = dropQuickly && doneMicrofading( *vt );
}
else { else {
drop = dropTrack( *vt ); drop = dropTrack( *vt );
linkFlag = vt->GetLinked();
selected = vt->GetSelected(); selected = vt->GetSelected();
if ( lastChannel ) {
// TODO: more-than-two-channels
#if 1
// If we have a mono track, clear the right channel // If we have a mono track, clear the right channel
if (!linkFlag)
memset(tempBufs[1], 0, framesPerBuffer * sizeof(float)); memset(tempBufs[1], 0, framesPerBuffer * sizeof(float));
#else
// clear any other channels
for ( size_t c = chanCnt + 1; c < numPlaybackChannels; ++c )
memset(tempBufs[c], 0, framesPerBuffer * sizeof(float));
#endif
}
dropQuickly = drop && doneMicrofading( *vt ); dropQuickly = drop && doneMicrofading( *vt );
} }
@ -5055,7 +5064,7 @@ int AudioIO::AudioCallback(const void *inputBuffer, void *outputBuffer,
maxLen = std::max(maxLen, len); maxLen = std::max(maxLen, len);
if (linkFlag) if ( ! lastChannel )
{ {
continue; continue;
} }

View File

@ -2318,14 +2318,13 @@ CommandFlag MenuCommandHandler::GetUpdateFlags
flags |= PlayableTracksExistFlag; flags |= PlayableTracksExistFlag;
if (t->GetSelected()) { if (t->GetSelected()) {
flags |= TracksSelectedFlag; flags |= TracksSelectedFlag;
if (t->GetLinked()) { // TODO: more-than-two-channels
if (TrackList::Channels(t).size() > 1) {
flags |= StereoRequiredFlag; flags |= StereoRequiredFlag;
} }
else {
flags |= WaveTracksSelectedFlag; flags |= WaveTracksSelectedFlag;
flags |= AudioTracksSelectedFlag; flags |= AudioTracksSelectedFlag;
} }
}
if( t->GetEndTime() > t->GetStartTime() ) if( t->GetEndTime() > t->GetStartTime() )
flags |= HasWaveDataFlag; flags |= HasWaveDataFlag;
} }

View File

@ -49,29 +49,24 @@ void MixAndRender(TrackList *tracks, TrackFactory *trackFactory,
uLeft.reset(), uRight.reset(); uLeft.reset(), uRight.reset();
// This function was formerly known as "Quick Mix". // This function was formerly known as "Quick Mix".
const Track *t;
bool mono = false; /* flag if output can be mono without loosing anything*/ bool mono = false; /* flag if output can be mono without loosing anything*/
bool oneinput = false; /* flag set to true if there is only one input track bool oneinput = false; /* flag set to true if there is only one input track
(mono or stereo) */ (mono or stereo) */
TrackListIterator iter(tracks); const auto trackRange = tracks->Selected< const WaveTrack >();
SelectedTrackListOfKindIterator usefulIter(Track::Wave, tracks); auto first = *trackRange.begin();
// this only iterates tracks which are relevant to this function, i.e. // this only iterates tracks which are relevant to this function, i.e.
// selected WaveTracks. The tracklist is (confusingly) the list of all // selected WaveTracks. The tracklist is (confusingly) the list of all
// tracks in the project // tracks in the project
int numWaves = 0; /* number of wave tracks in the selection */ int numWaves = 0; /* number of wave tracks in the selection */
int numMono = 0; /* number of mono, centre-panned wave tracks in selection*/ int numMono = 0; /* number of mono, centre-panned wave tracks in selection*/
t = iter.First(); for(auto wt : trackRange) {
while (t) {
if (t->GetSelected() && t->GetKind() == Track::Wave) {
numWaves++; numWaves++;
float pan = ((WaveTrack*)t)->GetPan(); float pan = wt->GetPan();
if (t->GetChannel() == Track::MonoChannel && pan == 0) if (wt->GetChannel() == Track::MonoChannel && pan == 0)
numMono++; numMono++;
} }
t = iter.Next();
}
if (numMono == numWaves) if (numMono == numWaves)
mono = true; mono = true;
@ -88,13 +83,11 @@ void MixAndRender(TrackList *tracks, TrackFactory *trackFactory,
double tstart, tend; // start and end times for one track. double tstart, tend; // start and end times for one track.
WaveTrackConstArray waveArray; WaveTrackConstArray waveArray;
t = iter.First();
while (t) { for(auto wt : trackRange) {
if (t->GetSelected() && t->GetKind() == Track::Wave) { waveArray.push_back( Track::Pointer< const WaveTrack >( wt ) );
waveArray.push_back(Track::Pointer<const WaveTrack>(t)); tstart = wt->GetStartTime();
tstart = t->GetStartTime(); tend = wt->GetEndTime();
tend = t->GetEndTime();
if (tend > mixEndTime) if (tend > mixEndTime)
mixEndTime = tend; mixEndTime = tend;
// try and get the start time. If the track is empty we will get 0, // try and get the start time. If the track is empty we will get 0,
@ -111,22 +104,21 @@ void MixAndRender(TrackList *tracks, TrackFactory *trackFactory,
} else if (tstart < mixStartTime) } else if (tstart < mixStartTime)
mixStartTime = tstart; // have a start, only make it smaller mixStartTime = tstart; // have a start, only make it smaller
} // end if start and end are different } // end if start and end are different
} // end if track is a selected WaveTrack.
/** @TODO: could we not use a SelectedTrackListOfKindIterator here? */
t = iter.Next();
} }
/* create the destination track (NEW track) */ /* create the destination track (NEW track) */
if ((numWaves == 1) || ((numWaves == 2) && (usefulIter.First()->GetLink() != NULL))) if (numWaves == TrackList::Channels(first).size())
oneinput = true; oneinput = true;
// only one input track (either 1 mono or one linked stereo pair) // only one input track (either 1 mono or one linked stereo pair)
auto mixLeft = trackFactory->NewWaveTrack(format, rate); auto mixLeft = trackFactory->NewWaveTrack(format, rate);
if (oneinput) if (oneinput)
mixLeft->SetName(usefulIter.First()->GetName()); /* set name of output track to be the same as the sole input track */ mixLeft->SetName(first->GetName()); /* set name of output track to be the same as the sole input track */
else else
mixLeft->SetName(_("Mix")); mixLeft->SetName(_("Mix"));
mixLeft->SetOffset(mixStartTime); mixLeft->SetOffset(mixStartTime);
// TODO: more-than-two-channels
decltype(mixLeft) mixRight{}; decltype(mixLeft) mixRight{};
if (mono) { if (mono) {
mixLeft->SetChannel(Track::MonoChannel); mixLeft->SetChannel(Track::MonoChannel);
@ -134,10 +126,11 @@ void MixAndRender(TrackList *tracks, TrackFactory *trackFactory,
else { else {
mixRight = trackFactory->NewWaveTrack(format, rate); mixRight = trackFactory->NewWaveTrack(format, rate);
if (oneinput) { if (oneinput) {
if (usefulIter.First()->GetLink() != NULL) // we have linked track auto channels = TrackList::Channels(first);
mixRight->SetName(usefulIter.First()->GetLink()->GetName()); /* set name to match input track's right channel!*/ if (channels.size() > 1)
mixRight->SetName((*channels.begin().advance(1))->GetName()); /* set name to match input track's right channel!*/
else else
mixRight->SetName(usefulIter.First()->GetName()); /* set name to that of sole input channel */ mixRight->SetName(first->GetName()); /* set name to that of sole input channel */
} }
else else
mixRight->SetName(_("Mix")); mixRight->SetName(_("Mix"));

View File

@ -334,9 +334,10 @@ WaveTrack *MixerTrackCluster::GetWave() const
WaveTrack *MixerTrackCluster::GetRight() const WaveTrack *MixerTrackCluster::GetRight() const
{ {
// TODO: more-than-two-channels
auto left = GetWave(); auto left = GetWave();
if (left) if (left)
return static_cast<WaveTrack*>(left->GetLink()); return * ++ TrackList::Channels(left).begin();
else else
return nullptr; return nullptr;
} }
@ -981,9 +982,9 @@ void MixerBoard::UpdateTrackClusters()
size_t nClusterCount = mMixerTrackClusters.size(); size_t nClusterCount = mMixerTrackClusters.size();
unsigned int nClusterIndex = 0; unsigned int nClusterIndex = 0;
MixerTrackCluster* pMixerTrackCluster = NULL; MixerTrackCluster* pMixerTrackCluster = NULL;
Track* pTrack;
for (auto pPlayableTrack: mTracks->Leaders<PlayableTrack>()) { for (auto pPlayableTrack: mTracks->Leaders<PlayableTrack>()) {
// TODO: more-than-two-channels
auto spTrack = Track::Pointer<PlayableTrack>( pPlayableTrack ); auto spTrack = Track::Pointer<PlayableTrack>( pPlayableTrack );
if (nClusterIndex < nClusterCount) if (nClusterIndex < nClusterCount)
{ {

View File

@ -703,16 +703,20 @@ void ScreenFrame::OnOneHour(wxCommandEvent & WXUNUSED(event))
void ScreenFrame::SizeTracks(int h) void ScreenFrame::SizeTracks(int h)
{ {
TrackListIterator iter(mContext.GetProject()->GetTracks()); // h is the height for a channel
for (Track * t = iter.First(); t; t = iter.Next()) { // Set the height of a mono track twice as high
if (t->GetKind() == Track::Wave) {
if (t->GetLink()) { // TODO: more-than-two-channels
t->SetHeight(h); // If there should be more-than-stereo tracks, this makes
} // each channel as high as for a stereo channel
else {
t->SetHeight(h*2); auto tracks = mContext.GetProject()->GetTracks();
} for (auto t : tracks->Leaders<WaveTrack>()) {
} auto channels = TrackList::Channels(t);
auto nChannels = channels.size();
auto height = nChannels == 1 ? 2 * h : h;
for (auto channel : channels)
channel->SetHeight(height);
} }
mContext.GetProject()->RedrawProject(); mContext.GetProject()->RedrawProject();
} }

View File

@ -1359,10 +1359,9 @@ bool Effect::ProcessPass()
if (!left->GetSelected()) if (!left->GetSelected())
return fallthrough(); return fallthrough();
WaveTrack *right;
sampleCount len; sampleCount len;
sampleCount leftStart; sampleCount leftStart;
sampleCount rightStart; sampleCount rightStart = 0;
if (!isGenerator) if (!isGenerator)
{ {
@ -1376,48 +1375,37 @@ bool Effect::ProcessPass()
mSampleCnt = left->TimeToLongSamples(mDuration); mSampleCnt = left->TimeToLongSamples(mDuration);
} }
mNumChannels = 1; mNumChannels = 0;
WaveTrack *right{};
if (left->GetChannel() == Track::LeftChannel) // Iterate either over one track which could be any channel,
{ // or if multichannel, then over all channels of left,
map[0] = ChannelNameFrontLeft; // which is a leader.
} for (auto channel :
else if (left->GetChannel() == Track::RightChannel) TrackList::Channels(left).StartingWith(left)) {
{ if (channel->GetChannel() == Track::LeftChannel)
map[0] = ChannelNameFrontRight; map[mNumChannels] = ChannelNameFrontLeft;
} else if (channel->GetChannel() == Track::RightChannel)
map[mNumChannels] = ChannelNameFrontRight;
else else
{ map[mNumChannels] = ChannelNameMono;
map[0] = ChannelNameMono;
}
map[1] = ChannelNameEOL;
right = NULL; ++ mNumChannels;
rightStart = 0; map[mNumChannels] = ChannelNameEOL;
if (left->GetLinked() && multichannel)
{ if (! multichannel)
// Assume linked track is wave break;
right = static_cast<WaveTrack *>(left->GetLink());
if (!isGenerator) if (mNumChannels == 2) {
{ // TODO: more-than-two-channels
GetSamples(right, &rightStart, &len); right = channel;
}
clear = false; clear = false;
mNumChannels = 2; if (!isGenerator)
GetSamples(right, &rightStart, &len);
if (right->GetChannel() == Track::LeftChannel) // Ignore other channels
{ break;
map[1] = ChannelNameFrontLeft;
} }
else if (right->GetChannel() == Track::RightChannel)
{
map[1] = ChannelNameFrontRight;
}
else
{
map[1] = ChannelNameMono;
}
map[2] = ChannelNameEOL;
} }
// Let the client know the sample rate // Let the client know the sample rate

View File

@ -75,24 +75,20 @@ bool EffectStereoToMono::Process()
this->CopyInputTracks(); // Set up mOutputTracks. this->CopyInputTracks(); // Set up mOutputTracks.
bool bGoodResult = true; bool bGoodResult = true;
auto trackRange = mOutputTracks->Selected< WaveTrack >(); auto trackRange = mOutputTracks->SelectedLeaders< WaveTrack >();
mLeftTrack = *trackRange.first;
bool refreshIter = false; bool refreshIter = false;
if(mLeftTrack)
{
// create a NEW WaveTrack to hold all of the output
AudacityProject *p = GetActiveProject();
mOutTrack = p->GetTrackFactory()->NewWaveTrack(floatSample, mLeftTrack->GetRate());
}
int count = 0; int count = 0;
while ( trackRange.first != trackRange.second ) { while ( trackRange.first != trackRange.second ) {
mLeftTrack = *trackRange.first; mLeftTrack = *trackRange.first;
if (mLeftTrack->GetLinked()) { auto channels = TrackList::Channels( mLeftTrack );
if (channels.size() != 2) {
// TODO: more-than-two-channels
++ trackRange.first;
continue;
}
// Assume linked track is wave mRightTrack = * channels.rbegin();
mRightTrack = * ++ trackRange.first;
if ((mLeftTrack->GetRate() == mRightTrack->GetRate())) { if ((mLeftTrack->GetRate() == mRightTrack->GetRate())) {
auto leftTrackStart = mLeftTrack->TimeToLongSamples(mLeftTrack->GetStartTime()); auto leftTrackStart = mLeftTrack->TimeToLongSamples(mLeftTrack->GetStartTime());
@ -107,15 +103,12 @@ bool EffectStereoToMono::Process()
if (!bGoodResult) if (!bGoodResult)
break; break;
mOutTrack->Clear(mOutTrack->GetStartTime(), mOutTrack->GetEndTime());
// The right channel has been deleted, so we must restart from the beginning // The right channel has been deleted, so we must restart from the beginning
refreshIter = true; refreshIter = true;
} }
}
if (refreshIter) { if (refreshIter) {
trackRange = mOutputTracks->Selected< WaveTrack >(); trackRange = mOutputTracks->SelectedLeaders< WaveTrack >();
refreshIter = false; refreshIter = false;
} }
else else
@ -128,11 +121,6 @@ bool EffectStereoToMono::Process()
return bGoodResult; return bGoodResult;
} }
void EffectStereoToMono::End()
{
mOutTrack.reset();
}
bool EffectStereoToMono::ProcessOne(int count) bool EffectStereoToMono::ProcessOne(int count)
{ {
float curLeftFrame; float curLeftFrame;
@ -145,6 +133,10 @@ bool EffectStereoToMono::ProcessOne(int count)
Floats rightBuffer{ idealBlockLen }; Floats rightBuffer{ idealBlockLen };
bool bResult = true; bool bResult = true;
AudacityProject *p = GetActiveProject();
auto outTrack =
p->GetTrackFactory()->NewWaveTrack(floatSample, mLeftTrack->GetRate());
while (index < mEnd) { while (index < mEnd) {
bResult &= mLeftTrack->Get((samplePtr)leftBuffer.get(), floatSample, index, idealBlockLen); bResult &= mLeftTrack->Get((samplePtr)leftBuffer.get(), floatSample, index, idealBlockLen);
bResult &= mRightTrack->Get((samplePtr)rightBuffer.get(), floatSample, index, idealBlockLen); bResult &= mRightTrack->Get((samplePtr)rightBuffer.get(), floatSample, index, idealBlockLen);
@ -156,15 +148,15 @@ bool EffectStereoToMono::ProcessOne(int count)
curMonoFrame = (curLeftFrame + curRightFrame) / 2.0; curMonoFrame = (curLeftFrame + curRightFrame) / 2.0;
leftBuffer[i] = curMonoFrame; leftBuffer[i] = curMonoFrame;
} }
mOutTrack->Append((samplePtr)leftBuffer.get(), floatSample, limit); outTrack->Append((samplePtr)leftBuffer.get(), floatSample, limit);
if (TrackProgress(count, 2.*(index.as_double() / (mEnd - mStart).as_double()))) if (TrackProgress(count, 2.*(index.as_double() / (mEnd - mStart).as_double())))
return false; return false;
} }
double minStart = wxMin(mLeftTrack->GetStartTime(), mRightTrack->GetStartTime()); double minStart = wxMin(mLeftTrack->GetStartTime(), mRightTrack->GetStartTime());
mLeftTrack->Clear(mLeftTrack->GetStartTime(), mLeftTrack->GetEndTime()); mLeftTrack->Clear(mLeftTrack->GetStartTime(), mLeftTrack->GetEndTime());
mOutTrack->Flush(); outTrack->Flush();
mLeftTrack->Paste(minStart, mOutTrack.get()); mLeftTrack->Paste(minStart, outTrack.get());
mLeftTrack->SetLinked(false); mLeftTrack->SetLinked(false);
mRightTrack->SetLinked(false); mRightTrack->SetLinked(false);
mLeftTrack->SetChannel(Track::MonoChannel); mLeftTrack->SetChannel(Track::MonoChannel);

View File

@ -41,7 +41,6 @@ public:
// Effect implementation // Effect implementation
bool Process() override; bool Process() override;
void End() override;
bool IsHidden() override; bool IsHidden() override;
private: private:
@ -54,7 +53,6 @@ private:
sampleCount mEnd; sampleCount mEnd;
WaveTrack *mLeftTrack; WaveTrack *mLeftTrack;
WaveTrack *mRightTrack; WaveTrack *mRightTrack;
std::unique_ptr<WaveTrack> mOutTrack;
}; };
#endif #endif

View File

@ -769,7 +769,7 @@ bool NyquistEffect::Process()
Effect::MessageBox(message, wxOK | wxCENTRE | wxICON_EXCLAMATION, _("Nyquist Error")); Effect::MessageBox(message, wxOK | wxCENTRE | wxICON_EXCLAMATION, _("Nyquist Error"));
} }
auto trackRange = mOutputTracks->Selected< WaveTrack >(); auto trackRange = mOutputTracks->Selected< WaveTrack >() + &Track::IsLeader;
// Keep track of whether the current track is first selected in its sync-lock group // Keep track of whether the current track is first selected in its sync-lock group
// (we have no idea what the length of the returned audio will be, so we have // (we have no idea what the length of the returned audio will be, so we have
@ -785,10 +785,14 @@ bool NyquistEffect::Process()
if (bOnePassTool) { if (bOnePassTool) {
} }
else { else {
if (mCurTrack[0]->GetLinked()) { auto channels = TrackList::Channels(mCurTrack[0]);
if (channels.size() > 1) {
// TODO: more-than-two-channels
// Pay attention to consistency of mNumSelectedChannels
// with the running tally made by this loop!
mCurNumChannels = 2; mCurNumChannels = 2;
mCurTrack[1] = * ++ iter; mCurTrack[1] = * ++ channels.first;
if (mCurTrack[1]->GetRate() != mCurTrack[0]->GetRate()) { if (mCurTrack[1]->GetRate() != mCurTrack[0]->GetRate()) {
Effect::MessageBox(_("Sorry, cannot apply effect on stereo tracks where the tracks don't match."), Effect::MessageBox(_("Sorry, cannot apply effect on stereo tracks where the tracks don't match."),
wxOK | wxCENTRE); wxOK | wxCENTRE);