From f209391d592ed14ff4c9ef4e2539149c2fdceb01 Mon Sep 17 00:00:00 2001 From: martynshaw99 Date: Thu, 30 May 2013 23:14:25 +0000 Subject: [PATCH] John (Thales) code to make the waveform display look like the output of the gain and pan sliders, rather than the input. Added as EXPERIMENTAL_OUTPUT_DISPLAY since there is work to do, but I think this deserves wider input/views. --- src/Experimental.h | 3 + src/Printing.cpp | 12 ++ src/Track.cpp | 108 ++++++++++++- src/Track.h | 23 ++- src/TrackArtist.cpp | 57 ++++++- src/TrackArtist.h | 9 +- src/TrackPanel.cpp | 338 ++++++++++++++++++++++++++++++++++++++++- src/TrackPanel.h | 3 + src/WaveTrack.cpp | 100 ++++++++++++ src/prefs/GUIPrefs.cpp | 6 + 10 files changed, 642 insertions(+), 17 deletions(-) diff --git a/src/Experimental.h b/src/Experimental.h index 836b4b05a..a65d79dc9 100644 --- a/src/Experimental.h +++ b/src/Experimental.h @@ -150,4 +150,7 @@ //#define AUTOMATED_INPUT_LEVEL_ADJUSTMENT #endif +// John (Thales) work to make the display show the result of the pan and gain sliders, rather than their input. +// First committed by Martyn, 30th May 2013. +#define EXPERIMENTAL_OUTPUT_DISPLAY #endif diff --git a/src/Printing.cpp b/src/Printing.cpp index edccd62d7..b968e9527 100644 --- a/src/Printing.cpp +++ b/src/Printing.cpp @@ -102,6 +102,18 @@ bool AudacityPrintout::OnPrintPage(int page) dc->SetPen(*wxBLACK_PEN); AColor::Line(*dc, 0, r.y, width, r.y); +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + if(MONO_WAVE_PAN(n)){ + y += r.height; + r.x = 0; + r.y = y; + r.width = width; + r.height = (int)(n->GetHeight(true) * scale); + artist.DrawTrack(n, *dc, r, &viewInfo, false, false, false, false); + dc->SetPen(*wxBLACK_PEN); + AColor::Line(*dc, 0, r.y, width, r.y); + } +#endif n = iter.Next(); y += r.height; }; diff --git a/src/Track.cpp b/src/Track.cpp index a4c8bc79e..142005661 100644 --- a/src/Track.cpp +++ b/src/Track.cpp @@ -55,7 +55,13 @@ Track::Track(DirManager * projDirManager) mY = 0; mHeight = 150; mIndex = 0; - +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + mYv = mHeight; + mHeightv = mHeight; + mPerY = 0.5; + mVirtualStereo = false; +#endif + mMinimized = false; mOffset = 0.0; @@ -71,7 +77,9 @@ Track::Track(const Track &orig) mNode = NULL; mY = 0; mIndex = 0; - +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + mPerY = 0.5; +#endif Init(orig); mOffset = orig.mOffset; } @@ -99,6 +107,11 @@ void Track::Init(const Track &orig) mHeight = orig.mHeight; mMinimized = orig.mMinimized; mChannel = orig.mChannel; +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + mVirtualStereo = orig.mVirtualStereo; + mHeightv = orig.mHeightv; + mYv = orig.mYv; +#endif } void Track::Merge(const Track &orig) @@ -152,6 +165,41 @@ void Track::SetIndex(int index) mIndex = index; } +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY +int Track::GetY(bool vStereo) const +{ + if(vStereo && mChannel == Track::MonoChannel) return mYv; + return mY; +} + +void Track::SetY(int y, bool vStereo) +{ + if(vStereo && mChannel == Track::MonoChannel) mYv = y; + else mY = y; +} + +int Track::GetHeight(bool vStereo) const +{ + if (mMinimized) { + return GetMinimizedHeight(); + } + + if(vStereo && mChannel == Track::MonoChannel) return mHeightv; + return mHeight; +} + +void Track::SetHeight(int h, bool vStereo) +{ + + if(vStereo && mChannel == Track::MonoChannel) mHeightv = h; + else mHeight = h; + + mList->RecalcPositions(mNode); + mList->ResizedEvent(mNode); +} + +#else // EXPERIMENTAL_OUTPUT_DISPLAY + int Track::GetY() const { return mY; @@ -177,6 +225,7 @@ void Track::SetHeight(int h) mList->RecalcPositions(mNode); mList->ResizedEvent(mNode); } +#endif // EXPERIMENTAL_OUTPUT_DISPLAY bool Track::GetMinimized() const { @@ -212,6 +261,15 @@ Track *Track::GetLink() const return NULL; } +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY +void Track::ReorderList(bool resize) +{ + mList->RecalcPositions(mNode); + if(resize) + mList->ResizedEvent(mNode); +} +#endif + bool Track::IsSyncLockSelected() { #ifdef EXPERIMENTAL_SYNC_LOCK @@ -664,6 +722,34 @@ void TrackList::RecalcPositions(const TrackListNode *node) return; } +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + int cnt = 0; + if (node->prev) { + t = node->prev->t; + i = t->GetIndex() + 1; + if(MONO_WAVE_PAN(t)) + y = t->GetY(true) + t->GetHeight(true); + else + y = t->GetY() + t->GetHeight(); + } + + for (const TrackListNode *n = node; n; n = n->next) { + t = n->t; + if(MONO_WAVE_PAN(t)) + cnt++; + + if(cnt != 2){ + t->SetIndex(i++); + t->SetY(y); + y += t->GetHeight(); + } + if(cnt != 0){ + t->SetY(y,true); + y += t->GetHeight(true); + } + cnt = 0; + } +#else // EXPERIMENTAL_OUTPUT_DISPLAY if (node->prev) { t = node->prev->t; i = t->GetIndex() + 1; @@ -676,6 +762,7 @@ void TrackList::RecalcPositions(const TrackListNode *node) t->SetY(y); y += t->GetHeight(); } +#endif // EXPERIMENTAL_OUTPUT_DISPLAY } void TrackList::UpdatedEvent(const TrackListNode *node) @@ -905,7 +992,11 @@ int TrackList::GetGroupHeight(Track * t) const if (t) { height += t->GetHeight(); } - +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + else if(MONO_WAVE_PAN(t)){ + height += t->GetHeight(true); + } +#endif return height; } @@ -1183,11 +1274,20 @@ int TrackList::GetHeight() const { int height = 0; +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + if (tail) { + const Track *t = tail->t; + if(MONO_WAVE_PAN(t)) + height = t->GetY(true) + t->GetHeight(true); + else + height = t->GetY() + t->GetHeight(); + } +#else if (tail) { const Track *t = tail->t; height = t->GetY() + t->GetHeight(); } - +#endif return height; } diff --git a/src/Track.h b/src/Track.h index 7ab346861..dd033b4ca 100644 --- a/src/Track.h +++ b/src/Track.h @@ -55,6 +55,12 @@ class AUDACITY_DLL_API Track: public XMLTagHandler int mIndex; int mY; int mHeight; +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + int mYv; //For mono a virtual Y value is necessary. + int mHeightv; // For mono a virtual height value is necessary. + float mPerY; //mY as a percent of mYv + mY + bool mVirtualStereo; +#endif wxString mName; wxString mDefaultName; @@ -73,13 +79,25 @@ class AUDACITY_DLL_API Track: public XMLTagHandler int GetIndex() const; void SetIndex(int index); +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + int GetY(bool vStereo = false) const; + void SetY(int y, bool vStereo = false); + int GetHeight(bool vStereo = false) const; + void SetHeight(int h, bool vStereo = false); +#else int GetY() const; void SetY(int y); int GetHeight() const; void SetHeight(int h); +#endif bool GetMinimized() const; void SetMinimized(bool isMinimized); - +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + float GetVirtualTrackPercentage() { return mPerY;} + void SetVirtualTrackPercentage(float val) { mPerY = val;} + bool GetVirtualStereo() { return mVirtualStereo;} + void SetVirtualStereo(bool vStereo) { mVirtualStereo = vStereo;} +#endif Track *GetLink() const; const TrackListNode *GetNode(); @@ -96,6 +114,9 @@ class AUDACITY_DLL_API Track: public XMLTagHandler mutable DirManager *mDirManager; public: +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + void ReorderList(bool resize = true); +#endif enum { diff --git a/src/TrackArtist.cpp b/src/TrackArtist.cpp index a27683085..54fb76907 100644 --- a/src/TrackArtist.cpp +++ b/src/TrackArtist.cpp @@ -363,6 +363,12 @@ void TrackArtist::DrawTracks(TrackList * tracks, stereoTrackRect.height += link->GetHeight(); } } +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + if(MONO_WAVE_PAN(t)){ + stereoTrackRect.height += t->GetHeight(true); + t->SetVirtualStereo(false); + } +#endif if (stereoTrackRect.Intersects(clip) && reg.Contains(stereoTrackRect)) { wxRect rr = trackRect; @@ -374,6 +380,26 @@ void TrackArtist::DrawTracks(TrackList * tracks, drawEnvelope, drawSamples, drawSliders, hasSolo); } +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + if(MONO_WAVE_PAN(t)){ + trackRect.y = t->GetY(true) - viewInfo->vpos; + trackRect.height = t->GetHeight(true); + stereoTrackRect = trackRect; + stereoTrackRect.y -= t->GetHeight(); + stereoTrackRect.height += t->GetHeight(); + t->SetVirtualStereo(true); + if (stereoTrackRect.Intersects(clip) && reg.Contains(stereoTrackRect)) { + wxRect rr = trackRect; + rr.x += mInsetLeft; + rr.y += mInsetTop; + rr.width -= (mInsetLeft + mInsetRight); + rr.height -= (mInsetTop + mInsetBottom); + DrawTrack(t, dc, rr, viewInfo, + drawEnvelope, drawSamples, drawSliders, hasSolo); + } + } +#endif + t = iter.Next(); } } @@ -983,10 +1009,18 @@ void TrackArtist::DrawWaveformBackground(wxDC &dc, const wxRect &r, const double } } + +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY +void TrackArtist::DrawMinMaxRMS(wxDC &dc, const wxRect &r, const double env[], + float zoomMin, float zoomMax, bool dB, + const float min[], const float max[], const float rms[], + const int bl[], bool showProgress, bool muted, const float gain) +#else void TrackArtist::DrawMinMaxRMS(wxDC &dc, const wxRect &r, const double env[], float zoomMin, float zoomMax, bool dB, const float min[], const float max[], const float rms[], const int bl[], bool showProgress, bool muted) +#endif { // Display a line representing the // min and max of the samples in this region @@ -1014,8 +1048,12 @@ void TrackArtist::DrawMinMaxRMS(wxDC &dc, const wxRect &r, const double env[], for (x = 0; x < r.width; x++) { int xx = r.x + x; double v; - +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + //JWA: "gain" variable passed to function includes the pan value and is used below 4/14/13 + v = min[x] * env[x] * gain; +#else v = min[x] * env[x]; +#endif if (clipped && mShowClipping && (v <= -MAX_AUDIO)) { if (clipcnt == 0 || clipped[clipcnt - 1] != xx) { @@ -1025,7 +1063,11 @@ void TrackArtist::DrawMinMaxRMS(wxDC &dc, const wxRect &r, const double env[], h1 = GetWaveYPos(v, zoomMin, zoomMax, r.height, dB, true, mdBrange, true); +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + v = max[x] * env[x] * gain; +#else v = max[x] * env[x]; +#endif if (clipped && mShowClipping && (v >= MAX_AUDIO)) { if (clipcnt == 0 || clipped[clipcnt - 1] != xx) { @@ -1048,11 +1090,17 @@ void TrackArtist::DrawMinMaxRMS(wxDC &dc, const wxRect &r, const double env[], lasth1 = h1; lasth2 = h2; +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + r1[x] = GetWaveYPos(-rms[x] * env[x]*gain, zoomMin, zoomMax, + r.height, dB, true, mdBrange, true); + r2[x] = GetWaveYPos(rms[x] * env[x]*gain, zoomMin, zoomMax, + r.height, dB, true, mdBrange, true); +#else r1[x] = GetWaveYPos(-rms[x] * env[x], zoomMin, zoomMax, r.height, dB, true, mdBrange, true); r2[x] = GetWaveYPos(rms[x] * env[x], zoomMin, zoomMax, r.height, dB, true, mdBrange, true); - +#endif // Make sure the rms isn't larger than the waveform min/max if (r1[x] > h1 - 1) { r1[x] = h1 - 1; @@ -1505,8 +1553,13 @@ void TrackArtist::DrawClipWaveform(WaveTrack *track, !track->GetSelected()); if (!showIndividualSamples) { +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + DrawMinMaxRMS(dc, mid, envValues, zoomMin, zoomMax, dB, + min, max, rms, bl, isLoadingOD, muted, track->GetChannelGain(track->GetChannel())); +#else DrawMinMaxRMS(dc, mid, envValues, zoomMin, zoomMax, dB, min, max, rms, bl, isLoadingOD, muted); +#endif } else { DrawIndividualSamples(dc, mid, zoomMin, zoomMax, dB, diff --git a/src/TrackArtist.h b/src/TrackArtist.h index 9642febb6..561c6eb06 100644 --- a/src/TrackArtist.h +++ b/src/TrackArtist.h @@ -152,12 +152,17 @@ class AUDACITY_DLL_API TrackArtist { const sampleCount where[], sampleCount ssel0, sampleCount ssel1, bool drawEnvelope, bool bIsSyncLockSelected); - +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + void DrawMinMaxRMS(wxDC & dc, const wxRect & r, const double env[], + float zoomMin, float zoomMax, bool dB, + const float min[], const float max[], const float rms[], + const int bl[], bool showProgress, bool muted, const float gain); +#else void DrawMinMaxRMS(wxDC & dc, const wxRect & r, const double env[], float zoomMin, float zoomMax, bool dB, const float min[], const float max[], const float rms[], const int bl[], bool showProgress, bool muted); - +#endif void DrawIndividualSamples(wxDC & dc, const wxRect & r, float zoomMin, float zoomMax, bool dB, WaveClip *clip, diff --git a/src/TrackPanel.cpp b/src/TrackPanel.cpp index 14e3578c0..1db36bdbd 100644 --- a/src/TrackPanel.cpp +++ b/src/TrackPanel.cpp @@ -734,6 +734,33 @@ void TrackPanel::DeleteMenus(void) } } +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY +void TrackPanel::UpdateVirtualStereoOrder() +{ + TrackListIterator iter(mTracks); + Track *t; + int temp; + + for (t = iter.First(); t; t = iter.Next()) { + if(t->GetKind() == Track::Wave && t->GetChannel() == Track::MonoChannel){ + WaveTrack *wt = (WaveTrack*)t; + + if(WaveTrack::mMonoAsVirtualStereo && wt->GetPan() != 0){ + temp = wt->GetHeight(); + wt->SetHeight(temp*wt->GetVirtualTrackPercentage()); + wt->SetHeight(temp - wt->GetHeight(),true); + }else if(!WaveTrack::mMonoAsVirtualStereo && wt->GetPan() != 0){ + wt->SetHeight(wt->GetHeight() + wt->GetHeight(true)); + } + } + } + t = iter.First(); + if(t){ + t->ReorderList(false); + } +} +#endif + void TrackPanel::UpdatePrefs() { mdBr = gPrefs->Read(wxT("/GUI/EnvdBRange"), ENV_DB_RANGE); @@ -749,6 +776,15 @@ void TrackPanel::UpdatePrefs() gPrefs->Read(wxT("/AudioIO/SeekLongPeriod"), &mSeekLong, 15.0); +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + bool temp = WaveTrack::mMonoAsVirtualStereo; + gPrefs->Read(wxT("/GUI/MonoAsVirtualStereo"), &WaveTrack::mMonoAsVirtualStereo, + false); + + if(WaveTrack::mMonoAsVirtualStereo != temp) + UpdateVirtualStereoOrder(); +#endif + if (mTrackArtist) { mTrackArtist->UpdatePrefs(); } @@ -1245,6 +1281,16 @@ void TrackPanel::DoDrawCursor(wxDC & dc) // MB: warp() is not needed here as far as I know, in fact it creates a bug. Removing it fixes that. AColor::Line( dc, x, top, x, bottom ); // <-- The whole point of this routine. + +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + if(MONO_WAVE_PAN(t)){ + y = t->GetY(true) - mViewInfo->vpos + 1; + top = y + kTopInset; + bottom = y + t->GetHeight(true) - kTopInset; + AColor::Line( dc, x, top, x, bottom ); + } +#endif + } } @@ -4091,6 +4137,9 @@ void TrackPanel::HandleMinimizing(wxMouseEvent & event) void TrackPanel::HandleSliders(wxMouseEvent &event, bool pan) { LWSlider *slider; +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + bool panZero = false; +#endif if (pan) slider = mTrackInfo.PanSlider(mCapturedTrack->GetIndex()); @@ -4111,10 +4160,18 @@ void TrackPanel::HandleSliders(wxMouseEvent &event, bool pan) WaveTrack *link = (WaveTrack *)mTracks->GetLink(mCapturedTrack); if (pan) { +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + panZero = ((WaveTrack *)mCapturedTrack)->SetPan(newValue); +#else ((WaveTrack *)mCapturedTrack)->SetPan(newValue); +#endif if (link) link->SetPan(newValue); +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + if(panZero) MakeParentRedrawScrollbars(); +#endif + if (pMixerBoard) pMixerBoard->UpdatePan((WaveTrack*)mCapturedTrack); } @@ -4546,12 +4603,51 @@ void TrackPanel::HandleResizeClick( wxMouseEvent & event ) return; } - Track *prev = mTracks->GetPrev(t); - Track *next = mTracks->GetNext(t); - mMouseClickX = event.m_x; mMouseClickY = event.m_y; +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + if(MONO_WAVE_PAN(t)){ + //STM: Determine whether we should rescale one or two tracks + if (t->GetVirtualStereo()) { + // mCapturedTrack is the lower track + mInitialTrackHeight = t->GetHeight(true); + mInitialUpperTrackHeight = t->GetHeight(); + SetCapturedTrack(t, IsResizingBelowLinkedTracks); + } + else { + // mCapturedTrack is the upper track + mInitialTrackHeight = t->GetHeight(true); + mInitialUpperTrackHeight = t->GetHeight(); + SetCapturedTrack(t, IsResizingBetweenLinkedTracks); + } + }else{ + Track *prev = mTracks->GetPrev(t); + Track *next = mTracks->GetNext(t); + + //STM: Determine whether we should rescale one or two tracks + if (prev && prev->GetLink() == t) { + // mCapturedTrack is the lower track + mInitialTrackHeight = t->GetHeight(); + mInitialUpperTrackHeight = prev->GetHeight(); + SetCapturedTrack(t, IsResizingBelowLinkedTracks); + } + else if (next && t->GetLink() == next) { + // mCapturedTrack is the upper track + mInitialTrackHeight = next->GetHeight(); + mInitialUpperTrackHeight = t->GetHeight(); + SetCapturedTrack(t, IsResizingBetweenLinkedTracks); + } + else { + // DM: Save the initial mouse location and the initial height + mInitialTrackHeight = t->GetHeight(); + SetCapturedTrack(t, IsResizing); + } + } +#else // EXPERIMENTAL_OUTPUT_DISPLAY + Track *prev = mTracks->GetPrev(t); + Track *next = mTracks->GetNext(t); + //STM: Determine whether we should rescale one or two tracks if (prev && prev->GetLink() == t) { // mCapturedTrack is the lower track @@ -4570,6 +4666,7 @@ void TrackPanel::HandleResizeClick( wxMouseEvent & event ) mInitialTrackHeight = t->GetHeight(); SetCapturedTrack(t, IsResizing); } +#endif // EXPERIMENTAL_OUTPUT_DISPLAY } /// This happens when the button is released from a drag. @@ -4612,11 +4709,126 @@ void TrackPanel::HandleResizeDrag(wxMouseEvent & event) mInitialUpperTrackHeight = link->GetHeight(); mInitialTrackHeight = mCapturedTrack->GetHeight(); } +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + else if(MONO_WAVE_PAN(mCapturedTrack)){ + mCapturedTrack->SetMinimized(false); + mInitialUpperTrackHeight = mCapturedTrack->GetHeight(); + mInitialTrackHeight = mCapturedTrack->GetHeight(true); + } +#endif } //STM: We may be dragging one or two (stereo) tracks. // If two, resize proportionally if we are dragging the lower track, and // adjust compensatively if we are dragging the upper track. +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + switch( mMouseCapture ) + { + case IsResizingBelowLinkedTracks: + { + if(MONO_WAVE_PAN(mCapturedTrack)){ + double proportion = static_cast < double >(mInitialTrackHeight) + / (mInitialTrackHeight + mInitialUpperTrackHeight); + + int newTrackHeight = static_cast < int > + (mInitialTrackHeight + delta * proportion); + + int newUpperTrackHeight = static_cast < int > + (mInitialUpperTrackHeight + delta * (1.0 - proportion)); + + //make sure neither track is smaller than its minimum height + if (newTrackHeight < mCapturedTrack->GetMinimizedHeight()) + newTrackHeight = mCapturedTrack->GetMinimizedHeight(); + if (newUpperTrackHeight < mCapturedTrack->GetMinimizedHeight()) + newUpperTrackHeight = mCapturedTrack->GetMinimizedHeight(); + + mCapturedTrack->SetHeight(newTrackHeight,true); + mCapturedTrack->SetHeight(newUpperTrackHeight); + } + else{ + Track *prev = mTracks->GetPrev(mCapturedTrack); + + double proportion = static_cast < double >(mInitialTrackHeight) + / (mInitialTrackHeight + mInitialUpperTrackHeight); + + int newTrackHeight = static_cast < int > + (mInitialTrackHeight + delta * proportion); + + int newUpperTrackHeight = static_cast < int > + (mInitialUpperTrackHeight + delta * (1.0 - proportion)); + + //make sure neither track is smaller than its minimum height + if (newTrackHeight < mCapturedTrack->GetMinimizedHeight()) + newTrackHeight = mCapturedTrack->GetMinimizedHeight(); + if (newUpperTrackHeight < prev->GetMinimizedHeight()) + newUpperTrackHeight = prev->GetMinimizedHeight(); + + mCapturedTrack->SetHeight(newTrackHeight); + prev->SetHeight(newUpperTrackHeight); + } + break; + } + case IsResizingBetweenLinkedTracks: + { + if(MONO_WAVE_PAN(mCapturedTrack)){ + int newUpperTrackHeight = mInitialUpperTrackHeight + delta; + int newTrackHeight = mInitialTrackHeight - delta; + + // make sure neither track is smaller than its minimum height + if (newTrackHeight < mCapturedTrack->GetMinimizedHeight()) { + newTrackHeight = mCapturedTrack->GetMinimizedHeight(); + newUpperTrackHeight = + mInitialUpperTrackHeight + mInitialTrackHeight - mCapturedTrack->GetMinimizedHeight(); + } + if (newUpperTrackHeight < mCapturedTrack->GetMinimizedHeight()) { + newUpperTrackHeight = mCapturedTrack->GetMinimizedHeight(); + newTrackHeight = + mInitialUpperTrackHeight + mInitialTrackHeight - mCapturedTrack->GetMinimizedHeight(); + } + float temp = 1.0f; + if(newUpperTrackHeight != 0.0f) + temp = (float)newUpperTrackHeight/(float)(newUpperTrackHeight + newTrackHeight); + + mCapturedTrack->SetVirtualTrackPercentage(temp); + mCapturedTrack->SetHeight(newUpperTrackHeight); + mCapturedTrack->SetHeight(newTrackHeight,true); + } + else{ + Track *next = mTracks->GetNext(mCapturedTrack); + int newUpperTrackHeight = mInitialUpperTrackHeight + delta; + int newTrackHeight = mInitialTrackHeight - delta; + + // make sure neither track is smaller than its minimum height + if (newTrackHeight < next->GetMinimizedHeight()) { + newTrackHeight = next->GetMinimizedHeight(); + newUpperTrackHeight = + mInitialUpperTrackHeight + mInitialTrackHeight - next->GetMinimizedHeight(); + } + if (newUpperTrackHeight < mCapturedTrack->GetMinimizedHeight()) { + newUpperTrackHeight = mCapturedTrack->GetMinimizedHeight(); + newTrackHeight = + mInitialUpperTrackHeight + mInitialTrackHeight - mCapturedTrack->GetMinimizedHeight(); + } + + mCapturedTrack->SetHeight(newUpperTrackHeight); + next->SetHeight(newTrackHeight); + break; + } + break; + } + case IsResizing: + { + int newTrackHeight = mInitialTrackHeight + delta; + if (newTrackHeight < mCapturedTrack->GetMinimizedHeight()) + newTrackHeight = mCapturedTrack->GetMinimizedHeight(); + mCapturedTrack->SetHeight(newTrackHeight); + break; + } + default: + // don't refresh in this case. + return; + } +#else // EXPERIMENTAL_OUTPUT_DISPLAY switch( mMouseCapture ) { case IsResizingBelowLinkedTracks: @@ -4676,7 +4888,7 @@ void TrackPanel::HandleResizeDrag(wxMouseEvent & event) // don't refresh in this case. return; } - +#endif // EXPERIMENTAL_OUTPUT_DISPLAY Refresh(false); } @@ -5536,6 +5748,12 @@ void TrackPanel::RefreshTrack(Track *trk, bool refreshbacking) r.height += link->GetHeight(); } +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + else if(MONO_WAVE_PAN(trk)){ + r.height += trk->GetHeight(true); + } +#endif + if( refreshbacking ) { mRefreshBacking = true; @@ -5632,6 +5850,12 @@ void TrackPanel::DrawEverythingElse(wxDC * dc, skipBorder = true; } +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + if(MONO_WAVE_PAN(t)){ + r.height += t->GetHeight(true); + } +#endif + // If the previous track is linked to this one but isn't on the screen // (and thus would have been skipped by VisibleTrackIterator) we need to // draw that track's border instead. @@ -5674,6 +5898,21 @@ void TrackPanel::DrawEverythingElse(wxDC * dc, r.height -= (kTopInset + 2); mTrackArtist->DrawVRuler(t, dc, r); } + +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + if(MONO_WAVE_PAN(t)){ + trackRect.y = t->GetY(true) - mViewInfo->vpos; + trackRect.height = t->GetHeight(true); + if (region.Contains(0, trackRect.y, GetLeftOffset(), trackRect.height)) { + wxRect r = trackRect; + r.x += GetVRulerOffset(); + r.y += kTopInset; + r.width = GetVRulerWidth(); + r.height -= (kTopInset + 2); + mTrackArtist->DrawVRuler(t, dc, r); + } + } +#endif } if ((mMouseCapture == IsZooming || mMouseCapture == IsVZooming) && @@ -5820,7 +6059,7 @@ void TrackPanel::DrawOutside(Track * t, wxDC * dc, const wxRect rec, dc->DrawText(TrackSubText(t), trackRect.x + offset, trackRect.y + 22); - + if (r.y + 38 + 12 < rec.y + rec.height - 19) dc->DrawText(GetSampleFormatStr(((WaveTrack *) t)->GetSampleFormat()), trackRect.x + offset, @@ -5900,12 +6139,21 @@ void TrackPanel::DrawOutsideOfTrack(Track * t, wxDC * dc, const wxRect r) dc->DrawRectangle(side); // Area between tracks of stereo group +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + if (t->GetLinked() || MONO_WAVE_PAN(t)) { + side = r; + side.y += t->GetHeight() - 1; + side.height = kTopInset + 1; + dc->DrawRectangle(side); + } +#else if (t->GetLinked()) { side = r; side.y += t->GetHeight() - 1; side.height = kTopInset + 1; dc->DrawRectangle(side); } +#endif } /// Draw a three-level highlight gradient around the focused track. @@ -5964,6 +6212,12 @@ void TrackPanel::UpdateTrackVRuler(Track *t) r.height = l->GetHeight() - (kTopInset + 2); mTrackArtist->UpdateVRuler(l, r); } +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + else if(MONO_WAVE_PAN(t)){ + r.height = t->GetHeight(true) - (kTopInset + 2); + mTrackArtist->UpdateVRuler(t, r); + } +#endif } void TrackPanel::UpdateVRulerSize() @@ -6957,6 +7211,11 @@ void TrackPanel::EnsureVisible(Track * t) nt = iter.Next(); trackHeight += nt->GetHeight(); } +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + else if(MONO_WAVE_PAN(it)){ + trackHeight += it->GetHeight(true); + } +#endif else { nt = it; } @@ -6998,11 +7257,19 @@ void TrackPanel::DrawBordersAroundTrack(Track * t, wxDC * dc, // The lines at bottom of 1st track and top of second track of stereo group // Possibly replace with DrawRectangle to add left border. +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + if (t->GetLinked() || MONO_WAVE_PAN(t)) { + int h1 = r.y + t->GetHeight() - kTopInset; + AColor::Line(*dc, vrul, h1 - 2, r.x + r.width - 1, h1 - 2); + AColor::Line(*dc, vrul, h1 + kTopInset, r.x + r.width - 1, h1 + kTopInset); + } +#else if (t->GetLinked()) { int h1 = r.y + t->GetHeight() - kTopInset; AColor::Line(*dc, vrul, h1 - 2, r.x + r.width - 1, h1 - 2); AColor::Line(*dc, vrul, h1 + kTopInset, r.x + r.width - 1, h1 + kTopInset); } +#endif } void TrackPanel::DrawShadow(Track * /* t */ , wxDC * dc, const wxRect r) @@ -7035,8 +7302,13 @@ wxString TrackPanel::TrackSubText(Track * t) wxString s = wxString::Format(wxT("%dHz"), (int) (((WaveTrack *) t)->GetRate() + 0.5)); +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + if (t->GetLinked() && t->GetChannel() != Track::MonoChannel) + s = _("Stereo, ") + s; +#else if (t->GetLinked()) s = _("Stereo, ") + s; +#endif else { if (t->GetChannel() == Track::MonoChannel) s = _("Mono, ") + s; @@ -7094,6 +7366,14 @@ void TrackPanel::SplitStereo(bool stereo) mPopupMenuTarget->SetChannel(Track::MonoChannel); Track *partner = mPopupMenuTarget->GetLink(); + +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + if(!stereo && MONO_WAVE_PAN(mPopupMenuTarget)) + ((WaveTrack*)mPopupMenuTarget)->SetVirtualState(true,true); + if(!stereo && MONO_WAVE_PAN(partner)) + ((WaveTrack*)partner)->SetVirtualState(true,true); +#endif + if (partner) { partner->SetName(mPopupMenuTarget->GetName()); @@ -7132,6 +7412,14 @@ void TrackPanel::OnMergeStereo(wxCommandEvent &event) wxASSERT(mPopupMenuTarget); mPopupMenuTarget->SetLinked(true); Track *partner = mPopupMenuTarget->GetLink(); + +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + if(MONO_WAVE_PAN(mPopupMenuTarget)) + ((WaveTrack*)mPopupMenuTarget)->SetVirtualState(false); + if(MONO_WAVE_PAN(partner)) + ((WaveTrack*)partner)->SetVirtualState(false); +#endif + if (partner) { // Set partner's parameters to match target. partner->Merge(*mPopupMenuTarget); @@ -7183,7 +7471,13 @@ void TrackPanel::OnSetDisplay(wxCommandEvent & event) l->SetDisplay(id); mTrackArtist->InvalidateSpectrumCache(l); } - +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + if (wt->GetDisplay() == WaveTrack::WaveformDisplay) { + wt->SetVirtualState(false); + }else if (id == WaveTrack::WaveformDisplay) { + wt->SetVirtualState(true); + } +#endif UpdateVRuler(wt); } MakeParentModifyState(); //v Doesn't really warrant AutoSave. Maybe add bWantAutoSave param if there are more. @@ -7690,15 +7984,23 @@ Track *TrackPanel::FindTrack(int mouseX, int mouseY, bool label, bool link, int h = l->GetHeight(); if (!t->GetLinked()) { t = l; - r.y = t->GetY() - mViewInfo->vpos + kTopInset;; + r.y = t->GetY() - mViewInfo->vpos + kTopInset; } r.height += h; } - +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + else if(link && MONO_WAVE_PAN(t)) + { + r.height += t->GetHeight(true); + } +#endif //Determine whether the mouse is inside //the current rectangle. If so, recalculate //the proper dimensions and return. if (r.Contains(mouseX, mouseY)) { +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + t->SetVirtualStereo(false); +#endif if (trackRect) { r.y -= kTopInset; if (label) { @@ -7712,6 +8014,26 @@ Track *TrackPanel::FindTrack(int mouseX, int mouseY, bool label, bool link, return t; } +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + if(!link && MONO_WAVE_PAN(t)){ + r.y = t->GetY(true) - mViewInfo->vpos + kTopInset; + r.height = t->GetHeight(true); + if (r.Contains(mouseX, mouseY)) { + t->SetVirtualStereo(true); + if (trackRect) { + r.y -= kTopInset; + if (label) { + r.x += kLeftInset; + r.width -= kLeftInset; + r.y += kTopInset; + r.height -= kTopInset; + } + *trackRect = r; + } + return t; + } + } +#endif // EXPERIMENTAL_OUTPUT_DISPLAY } return NULL; diff --git a/src/TrackPanel.h b/src/TrackPanel.h index df7a2d185..69c483771 100644 --- a/src/TrackPanel.h +++ b/src/TrackPanel.h @@ -497,6 +497,9 @@ protected: virtual int IdOfRate( int rate ); virtual int IdOfFormat( int format ); +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + void UpdateVirtualStereoOrder(); +#endif // Accessors... virtual bool HasSoloButton(){ return mSoloPref!=wxT("None");}; diff --git a/src/WaveTrack.cpp b/src/WaveTrack.cpp index 105f35c80..6f0c814bd 100644 --- a/src/WaveTrack.cpp +++ b/src/WaveTrack.cpp @@ -56,6 +56,10 @@ Track classes. using std::max; +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY +bool WaveTrack::mMonoAsVirtualStereo; +#endif + WaveTrack* TrackFactory::DuplicateWaveTrack(WaveTrack &orig) { return (WaveTrack*)(orig.Duplicate()); @@ -215,6 +219,37 @@ float WaveTrack::GetPan() const return mPan; } +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY +bool WaveTrack::SetPan(float newPan) +{ + float p=mPan; + bool panZero=false; + int temp; + + if (newPan > 1.0) + mPan = 1.0; + else if (newPan < -1.0) + mPan = -1.0; + else + mPan = newPan; + + if(mDisplay == WaveTrack::WaveformDisplay && mChannel == Track::MonoChannel && (p == 0.0f && newPan != 0.0f || p != 0.0f && newPan == 0.0f) && mMonoAsVirtualStereo) + { + panZero=true; + if(!mPan){ + mHeight = mHeight + mHeightv; + }else{ + temp = mHeight; + mHeight = temp*mPerY; + mHeightv = temp - mHeight; + } + ReorderList(); + } + + return panZero; +} + +#else // EXPERIMENTAL_OUTPUT_DISPLAY void WaveTrack::SetPan(float newPan) { if (newPan > 1.0) @@ -224,12 +259,65 @@ void WaveTrack::SetPan(float newPan) else mPan = newPan; } +#endif // EXPERIMENTAL_OUTPUT_DISPLAY + +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY +void WaveTrack::SetVirtualState(bool state, bool half) +{ + int temp; + + if(half) + mPerY = 0.5; + + if(state){ + if(mPan){ + temp = mHeight; + mHeight = temp*mPerY; + mHeightv = temp - mHeight; + } + ReorderList(); + }else{ + if(mPan){ + mHeight = mHeight + mHeightv; + } + } +} + +int WaveTrack::GetMinimizedHeight() const +{ + if (GetLink()) { + return 20; + } + + if(GetChannel() == MonoChannel && GetPan() != 0 && mMonoAsVirtualStereo && mDisplay == WaveformDisplay) + return 20; + else + return 40; +} + +void WaveTrack::VirtualStereoInit() +{ + int temp; + + if(mChannel == Track::MonoChannel && mPan != 0.0f && mMonoAsVirtualStereo){ + temp = mHeight; + mHeight = temp*mPerY; + mHeightv = temp - mHeight; + ReorderList(false); + } +} +#endif float WaveTrack::GetChannelGain(int channel) { float left = 1.0; float right = 1.0; +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + if(mVirtualStereo) + channel = 3; +#endif + if (mPan < 0) right = (mPan + 1.0); else if (mPan > 0) @@ -1385,6 +1473,9 @@ bool WaveTrack::HandleXMLTag(const wxChar *tag, const wxChar **attrs) SetLinked(nValue != 0); } // while +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + VirtualStereoInit(); +#endif return true; } @@ -1442,7 +1533,16 @@ void WaveTrack::WriteXML(XMLWriter &xmlFile) xmlFile.WriteAttr(wxT("linked"), mLinked); xmlFile.WriteAttr(wxT("mute"), mMute); xmlFile.WriteAttr(wxT("solo"), mSolo); +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + int height; + if(MONO_PAN) + height = mHeight + mHeightv; + else + height = this->GetActualHeight(); + xmlFile.WriteAttr(wxT("height"), height); +#else xmlFile.WriteAttr(wxT("height"), this->GetActualHeight()); +#endif xmlFile.WriteAttr(wxT("minimized"), this->GetMinimized()); xmlFile.WriteAttr(wxT("isSelected"), this->GetSelected()); xmlFile.WriteAttr(wxT("rate"), mRate); diff --git a/src/prefs/GUIPrefs.cpp b/src/prefs/GUIPrefs.cpp index fd6844df1..54950dea9 100644 --- a/src/prefs/GUIPrefs.cpp +++ b/src/prefs/GUIPrefs.cpp @@ -131,6 +131,12 @@ void GUIPrefs::PopulateOrExchange(ShuttleGui & S) S.TieCheckBox(_("Re&tain labels if selection snaps to a label edge"), wxT("/GUI/RetainLabels"), false); + +#ifdef EXPERIMENTAL_OUTPUT_DISPLAY + S.TieCheckBox(_("&Display a mono channel as virtual stereo"), + wxT("/GUI/MonoAsVirtualStereo"), + false); +#endif } S.EndStatic(); }