Track *SyncLockedTracksIterator::Prev(bool skiplinked) { Track *t = TrackListIterator::Prev(skiplinked); // // Ways to end a sync-locked group in reverse // // Beginning of tracks if (!t) return NULL; // In wave section, encounter a label track if (!mInLabelSection && t->GetKind() == Track::Label) { cur = NULL; return NULL; } #ifndef USE_MIDI // Encounter a non-wave non-label track if (t->GetKind() != Track::Wave && t->GetKind() != Track::Label) { cur = NULL; return NULL; } #endif // Otherwise, check if we're in the label section mInLabelSection = (t->GetKind() == Track::Label); return t; }
Track *SyncLockedTracksIterator::Next(bool skiplinked) { Track *t = TrackListIterator::Next(skiplinked); // // Ways to end a sync-locked group // // End of tracks if (!t) return NULL; // In the label section, encounter a non-label track if (mInLabelSection && t->GetKind() != Track::Label) { cur = NULL; return NULL; } // This code block stops a group when a NoteTrack is encountered #ifndef USE_MIDI // Encounter a non-wave non-label track if (t->GetKind() != Track::Wave && t->GetKind() != Track::Label) { cur = NULL; return NULL; } #endif // Otherwise, check if we're in the label section mInLabelSection = (t->GetKind() == Track::Label); return t; }
void ControlToolBar::EnableDisableButtons() { //TIDY-ME: Button logic could be neater. AudacityProject *p = GetActiveProject(); bool tracks = false; bool playing = mPlay->IsDown(); bool recording = mRecord->IsDown(); bool busy = gAudioIO->IsBusy() || playing || recording; // Only interested in audio type tracks if (p) { TrackListIterator iter( p->GetTracks() ); for (Track *t = iter.First(); t; t = iter.Next()) { if (t->GetKind() == Track::Wave #if defined(USE_MIDI) || t->GetKind() == Track::Note #endif ) { tracks = true; break; } } } mPlay->SetEnabled((!recording) || (tracks && !busy)); mRecord->SetEnabled(!busy && !playing); mStop->SetEnabled(busy); mRewind->SetEnabled(!busy); mFF->SetEnabled(tracks && !busy); mPause->SetEnabled(true); }
bool LabelDialog::TransferDataFromWindow() { int cnt = mData.size(); int i; TrackListIterator iter(mTracks); Track *t; int tndx = 0; // Clear all label tracks of labels for (t = iter.First(); t; t = iter.Next()) { if (t->GetKind() == Track::Label) { LabelTrack *lt = (LabelTrack *)t; tndx++; for (i = lt->GetNumLabels() - 1; i >= 0 ; i--) { lt->DeleteLabel(i); } } } // Create any added tracks while (tndx < (int)mTrackNames.GetCount() - 1) { // Extract the name wxString name = mTrackNames[tndx + 1].AfterFirst(wxT('-')).Mid(1); // Create the NEW track and add to track list auto newTrack = mFactory.NewLabelTrack(); newTrack->SetName(name); mTracks->Add(std::move(newTrack)); tndx++; } // Repopulate with updated labels for (i = 0; i < cnt; i++) { RowData &rd = mData[i]; // Look for track with matching index tndx = 1; for (t = iter.First(); t; t = iter.Next()) { if (t->GetKind() == Track::Label && rd.index == tndx++) { break; } } wxASSERT(t); if (!t) return false; // Add the label to it ((LabelTrack *) t)->AddLabel(rd.selectedRegion, rd.title); ((LabelTrack *) t)->Unselect(); } return true; }
bool EffectAutoDuck::Init() { mControlTrack = NULL; TrackListIterator iter(inputTracks()); Track *t = iter.First(); bool lastWasSelectedWaveTrack = false; const WaveTrack *controlTrackCandidate = NULL; while(t) { if (lastWasSelectedWaveTrack && !t->GetSelected() && t->GetKind() == Track::Wave) { // This could be the control track, so remember it controlTrackCandidate = (WaveTrack*)t; } lastWasSelectedWaveTrack = false; if (t->GetSelected()) { if (t->GetKind() == Track::Wave) { lastWasSelectedWaveTrack = true; } else { Effect::MessageBox( _("You selected a track which does not contain audio. AutoDuck can only process audio tracks."), /* i18n-hint: Auto duck is the name of an effect that 'ducks' (reduces the volume) * of the audio automatically when there is sound on another track. Not as * in 'Donald-Duck'!*/ wxICON_ERROR); return false; } } t = iter.Next(); } if (!controlTrackCandidate) { Effect::MessageBox( _("Auto Duck needs a control track which must be placed below the selected track(s)."), wxICON_ERROR); return false; } mControlTrack = controlTrackCandidate; return true; }
bool LabelDialog::TransferDataFromWindow() { int cnt = mData.GetCount(); int i; TrackListIterator iter(mTracks); Track *t; int tndx = 0; // Clear all label tracks of labels for (t = iter.First(); t; t = iter.Next()) { if (t->GetKind() == Track::Label) { LabelTrack *lt = (LabelTrack *)t; tndx++; for (i = lt->GetNumLabels() - 1; i >= 0 ; i--) { lt->DeleteLabel(i); } } } // Create any added tracks while (tndx < (int)mTrackNames.GetCount() - 1) { // Extract the name wxString name = mTrackNames[tndx + 1].AfterFirst(wxT('-')).Mid(1); // Create the new track and add to track list LabelTrack *newTrack = new LabelTrack(mDirManager); newTrack->SetName(name); mTracks->Add(newTrack); tndx++; } // Repopulate with updated labels for (i = 0; i < cnt; i++) { RowData *rd = mData[i]; // Look for track with matching index tndx = 1; for (t = iter.First(); t; t = iter.Next()) { if (t->GetKind() == Track::Label && rd->index == tndx++) { break; } } // Add the label to it if (!rd->title.IsEmpty()) { ((LabelTrack *) t)->AddLabel(rd->stime, rd->etime, rd->title); ((LabelTrack *) t)->Unselect(); } } return true; }
void ExportMultiple::CountTracksAndLabels() { mLabels = NULL; mNumLabels = 0; mNumWaveTracks = 0; Track* pTrack; for (pTrack = mIterator.First(mTracks); pTrack != NULL; pTrack = mIterator.Next()) { switch (pTrack->GetKind()) { // Count WaveTracks, and for linked pairs, count only the second of the pair. case Track::Wave: { if (pTrack->GetLinked() == false) mNumWaveTracks++; break; } case Track::Label: { // Supports only one LabelTrack. if (mLabels == NULL) { mLabels = (LabelTrack*)pTrack; mNumLabels = mLabels->GetNumLabels(); } break; } } } }
UIHandle::Result LabelDefaultClickHandle::Click (const TrackPanelMouseEvent &evt, AudacityProject *pProject) { using namespace RefreshCode; // Redraw to show the change of text box selection status UIHandle::Result result = RefreshAll; if (evt.event.LeftDown()) { SaveState( pProject ); TrackList *const tracks = pProject->GetTracks(); TrackListIterator iter(tracks); Track *n = iter.First(); while (n) { if (n->GetKind() == Track::Label && evt.pCell.get() != n) { LabelTrack *const lt = static_cast<LabelTrack*>(n); lt->ResetFlags(); lt->Unselect(); } n = iter.Next(); } } return result; }
void FreqWindow::GetAudio() { int selcount = 0; int i; bool warning = false; //wxLogDebug(wxT("Entering FreqWindow::GetAudio()")); TrackListIterator iter(p->GetTracks()); Track *t = iter.First(); while (t) { if (t->GetSelected() && t->GetKind() == Track::Wave) { WaveTrack *track = (WaveTrack *)t; if (selcount==0) { mRate = track->GetRate(); sampleCount start, end; start = track->TimeToLongSamples(p->mViewInfo.sel0); end = track->TimeToLongSamples(p->mViewInfo.sel1); mDataLen = (sampleCount)(end - start); if (mDataLen > 10485760) { warning = true; mDataLen = 10485760; } if (mBuffer) { delete [] mBuffer; } mBuffer = new float[mDataLen]; track->Get((samplePtr)mBuffer, floatSample, start, mDataLen); } else { if (track->GetRate() != mRate) { wxMessageBox(_("To plot the spectrum, all selected tracks must be the same sample rate.")); delete[] mBuffer; mBuffer = NULL; return; } sampleCount start; start = track->TimeToLongSamples(p->mViewInfo.sel0); float *buffer2 = new float[mDataLen]; track->Get((samplePtr)buffer2, floatSample, start, mDataLen); for(i=0; i<mDataLen; i++) mBuffer[i] += buffer2[i]; delete[] buffer2; } selcount++; } t = iter.Next(); } if (selcount == 0) return; if (warning) { wxString msg; msg.Printf(_("Too much audio was selected. Only the first %.1f seconds of audio will be analyzed."), (mDataLen / mRate)); //wxLogDebug(wxT("About to show length warning message")); wxMessageBox(msg); //wxLogDebug(wxT("Length warning message done")); } //wxLogDebug(wxT("Leaving FreqWindow::GetAudio()")); }
void ExportMultiple::CountTracksAndLabels() { mLabels = NULL; mNumLabels = 0; mNumWaveTracks = 0; Track* pTrack; for (pTrack = mIterator->First(mTracks); pTrack != NULL; pTrack = mIterator->Next()) { switch (pTrack->GetKind()) { // Count WaveTracks, and for linked pairs, count only the second of the pair. case Track::Wave: { if (!pTrack->GetMute() && !pTrack->GetLinked()) // Don't count muted tracks. mNumWaveTracks++; break; } // Only support one label track??? case Track::Label: { // Supports only one LabelTrack. if (mLabels == NULL) { mLabels = (LabelTrack*)pTrack; mNumLabels = mLabels->GetNumLabels(); } break; } } } }
int TrackList::GetNumExportChannels(bool selectionOnly) { /* counters for tracks panned different places */ int numLeft = 0; int numRight = 0; int numMono = 0; /* track iteration kit */ Track *tr; TrackListIterator iter; for (tr = iter.First(this); tr != NULL; tr = iter.Next()) { // Want only unmuted wave tracks. if ((tr->GetKind() != Track::Wave) || tr->GetMute()) continue; // do we only want selected ones? if (selectionOnly && !(tr->GetSelected())) { //want selected but this one is not continue; } // Found a left channel if (tr->GetChannel() == Track::LeftChannel) { numLeft++; } // Found a right channel else if (tr->GetChannel() == Track::RightChannel) { numRight++; } // Found a mono channel, but it may be panned else if (tr->GetChannel() == Track::MonoChannel) { float pan = ((WaveTrack*)tr)->GetPan(); // Figure out what kind of channel it should be if (pan == -1.0) { // panned hard left numLeft++; } else if (pan == 1.0) { // panned hard right numRight++; } else if (pan == 0) { // panned dead center numMono++; } else { // panned somewhere else numLeft++; numRight++; } } } // if there is stereo content, report 2, else report 1 if (numRight > 0 || numLeft > 0) { return 2; } return 1; }
bool ODTask::IsTaskAssociatedWithProject(AudacityProject* proj) { TrackList *tracks = proj->GetTracks(); TrackListIterator iter1(tracks); Track *tr = iter1.First(); while (tr) { //go over all tracks in the project if (tr->GetKind() == Track::Wave) { //look inside our task's track list for one that matches this projects one. mWaveTrackMutex.Lock(); for(int i=0;i<(int)mWaveTracks.size();i++) { if(mWaveTracks[i]==tr) { //if we find one, then the project is associated with us;return true mWaveTrackMutex.Unlock(); return true; } } mWaveTrackMutex.Unlock(); } tr = iter1.Next(); } return false; }
int ExportMultiple::ShowModal() { Track *tr; mLabels = NULL; mNumLabels = 0; mNumTracks = 0; // Examine the track list looking for Wave and Label tracks for (tr = mIterator.First(mTracks); tr != NULL; tr = mIterator.Next()) { switch (tr->GetKind()) { // Only count WaveTracks, and for linked pairs, only count the // second one of the pair case Track::Wave: { if (tr->GetLinked() == false) { mNumTracks++; } break; } // Only support one label track??? case Track::Label: { if (mLabels == NULL) { mLabels = (LabelTrack *)tr; mNumLabels = mLabels->GetNumLabels(); } break; } } } if (mNumTracks < 2 && mNumLabels < 1) { ::wxMessageBox(_("If you have more than one Audio Track, you can export each track as a separate file,\nor if you have a Label Track, you can export a new file for each label.\n\nThis project does not have multiple tracks or a Label Track, so you cannot export multiple files."), _("Can't export multiple files"), wxOK | wxCENTRE, this); return wxID_CANCEL; } if (mNumLabels < 1) { mLabel->Enable(false); mTrack->SetValue(true); mLabel->SetValue(false); } if (mNumTracks < 2) { mTrack->Enable(false); mLabel->SetValue(true); mTrack->SetValue(false); } EnableControls(); return wxDialog::ShowModal(); }
void FreqWindow::GetAudio() { mData.reset(); mDataLen = 0; int selcount = 0; bool warning = false; TrackListIterator iter(p->GetTracks()); Track *t = iter.First(); while (t) { if (t->GetSelected() && t->GetKind() == Track::Wave) { WaveTrack *track = (WaveTrack *)t; if (selcount==0) { mRate = track->GetRate(); auto start = track->TimeToLongSamples(p->mViewInfo.selectedRegion.t0()); auto end = track->TimeToLongSamples(p->mViewInfo.selectedRegion.t1()); auto dataLen = end - start; if (dataLen > 10485760) { warning = true; mDataLen = 10485760; } else // dataLen is not more than 10 * 2 ^ 20 mDataLen = dataLen.as_size_t(); mData = Floats{ mDataLen }; // Don't allow throw for bad reads track->Get((samplePtr)mData.get(), floatSample, start, mDataLen, fillZero, false); } else { if (track->GetRate() != mRate) { AudacityMessageBox(_("To plot the spectrum, all selected tracks must be the same sample rate.")); mData.reset(); mDataLen = 0; return; } auto start = track->TimeToLongSamples(p->mViewInfo.selectedRegion.t0()); Floats buffer2{ mDataLen }; // Again, stop exceptions track->Get((samplePtr)buffer2.get(), floatSample, start, mDataLen, fillZero, false); for (size_t i = 0; i < mDataLen; i++) mData[i] += buffer2[i]; } selcount++; } t = iter.Next(); } if (selcount == 0) return; if (warning) { wxString msg; msg.Printf(_("Too much audio was selected. Only the first %.1f seconds of audio will be analyzed."), (mDataLen / mRate)); AudacityMessageBox(msg); } }
void ControlToolBar::EnableDisableButtons() { AudacityProject *p = GetActiveProject(); bool tracks = false; bool playing = mPlay->IsDown(); bool recording = mRecord->IsDown(); bool busy = gAudioIO->IsBusy(); // Only interested in audio type tracks if (p) { TrackListIterator iter( p->GetTracks() ); for (Track *t = iter.First(); t; t = iter.Next()) { if (t->GetKind() == Track::Wave #if defined(USE_MIDI) || t->GetKind() == Track::Note #endif ) { tracks = true; break; } } } if (p) { TranscriptionToolBar *const playAtSpeedTB = p->GetTranscriptionToolBar(); if (playAtSpeedTB) playAtSpeedTB->SetEnabled(CanStopAudioStream() && tracks && !recording); } mPlay->SetEnabled(CanStopAudioStream() && tracks && !recording); mRecord->SetEnabled( CanStopAudioStream() && !(busy && !recording) && !playing ); mStop->SetEnabled(CanStopAudioStream() && (playing || recording)); mRewind->SetEnabled(!playing && !recording); mFF->SetEnabled(tracks && !playing && !recording); auto pProject = GetActiveProject(); mPause->SetEnabled(CanStopAudioStream()); }
void ControlToolBar::EnableDisableButtons() { //TIDY-ME: Button logic could be neater. AudacityProject *p = GetActiveProject(); size_t numProjects = gAudacityProjects.Count(); bool tracks = false; bool cleaningSpeech = mBatch->IsDown(); bool playing = mPlay->IsDown(); bool recording = mRecord->IsDown(); bool busy = gAudioIO->IsBusy() || playing || recording; // Only interested in audio type tracks if (p) { TrackListIterator iter( p->GetTracks() ); for (Track *t = iter.First(); t; t = iter.Next()) { if (t->GetKind() == Track::Wave #if defined(USE_MIDI) || t->GetKind() == Track::Note #endif ) { tracks = true; break; } } } mPlay->SetEnabled((!recording) || (tracks && !busy && !cleaningSpeech)); mRecord->SetEnabled(!busy && !playing); if (p && GetActiveProject()->GetCleanSpeechMode()) { bool canRecord = !tracks; canRecord &= !cleaningSpeech; canRecord &= !busy; canRecord &= ((numProjects == 0) || ((numProjects == 1) && !tracks)); mRecord->SetEnabled(canRecord); mBatch->SetEnabled(!busy && !recording); } mStop->SetEnabled(busy && !cleaningSpeech); mRewind->SetEnabled(tracks && !busy); mFF->SetEnabled(tracks && !busy); mPause->SetEnabled(true); }
bool EffectReverse::Process() { //Track::All is needed because Reverse should move the labels too this->CopyInputTracks(Track::All); // Set up mOutputTracks. bool bGoodResult = true; TrackListIterator iter(mOutputTracks); Track *t = iter.First(); int count = 0; while (t) { if (t->GetKind() == Track::Wave && (t->GetSelected() || t->IsSyncLockSelected())) { WaveTrack *track = (WaveTrack*)t; if (mT1 > mT0) { sampleCount start = track->TimeToLongSamples(mT0); sampleCount end = track->TimeToLongSamples(mT1); sampleCount len = (sampleCount)(end - start); if (!ProcessOneWave(count, track, start, len)) { bGoodResult = false; break; } } } else if (t->GetKind() == Track::Label && (t->GetSelected() || t->IsSyncLockSelected())) { LabelTrack *track = (LabelTrack*)t; track->ChangeLabelsOnReverse(mT0, mT1); } t = iter.Next(); count++; } this->ReplaceProcessedTracks(bGoodResult); return bGoodResult; }
void ContrastDialog::OnUseSelectionB(wxCommandEvent & event) { AudacityProject *p = GetActiveProject(); TrackListIterator iter(p->GetTracks()); Track *t = iter.First(); while (t) { if (t->GetSelected() && t->GetKind() == Track::Wave) { mBackgroundStartT->SetTimeValue(p->mViewInfo.sel0); mBackgroundEndT->SetTimeValue(p->mViewInfo.sel1); break; } t = iter.Next(); } bBGset = true; OnGetBackgroundDB(event); }
void LabelDefaultClickHandle::SaveState( AudacityProject *pProject ) { mLabelState = std::make_shared<LabelState>(); auto &pairs = mLabelState->mPairs; TrackList *const tracks = pProject->GetTracks(); TrackListIterator iter(tracks); Track *n = iter.First(); while (n) { if (n->GetKind() == Track::Label) { LabelTrack *const lt = static_cast<LabelTrack*>(n); pairs.push_back( std::make_pair( Track::Pointer<LabelTrack>( lt ), lt->SaveFlags() ) ); } n = iter.Next(); } }
void LabelDialog::FindAllLabels() { TrackListIterator iter(mTracks); Track *t; // Add labels from all label tracks for (t = iter.First(); t; t = iter.Next()) { if (t->GetKind() == Track::Label) AddLabels(static_cast<LabelTrack *>(t)); } FindInitialRow(); if (mData.size() == 0) { wxCommandEvent e; OnInsert(e); } }
void LabelDialog::FindAllLabels() { TrackListIterator iter(mTracks); Track *t; mInitialRow = -1; // Add labels from all label tracks for (t = iter.First(); t; t = iter.Next()) { if (t->GetKind() == Track::Label) { AddLabels((LabelTrack *) t); } } if (mData.GetCount() == 0) { wxCommandEvent e; OnInsert(e); } }
void Effect::CountWaveTracks() { mNumTracks = 0; mNumGroups = 0; TrackListOfKindIterator iter(Track::Wave, mTracks); Track *t = iter.First(); while(t) { if (!t->GetSelected()) { t = iter.Next(); continue; } if (t->GetKind() == Track::Wave) { mNumTracks++; if (!t->GetLinked()) mNumGroups++; } t = iter.Next(); } }
void ControlToolBar::SetupCutPreviewTracks(double WXUNUSED(playStart), double cutStart, double cutEnd, double WXUNUSED(playEnd)) { ClearCutPreviewTracks(); AudacityProject *p = GetActiveProject(); if (p) { // Find first selected track (stereo or mono) and duplicate it Track *track1 = NULL, *track2 = NULL; TrackListIterator it(p->GetTracks()); for (Track *t = it.First(); t; t = it.Next()) { if (t->GetKind() == Track::Wave && t->GetSelected()) { track1 = t; track2 = t->GetLink(); break; } } if (track1) { // Duplicate and change tracks auto new1 = track1->Duplicate(); new1->Clear(cutStart, cutEnd); decltype(new1) new2{}; if (track2) { new2 = track2->Duplicate(); new2->Clear(cutStart, cutEnd); } mCutPreviewTracks = new TrackList(); mCutPreviewTracks->Add(std::move(new1)); if (track2) mCutPreviewTracks->Add(std::move(new2)); } } }
// Given a project, returns a single array of all SeqBlocks // in the current set of tracks. Enumerating that array allows // you to process all block files in the current set. void GetAllSeqBlocks(AudacityProject *project, BlockArray *outBlocks) { TrackList *tracks = project->GetTracks(); TrackListIterator iter(tracks); Track *t = iter.First(); while (t) { if (t->GetKind() == Track::Wave) { WaveTrack *waveTrack = (WaveTrack *)t; WaveClipList::compatibility_iterator node = waveTrack->GetClipIterator(); while(node) { WaveClip *clip = node->GetData(); Sequence *sequence = clip->GetSequence(); BlockArray *blocks = sequence->GetBlockArray(); int i; for (i = 0; i < (int)blocks->GetCount(); i++) outBlocks->Add(blocks->Item(i)); node = node->GetNext(); } } t = iter.Next(); } }
bool EffectAutoDuck::Process() { sampleCount i; if (GetNumWaveTracks() == 0 || !mControlTrack) return false; bool cancel = false; sampleCount start = mControlTrack->TimeToLongSamples(mT0 + mOuterFadeDownLen); sampleCount end = mControlTrack->TimeToLongSamples(mT1 - mOuterFadeUpLen); if (end <= start) return false; // the minimum number of samples we have to wait until the maximum // pause has been exceeded double maxPause = mMaximumPause; // We don't fade in until we have time enough to actually fade out again if (maxPause < mOuterFadeDownLen + mOuterFadeUpLen) maxPause = mOuterFadeDownLen + mOuterFadeUpLen; sampleCount minSamplesPause = mControlTrack->TimeToLongSamples(maxPause); double threshold = DB_TO_LINEAR(mThresholdDb); // adjust the threshold so we can compare it to the rmsSum value threshold = threshold * threshold * kRMSWindowSize; int rmsPos = 0; float rmsSum = 0; float *rmsWindow = new float[kRMSWindowSize]; for (i = 0; i < kRMSWindowSize; i++) rmsWindow[i] = 0; float *buf = new float[kBufSize]; bool inDuckRegion = false; // initialize the following two variables to prevent compiler warning double duckRegionStart = 0; sampleCount curSamplesPause = 0; // to make the progress bar appear more natural, we first look for all // duck regions and apply them all at once afterwards AutoDuckRegionArray regions; sampleCount pos = start; while (pos < end) { sampleCount len = end - pos; if (len > kBufSize) len = kBufSize; mControlTrack->Get((samplePtr)buf, floatSample, pos, (sampleCount)len); for (i = pos; i < pos + len; i++) { rmsSum -= rmsWindow[rmsPos]; rmsWindow[rmsPos] = buf[i - pos] * buf[i - pos]; rmsSum += rmsWindow[rmsPos]; rmsPos = (rmsPos + 1) % kRMSWindowSize; bool thresholdExceeded = rmsSum > threshold; if (thresholdExceeded) { // everytime the threshold is exceeded, reset our count for // the number of pause samples curSamplesPause = 0; if (!inDuckRegion) { // the threshold has been exceeded for the first time, so // let the duck region begin here inDuckRegion = true; duckRegionStart = mControlTrack->LongSamplesToTime(i); } } if (!thresholdExceeded && inDuckRegion) { // the threshold has not been exceeded and we are in a duck // region, but only fade in if the maximum pause has been // exceeded curSamplesPause += 1; if (curSamplesPause >= minSamplesPause) { // do the actual duck fade and reset all values double duckRegionEnd = mControlTrack->LongSamplesToTime(i - curSamplesPause); regions.Add(AutoDuckRegion( duckRegionStart - mOuterFadeDownLen, duckRegionEnd + mOuterFadeUpLen)); inDuckRegion = false; } } } pos += len; if (TotalProgress( ((double)(pos-start)) / (end-start) / (GetNumWaveTracks() + 1) )) { cancel = true; break; } } // apply last duck fade, if any if (inDuckRegion) { double duckRegionEnd = mControlTrack->LongSamplesToTime(end - curSamplesPause); regions.Add(AutoDuckRegion( duckRegionStart - mOuterFadeDownLen, duckRegionEnd + mOuterFadeUpLen)); } delete[] buf; delete[] rmsWindow; if (!cancel) { CopyInputTracks(); // Set up mOutputTracks. SelectedTrackListOfKindIterator iter(Track::Wave, mOutputTracks); Track *iterTrack = iter.First(); int trackNumber = 0; while (iterTrack) { wxASSERT(iterTrack->GetKind() == Track::Wave); WaveTrack* t = (WaveTrack*)iterTrack; for (i = 0; i < (int)regions.GetCount(); i++) { const AutoDuckRegion& region = regions[i]; if (ApplyDuckFade(trackNumber, t, region.t0, region.t1)) { cancel = true; break; } } if (cancel) break; iterTrack = iter.Next(); trackNumber++; } } ReplaceProcessedTracks(!cancel); return !cancel; }
bool EffectTruncSilence::DoRemoval (const RegionList &silences, unsigned iGroup, unsigned nGroups, Track *firstTrack, Track *lastTrack, double &totalCutLen) { // // Now remove the silent regions from all selected / sync-lock selected tracks. // // Loop over detected regions in reverse (so cuts don't change time values // down the line) int whichReg = 0; RegionList::const_reverse_iterator rit; for (rit = silences.rbegin(); rit != silences.rend(); ++rit) { const Region ®ion = *rit; const Region *const r = ®ion; // Progress dialog and cancellation. Do additional cleanup before return. const double frac = detectFrac + (1 - detectFrac) * (iGroup + whichReg / double(silences.size())) / nGroups; if (TotalProgress(frac)) { ReplaceProcessedTracks(false); return false; } // Intersection may create regions smaller than allowed; ignore them. // Allow one nanosecond extra for consistent results with exact milliseconds of allowed silence. if ((r->end - r->start) < (mInitialAllowedSilence - 0.000000001)) continue; // Find NEW silence length as requested double inLength = r->end - r->start; double outLength; switch (mActionIndex) { case kTruncate: outLength = std::min(mTruncLongestAllowedSilence, inLength); break; case kCompress: outLength = mInitialAllowedSilence + (inLength - mInitialAllowedSilence) * mSilenceCompressPercent / 100.0; break; default: // Not currently used. outLength = std::min(mInitialAllowedSilence + (inLength - mInitialAllowedSilence) * mSilenceCompressPercent / 100.0, mTruncLongestAllowedSilence); } double cutLen = inLength - outLength; totalCutLen += cutLen; TrackListIterator iterOut(mOutputTracks); bool lastSeen = false; for (Track *t = iterOut.StartWith(firstTrack); t && !lastSeen; t = iterOut.Next()) { lastSeen = (t == lastTrack); if (!(t->GetSelected() || t->IsSyncLockSelected())) continue; // Don't waste time past the end of a track if (t->GetEndTime() < r->start) continue; double cutStart = (r->start + r->end - cutLen) / 2; double cutEnd = cutStart + cutLen; if (t->GetKind() == Track::Wave) { // In WaveTracks, clear with a cross-fade WaveTrack *const wt = static_cast<WaveTrack*>(t); sampleCount blendFrames = mBlendFrameCount; // Round start/end times to frame boundaries cutStart = wt->LongSamplesToTime(wt->TimeToLongSamples(cutStart)); cutEnd = wt->LongSamplesToTime(wt->TimeToLongSamples(cutEnd)); // Make sure the cross-fade does not affect non-silent frames if (wt->LongSamplesToTime(blendFrames) > inLength) { blendFrames = wt->TimeToLongSamples(inLength); } // Perform cross-fade in memory float *buf1 = new float[blendFrames]; float *buf2 = new float[blendFrames]; sampleCount t1 = wt->TimeToLongSamples(cutStart) - blendFrames / 2; sampleCount t2 = wt->TimeToLongSamples(cutEnd) - blendFrames / 2; wt->Get((samplePtr)buf1, floatSample, t1, blendFrames); wt->Get((samplePtr)buf2, floatSample, t2, blendFrames); for (sampleCount i = 0; i < blendFrames; ++i) { buf1[i] = ((blendFrames-i) * buf1[i] + i * buf2[i]) / (double)blendFrames; } // Perform the cut wt->Clear(cutStart, cutEnd); // Write cross-faded data wt->Set((samplePtr)buf1, floatSample, t1, blendFrames); delete [] buf1; delete [] buf2; } else // Non-wave tracks: just do a sync-lock adjust t->SyncLockAdjust(cutEnd, cutStart); } ++whichReg; } return true; }
bool Generator::Process() { if (GetDuration() < 0.0) return false; // Set up mOutputTracks. // This effect needs Track::All for sync-lock grouping. this->CopyInputTracks(Track::All); // Iterate over the tracks bool bGoodResult = true; int ntrack = 0; TrackListIterator iter(mOutputTracks); Track* t = iter.First(); while (t != NULL) { if (t->GetKind() == Track::Wave && t->GetSelected()) { WaveTrack* track = (WaveTrack*)t; bool editClipCanMove; gPrefs->Read(wxT("/GUI/EditClipCanMove"), &editClipCanMove, true); //if we can't move clips, and we're generating into an empty space, //make sure there's room. if (!editClipCanMove && track->IsEmpty(mT0, mT1+1.0/track->GetRate()) && !track->IsEmpty(mT0, mT0+GetDuration()-(mT1-mT0)-1.0/track->GetRate())) { wxMessageBox( _("There is not enough room available to generate the audio"), _("Error"), wxICON_STOP); Failure(); return false; } if (GetDuration() > 0.0) { AudacityProject *p = GetActiveProject(); // Create a temporary track std::unique_ptr<WaveTrack> tmp( mFactory->NewWaveTrack(track->GetSampleFormat(), track->GetRate()) ); BeforeTrack(*track); BeforeGenerate(); // Fill it with data if (!GenerateTrack(&*tmp, *track, ntrack)) bGoodResult = false; else { // Transfer the data from the temporary track to the actual one tmp->Flush(); SetTimeWarper(new StepTimeWarper(mT0+GetDuration(), GetDuration()-(mT1-mT0))); bGoodResult = track->ClearAndPaste(p->GetSel0(), p->GetSel1(), &*tmp, true, false, GetTimeWarper()); } if (!bGoodResult) { Failure(); return false; } } else { // If the duration is zero, there's no need to actually // generate anything track->Clear(mT0, mT1); } ntrack++; } else if (t->IsSyncLockSelected()) { t->SyncLockAdjust(mT1, mT0 + GetDuration()); } // Move on to the next track t = iter.Next(); } Success(); this->ReplaceProcessedTracks(bGoodResult); mT1 = mT0 + GetDuration(); // Update selection. return true; }
bool EffectChangeSpeed::Process() { // Similar to EffectSoundTouch::Process() // Iterate over each track. // Track::All is needed because this effect needs to introduce // silence in the sync-lock group tracks to keep sync this->CopyInputTracks(Track::All); // Set up mOutputTracks. bool bGoodResult = true; TrackListIterator iter(mOutputTracks); Track* t; mCurTrackNum = 0; mMaxNewLength = 0.0; mFactor = 100.0 / (100.0 + mPercentChange); t = iter.First(); while (t != NULL) { if (t->GetKind() == Track::Label) { if (t->GetSelected() || t->IsSyncLockSelected()) { if (!ProcessLabelTrack(t)) { bGoodResult = false; break; } } } else if (t->GetKind() == Track::Wave && t->GetSelected()) { WaveTrack *pOutWaveTrack = (WaveTrack*)t; //Get start and end times from track mCurT0 = pOutWaveTrack->GetStartTime(); mCurT1 = pOutWaveTrack->GetEndTime(); //Set the current bounds to whichever left marker is //greater and whichever right marker is less: mCurT0 = wxMax(mT0, mCurT0); mCurT1 = wxMin(mT1, mCurT1); // Process only if the right marker is to the right of the left marker if (mCurT1 > mCurT0) { //Transform the marker timepoints to samples sampleCount start = pOutWaveTrack->TimeToLongSamples(mCurT0); sampleCount end = pOutWaveTrack->TimeToLongSamples(mCurT1); //ProcessOne() (implemented below) processes a single track if (!ProcessOne(pOutWaveTrack, start, end)) { bGoodResult = false; break; } } mCurTrackNum++; } else if (t->IsSyncLockSelected()) { t->SyncLockAdjust(mT1, mT0 + (mT1 - mT0) * mFactor); } //Iterate to the next track t=iter.Next(); } if (bGoodResult) ReplaceProcessedTracks(bGoodResult); mT1 = mT0 + mMaxNewLength; // Update selection. return bGoodResult; }
//------------------------- Processing methods ------------------------- bool EffectSineSweepGenerator::Process() { // taken `as is` from Audacity`s Generator.cpp to resolve // a vc++ linking problem... if (mDuration < 0.0) return false; BeforeGenerate(); // Set up mOutputTracks. This effect needs Track::All for grouping this->CopyInputTracks(Track::All); // Iterate over the tracks bool bGoodResult = true; int ntrack = 0; TrackListIterator iter(mOutputTracks); Track* t = iter.First(); while (t != NULL) { if (t->GetKind() == Track::Wave && t->GetSelected()) { WaveTrack* track = (WaveTrack*)t; bool editClipCanMove = true; //gPrefs->Read(wxT("/GUI/EditClipCanMove"), &editClipCanMove, true); //if we can't move clips, and we're generating into an empty space, //make sure there's room. if (!editClipCanMove && track->IsEmpty(mT0, mT1+1.0/track->GetRate()) && !track->IsEmpty(mT0, mT0+mDuration-(mT1-mT0)-1.0/track->GetRate())) { wxMessageBox(_("There is not enough room available to generate the audio"), _("Error"), wxICON_STOP); Failure(); return false; } if (mDuration > 0.0) { // Create a temporary track WaveTrack *tmp = mFactory->NewWaveTrack(track->GetSampleFormat(), track->GetRate()); //BeforeTrack(*track); // Fill it with data if (!GenerateTrack(tmp, *track, ntrack)) bGoodResult = false; else { // Transfer the data from the temporary track to the actual one tmp->Flush(); SetTimeWarper(new AFStepTimeWarper(mT0+mDuration, mDuration-(mT1-mT0))); bGoodResult = track->ClearAndPaste(mT0, mT1, tmp, true, false, GetTimeWarper()); delete tmp; } if (!bGoodResult) { Failure(); return false; } } else { // If the duration is zero, there's no need to actually // generate anything track->Clear(mT0, mT1); } ntrack++; } else if (t->IsSyncLockSelected()) { t->SyncLockAdjust(mT1, mT0 + mDuration); } // Move on to the next track t = iter.Next(); } Success(); this->ReplaceProcessedTracks(bGoodResult); mT1 = mT0 + mDuration; // Update selection. return true; }
// Gets the name of the specified object. wxAccStatus TrackPanelAx::GetName( int childId, wxString* name ) { #if defined(__WXMSW__) if( childId == wxACC_SELF ) { *name = _( "TrackView" ); } else { Track *t = FindTrack( childId ); if( t == NULL ) { return wxACC_FAIL; } else { *name = t->GetName(); if( *name == t->GetDefaultName() ) { /* i18n-hint: The %d is replaced by th enumber of the track.*/ name->Printf(_("Track %d"), TrackNum( t ) ); } if (t->GetKind() == Track::Label) { /* i18n-hint: This is for screen reader software and indicates that this is a Label track.*/ name->Append( wxT(" ") + wxString(_("Label Track"))); } else if (t->GetKind() == Track::Time) { /* i18n-hint: This is for screen reader software and indicates that this is a Time track.*/ name->Append( wxT(" ") + wxString(_("Time Track"))); } else if (t->GetKind() == Track::Note) { /* i18n-hint: This is for screen reader software and indicates that this is a Note track.*/ name->Append( wxT(" ") + wxString(_("Note Track"))); } // LLL: Remove these during "refactor" if( t->GetMute() ) { // The following comment also applies to the solo, selected, // and synclockselected states. // Many of translations of the strings with a leading space omitted // the leading space. Therefore a space has been added using wxT(" "). // Because screen readers won't be affected by multiple spaces, the // leading spaces have not been removed, so that no new translations are needed. /* i18n-hint: This is for screen reader software and indicates that on this track mute is on.*/ name->Append( wxT(" ") + wxString(_( " Mute On" )) ); } if( t->GetSolo() ) { /* i18n-hint: This is for screen reader software and indicates that on this track solo is on.*/ name->Append( wxT(" ") + wxString(_( " Solo On" )) ); } if( t->GetSelected() ) { /* i18n-hint: This is for screen reader software and indicates that this track is selected.*/ name->Append( wxT(" ") + wxString(_( " Select On" )) ); } if( t->IsSyncLockSelected() ) { /* i18n-hint: This is for screen reader software and indicates that this track is shown with a sync-locked icon.*/ // The absence of a dash between Sync and Locked is deliberate - // if present, Jaws reads it as "dash". name->Append( wxT(" ") + wxString(_( " Sync Lock Selected" )) ); } } } return wxACC_OK; #endif #if defined(__WXMAC__) return wxACC_NOT_IMPLEMENTED; #endif }