mirror of
				https://github.com/cookiengineer/audacity
				synced 2025-10-31 14:13:50 +01:00 
			
		
		
		
	Update to non-real-time preview.
Fixes and updates on top of some code clean-up from Leland.
This commit is contained in:
		| @@ -1,6 +1,8 @@ | ||||
| ;nyquist plug-in | ||||
| ;version 3 | ||||
| ;version 4 | ||||
| ;type process | ||||
| ;preview linear | ||||
| ;preview selection | ||||
| ;categories "http://lv2plug.in/ns/lv2core#MixerPlugin" | ||||
| ;name "Adjustable Fade..." | ||||
| ;action "Applying Fade..." | ||||
| @@ -22,6 +24,19 @@ | ||||
| ;control preset "   Handy Presets\n(override controls)" choice "None Selected,Linear In,Linear Out,Exponential In,Exponential Out,Logarithmic In,Logarithmic Out,Rounded In,Rounded Out,Cosine In,Cosine Out,S-Curve In,S-Curve Out" 0 | ||||
|  | ||||
|  | ||||
| (defun get-input (sig) | ||||
| "When previewing, we only need to process preview length." | ||||
|   (if (get '*track* 'view)  ;NIL if preview | ||||
|       sig | ||||
|       (multichan-expand #'trim-input sig))) | ||||
|  | ||||
| (defun trim-input (sig) | ||||
| "Trim input when previewing." | ||||
|   (let ((dur (min (get-duration 1) | ||||
|                   (get '*project* 'preview-duration)))) | ||||
|     (setf sig (extract-abs 0 dur *track*)))) | ||||
|  | ||||
|  | ||||
| (setq err "") | ||||
| ; bad things may happen outside of the slider range. | ||||
| (setq curve (min 1 (max -1 (/ curve 100.0)))) | ||||
| @@ -57,7 +72,7 @@ | ||||
|  | ||||
| ;;; select and apply fade | ||||
| (defun fade (sig type curve g0 g1) | ||||
|   (mult sig | ||||
|   (mult (get-input sig) | ||||
|     (case preset | ||||
|       (0  (case type                  ; Custom fade | ||||
|             (0 (simple (min g0 g1) (max g0 g1) curve)) | ||||
| @@ -180,5 +195,5 @@ | ||||
|     (check-values gain0 gain1) | ||||
|     (setf err (format nil "~a" (invalid-string gain0 gain1)))) | ||||
|   (if (= (length err) 0) | ||||
|       (fade s type curve gain0 gain1) | ||||
|       (fade *track* type curve gain0 gain1) | ||||
|       (format nil "Error.~%~a." err))) | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| ;nyquist plug-in | ||||
| ;version 3 | ||||
| ;version 4 | ||||
| ;type process | ||||
| ;preview enabled | ||||
| ;preview linear | ||||
| ;categories "http://lv2plug.in/ns/lv2core#HighpassPlugin" | ||||
| ;name "High Pass Filter..." | ||||
| ;action "Performing High Pass Filter..." | ||||
| @@ -10,7 +10,7 @@ | ||||
|  | ||||
| ;; highpass.ny by Dominic Mazzoni | ||||
| ;; Modified by David R. Sky | ||||
| ;; Updated by Steve Daulton June 2012 | ||||
| ;; Updated by Steve Daulton June 2012, 2015. | ||||
| ;; Released under terms of the GNU General Public License version 2: | ||||
| ;; http://www.gnu.org/licenses/old-licenses/gpl-2.0.html . | ||||
|  | ||||
| @@ -20,6 +20,7 @@ | ||||
| ;;control q "Filter quality (Q) for 12 dB rolloff" real "" 0.7071 .1 20 | ||||
| ;control frequency "Cutoff frequency (Hz)" real "" 1000 1 20000 | ||||
|  | ||||
|  | ||||
| (cond  | ||||
|   ((> frequency (/ *sound-srate* 2)) | ||||
|     (format nil  | ||||
| @@ -35,4 +36,4 @@ | ||||
|   (T  | ||||
|     (funcall  | ||||
|       (nth rolloff '(hp highpass2 highpass4 highpass6 highpass8)) | ||||
|       s frequency))) | ||||
|       *track* frequency))) | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| ;nyquist plug-in | ||||
| ;version 3 | ||||
| ;version 4 | ||||
| ;type process | ||||
| ;preview enabled | ||||
| ;preview linear | ||||
| ;categories "http://lv2plug.in/ns/lv2core#LowpassPlugin" | ||||
| ;name "Low Pass Filter..." | ||||
| ;action "Performing Low Pass Filter..." | ||||
| @@ -35,4 +35,4 @@ | ||||
|   (T  | ||||
|     (funcall  | ||||
|       (nth rolloff '(lp lowpass2 lowpass4 lowpass6 lowpass8)) | ||||
|       s frequency))) | ||||
|       *track* frequency))) | ||||
|   | ||||
| @@ -32,6 +32,7 @@ greater use in future. | ||||
| #include <wx/tglbtn.h> | ||||
| #include <wx/timer.h> | ||||
| #include <wx/utils.h> | ||||
| #include <wx/log.h> | ||||
|  | ||||
| #include "audacity/ConfigInterface.h" | ||||
|  | ||||
| @@ -46,6 +47,7 @@ greater use in future. | ||||
| #include "../widgets/ProgressDialog.h" | ||||
| #include "../ondemand/ODManager.h" | ||||
| #include "TimeWarper.h" | ||||
| #include "nyquist/Nyquist.h" | ||||
|  | ||||
| #if defined(__WXMAC__) | ||||
| #include <wx/mac/private.h> | ||||
| @@ -91,8 +93,10 @@ Effect::Effect() | ||||
|    mT0 = 0.0; | ||||
|    mT1 = 0.0; | ||||
|    mDuration = 0.0; | ||||
|    mIsPreview = false; | ||||
|    mIsLinearEffect = false; | ||||
|    mPreviewWithNotSelected = false; | ||||
|    mPreviewFullSelection = false; | ||||
|    mNumTracks = 0; | ||||
|    mNumGroups = 0; | ||||
|    mProgress = NULL; | ||||
| @@ -734,7 +738,6 @@ void Effect::SetDuration(double seconds) | ||||
|  | ||||
|    mDuration = seconds; | ||||
|    mT1 = mT0 + mDuration; | ||||
|    mSetDuration = mDuration; | ||||
|  | ||||
|    mIsSelection = false; | ||||
|  | ||||
| @@ -1556,7 +1559,16 @@ bool Effect::ProcessTrack(int count, | ||||
|    bool isProcessor = GetType() == EffectTypeProcess; | ||||
|    if (isGenerator) | ||||
|    { | ||||
|       genLength = left->GetRate() * mDuration; | ||||
|       double genDur; | ||||
|       if (mIsPreview) { | ||||
|          gPrefs->Read(wxT("/AudioIO/EffectsPreviewLen"), &genDur, 6.0); | ||||
|          genDur = wxMin(mDuration, CalcPreviewInputLength(genDur)); | ||||
|       } | ||||
|       else { | ||||
|          genDur = mDuration; | ||||
|       } | ||||
|  | ||||
|       genLength = left->GetRate() * genDur; | ||||
|       delayRemaining = genLength; | ||||
|       cleared = true; | ||||
|  | ||||
| @@ -1827,11 +1839,13 @@ bool Effect::ProcessTrack(int count, | ||||
|  | ||||
|    if (isGenerator) | ||||
|    { | ||||
|       AudacityProject *p = GetActiveProject(); | ||||
|       StepTimeWarper *warper = new StepTimeWarper(mT0 + genLength, genLength - (mT1 - mT0)); | ||||
|  | ||||
|       // Transfer the data from the temporary tracks to the actual ones | ||||
|       genLeft->Flush(); | ||||
|       left->ClearAndPaste(mT0, mT1, genLeft, true, true, warper); | ||||
|       // mT1 gives us the new selection. We want to replace up to GetSel1(). | ||||
|       left->ClearAndPaste(mT0, p->GetSel1(), genLeft, true, true, warper); | ||||
|       delete genLeft; | ||||
|  | ||||
|       if (genRight) | ||||
| @@ -1952,6 +1966,12 @@ void Effect::SetLinearEffectFlag(bool linearEffectFlag) | ||||
|    mIsLinearEffect = linearEffectFlag; | ||||
| } | ||||
|  | ||||
| void Effect::SetPreviewFullSelectionFlag(bool previewDurationFlag) | ||||
| { | ||||
|    mPreviewFullSelection = previewDurationFlag; | ||||
| } | ||||
|  | ||||
|  | ||||
| void Effect::IncludeNotSelectedPreviewTracks(bool includeNotSelected) | ||||
| { | ||||
|    mPreviewWithNotSelected = includeNotSelected; | ||||
| @@ -2383,75 +2403,77 @@ void Effect::Preview(bool dryOnly) | ||||
|     else | ||||
|        wxLogDebug(wxT("Non-linear Effect")); | ||||
|  | ||||
|    if (mNumTracks==0) // nothing to preview | ||||
|    if (mNumTracks == 0) { // nothing to preview | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    wxWindow* FocusDialog = wxWindow::FindFocus(); | ||||
|    if (gAudioIO->IsBusy()) | ||||
|    if (gAudioIO->IsBusy()) { | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    wxWindow *FocusDialog = wxWindow::FindFocus(); | ||||
|  | ||||
|    double previewDuration; | ||||
|    bool isNyquist = (GetFamily().IsSameAs(NYQUISTEFFECTS_FAMILY))? true : false; | ||||
|    bool isGenerator = GetType() == EffectTypeGenerate; | ||||
|  | ||||
|    // Mix a few seconds of audio from all of the tracks | ||||
|    double previewLen = 6.0; | ||||
|    gPrefs->Read(wxT("/AudioIO/EffectsPreviewLen"), &previewLen); | ||||
|    double previewLen; | ||||
|    gPrefs->Read(wxT("/AudioIO/EffectsPreviewLen"), &previewLen, 6.0); | ||||
|  | ||||
|    double rate = mProjectRate; | ||||
|    double warpedPreviewLength = CalcPreviewInputLength(previewLen); | ||||
|    double t0 = mT0; | ||||
|    double t1 = t0 + warpedPreviewLength; | ||||
|  | ||||
|    // Generators can run without a selection. | ||||
|    if (GetType() == EffectTypeGenerate) { | ||||
|       // If a generator varies over time, it must use the selected duration. | ||||
|       // otherwise set it as a linear effect and process no more than the preview length. | ||||
|       // TODO: When previewing non-linear generate effect, calculate only the first 'preview length'. | ||||
|       // For generate effects derived from the Nyquist Prompt, the duration is unknow, so | ||||
|       // ensure that we have at least preview length to copy. | ||||
|       double dur = (mIsLinearEffect)? wxMin(mSetDuration, warpedPreviewLength) : | ||||
|                                       wxMax(mSetDuration, warpedPreviewLength); | ||||
|       t1 = t0 + dur; | ||||
|       this->SetDuration(dur); | ||||
|    if (isNyquist && isGenerator) { | ||||
|       previewDuration = CalcPreviewInputLength(previewLen); | ||||
|    } | ||||
|    else if (t1 > mT1) { | ||||
|    else { | ||||
|       previewDuration = wxMin(mDuration, CalcPreviewInputLength(previewLen)); | ||||
|    } | ||||
|  | ||||
|    double t1 = mT0 + previewDuration; | ||||
|  | ||||
|    if ((t1 > mT1) && !(isNyquist && isGenerator)) { | ||||
|       t1 = mT1; | ||||
|    } | ||||
|    if (t1 <= t0) | ||||
|  | ||||
|    if (t1 <= mT0) | ||||
|       return; | ||||
|  | ||||
|    bool success = true; | ||||
|    WaveTrack *mixLeft = NULL; | ||||
|    WaveTrack *mixRight = NULL; | ||||
|    double oldT0 = mT0; | ||||
|    double oldT1 = mT1; | ||||
|    // Most effects should stop at t1. | ||||
|    if (!mPreviewFullSelection) | ||||
|       mT1 = t1; | ||||
|  | ||||
|    // Save the original track list | ||||
|    TrackList *saveTracks = mTracks; | ||||
|  | ||||
|    // Linear Effect preview optimised by pre-mixing to one track. | ||||
|    // Generators need to generate per track. | ||||
|    if (mIsLinearEffect && !(GetType() == EffectTypeGenerate)) { | ||||
|       success = ::MixAndRender(mTracks, mFactory, rate, floatSample, t0, t1, | ||||
|                                &mixLeft, &mixRight); | ||||
|    } | ||||
|  | ||||
|    // Build new tracklist from rendering tracks | ||||
|    mTracks = new TrackList(); | ||||
|  | ||||
|    if (mIsLinearEffect && !(GetType() == EffectTypeGenerate)) { | ||||
|    // Linear Effect preview optimised by pre-mixing to one track. | ||||
|    // Generators need to generate per track. | ||||
|    if (mIsLinearEffect && !isGenerator) { | ||||
|       success = ::MixAndRender(saveTracks, mFactory, rate, floatSample, mT0, t1, | ||||
|                                &mixLeft, &mixRight); | ||||
|       if (!success) { | ||||
|          delete mTracks; | ||||
|          mTracks = saveTracks; | ||||
|          return; | ||||
|       } | ||||
|  | ||||
|       mixLeft->InsertSilence(0.0, mT0); | ||||
|       mixLeft->SetSelected(true); | ||||
|       mixLeft->SetDisplay(WaveTrack::NoDisplay); | ||||
|       mTracks->Add(mixLeft); | ||||
|       if (mixRight) { | ||||
|          mixRight->InsertSilence(0.0, mT0); | ||||
|          mixRight->SetSelected(true); | ||||
|          mTracks->Add(mixRight); | ||||
|       } | ||||
|  | ||||
|       // Reset t0 / t1 is required when source tracks have different start times. | ||||
|       t0 = mixLeft->GetStartTime(); | ||||
|       t1 = mixLeft->GetEndTime(); | ||||
|    } | ||||
|    else { | ||||
|       TrackListOfKindIterator iter(Track::Wave, saveTracks); | ||||
| @@ -2460,7 +2482,8 @@ void Effect::Preview(bool dryOnly) | ||||
|       { | ||||
|          WaveTrack *dest; | ||||
|          if (src->GetSelected() || mPreviewWithNotSelected) { | ||||
|             src->Copy(t0, t1, (Track **) &dest); | ||||
|             src->Copy(mT0, t1, (Track **) &dest); | ||||
|             dest->InsertSilence(0.0, mT0); | ||||
|             dest->SetSelected(src->GetSelected()); | ||||
|             dest->SetDisplay(WaveTrack::NoDisplay); | ||||
|             mTracks->Add(dest); | ||||
| @@ -2472,25 +2495,14 @@ void Effect::Preview(bool dryOnly) | ||||
|    // Update track/group counts | ||||
|    CountWaveTracks(); | ||||
|  | ||||
|    double t0save = mT0; | ||||
|    double t1save = mT1; | ||||
|  | ||||
|    if (mIsLinearEffect) { | ||||
|       mT0 = t0; | ||||
|       mT1 = t1; | ||||
|    } | ||||
|    else { | ||||
|       mT0 = 0; | ||||
|       mT1 = t1 - t0; | ||||
|    } | ||||
|  | ||||
|    // Apply effect | ||||
|  | ||||
|    if (!dryOnly) { | ||||
|       mProgress = new ProgressDialog(GetName(), | ||||
|             _("Preparing preview"), | ||||
|             pdlgHideCancelButton); // Have only "Stop" button. | ||||
|       mIsPreview = true; | ||||
|       success = Process(); | ||||
|       mIsPreview = false; | ||||
|       delete mProgress; | ||||
|       mProgress = NULL; | ||||
|    } | ||||
| @@ -2502,11 +2514,12 @@ void Effect::Preview(bool dryOnly) | ||||
|  | ||||
|       SelectedTrackListOfKindIterator iter(Track::Wave, mTracks); | ||||
|       WaveTrack *src = (WaveTrack *) iter.First(); | ||||
|       while (src) | ||||
|       { | ||||
|       while (src) { | ||||
|          playbackTracks.Add(src); | ||||
|          src = (WaveTrack *) iter.Next(); | ||||
|       } | ||||
|       if (isNyquist && isGenerator) | ||||
|          t1 = mT1; | ||||
|  | ||||
| #ifdef EXPERIMENTAL_MIDI_OUT | ||||
|       NoteTrackArray empty; | ||||
| @@ -2517,11 +2530,11 @@ void Effect::Preview(bool dryOnly) | ||||
| #ifdef EXPERIMENTAL_MIDI_OUT | ||||
|                                empty, | ||||
| #endif | ||||
|                                rate, mT0, mT1); | ||||
|                                rate, mT0, t1); | ||||
|  | ||||
|       if (token) { | ||||
|          int previewing = eProgressSuccess; | ||||
|  | ||||
| wxLogDebug(wxT("mT0 %.3f   t1 %.3f"),mT0,t1); | ||||
|          // The progress dialog must be deleted before stopping the stream | ||||
|          // to allow events to flow to the app during StopStream processing. | ||||
|          // The progress dialog blocks these events. | ||||
| @@ -2530,7 +2543,7 @@ void Effect::Preview(bool dryOnly) | ||||
|  | ||||
|          while (gAudioIO->IsStreamActive(token) && previewing == eProgressSuccess) { | ||||
|             ::wxMilliSleep(100); | ||||
|             previewing = progress->Update(gAudioIO->GetStreamTime() - mT0, mT1); | ||||
|             previewing = progress->Update(gAudioIO->GetStreamTime() - mT0, t1 - mT0); | ||||
|          } | ||||
|  | ||||
|          delete progress; | ||||
| @@ -2547,10 +2560,6 @@ void Effect::Preview(bool dryOnly) | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    // Restore original selection | ||||
|    mT0 = t0save; | ||||
|    mT1 = t1save; | ||||
|  | ||||
|    if (FocusDialog) { | ||||
|       FocusDialog->SetFocus(); | ||||
|    } | ||||
| @@ -2562,6 +2571,9 @@ void Effect::Preview(bool dryOnly) | ||||
|    delete mTracks; | ||||
|  | ||||
|    mTracks = saveTracks; | ||||
|    mT0 = oldT0; | ||||
|    mT1 = oldT1; | ||||
|  | ||||
|    // Effect is already inited; we call Process, End, and then Init | ||||
|    // again, so the state is exactly the way it was before Preview | ||||
|    // was called. | ||||
|   | ||||
| @@ -321,6 +321,10 @@ protected: | ||||
|    // To allow pre-mixing before Preview, set linearEffectFlag to true. | ||||
|    void SetLinearEffectFlag(bool linearEffectFlag); | ||||
|  | ||||
|    // Most effects only need to preview a short selection. However some | ||||
|    // (such as fade effects) need to know the full selection length. | ||||
|    void SetPreviewFullSelectionFlag(bool previewDurationFlag); | ||||
|  | ||||
|    // Most effects only require selected tracks to be copied for Preview. | ||||
|    // If IncludeNotSelectedPreviewTracks(true), then non-linear effects have | ||||
|    // preview copies of all wave tracks. | ||||
| @@ -400,12 +404,13 @@ private: | ||||
|  | ||||
|    bool mIsLinearEffect; | ||||
|    bool mPreviewWithNotSelected; | ||||
|    bool mPreviewFullSelection; | ||||
|  | ||||
|    bool mIsSelection; | ||||
|    double mDuration; | ||||
|    wxString mDurationFormat; | ||||
|    // mSetDuration should ONLY be set when SetDuration() is called. | ||||
|    double mSetDuration; | ||||
|  | ||||
|    bool mIsPreview; | ||||
|  | ||||
|    bool mUIDebug; | ||||
|  | ||||
|   | ||||
| @@ -1366,6 +1366,10 @@ void NyquistEffect::Parse(wxString line) | ||||
|          mEnablePreview = true; | ||||
|          SetLinearEffectFlag(true); | ||||
|       } | ||||
|       else if (tokens[1] == wxT("selection")) { | ||||
|          mEnablePreview = true; | ||||
|          SetPreviewFullSelectionFlag(true); | ||||
|       } | ||||
|       else if (tokens[1] == wxT("disabled") || tokens[1] == wxT("false")) { | ||||
|          mEnablePreview = false; | ||||
|       } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user