Audacity 3.2.0
SpectrumVZoomHandle.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3Audacity: A Digital Audio Editor
4
5SpectrumVZoomHandle.cpp
6
7Paul Licameli split from WaveChannelVZoomHandle.cpp
8
9**********************************************************************/
10
11
12#include "SpectrumVZoomHandle.h"
13
15
16#include "../../../../HitTestResult.h"
17#include "NumberScale.h"
18#include "Prefs.h"
19#include "ProjectHistory.h"
20#include "../../../../RefreshCode.h"
21#include "../../../../TrackPanelMouseEvent.h"
22#include "WaveTrack.h"
23#include "../../../../prefs/SpectrogramSettings.h"
24
26(const std::shared_ptr<WaveTrack> &pTrack, const wxRect &rect, int y)
27 : mpTrack{ pTrack } , mZoomStart(y), mZoomEnd(y), mRect(rect)
28{
29}
30
32
33std::shared_ptr<const Channel> SpectrumVZoomHandle::FindChannel() const
34{
35 return mpTrack.lock();
36}
37
39{
40#ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING
42#endif
43}
44
46{
47 return true;
48}
49
52{
54}
55
57(const TrackPanelMouseEvent &evt, AudacityProject *pProject)
58{
59 using namespace RefreshCode;
60 auto pTrack = TrackList::Get( *pProject ).Lock(mpTrack);
61 if (!pTrack)
62 return Cancelled;
64}
65
68{
70}
71
73(const TrackPanelMouseEvent &evt, AudacityProject *pProject,
74 wxWindow *pParent)
75{
76 auto pTrack = TrackList::Get( *pProject ).Lock(mpTrack);
78 evt, pProject, pParent, pTrack.get(), mRect,
81}
82
84{
85 // Cancel is implemented! And there is no initial state to restore,
86 // so just return a code.
88}
89
92 const wxRect &rect, unsigned iPass )
93{
94 if (!mpTrack.lock()) //? TrackList::Lock()
95 return;
97 context, rect, iPass, mZoomStart, mZoomEnd );
98}
99
102 const wxRect &rect, const wxRect &panelRect, unsigned iPass )
103{
104 return WaveChannelVZoomHandle::DoDrawingArea(rect, panelRect, iPass);
105}
106
107// ZoomKind says how to zoom.
108// If ZoomStart and ZoomEnd are not equal, this may override
109// the zoomKind and cause a drag-zoom-in.
111 AudacityProject *pProject,
112 WaveTrack *pTrack,
114 const wxRect &rect, int zoomStart, int zoomEnd,
115 bool fixedMousePoint)
116{
117 using namespace WaveChannelViewConstants;
118 static const float ZOOMLIMIT = 0.001f;
119
120 int height = rect.height;
121 int ypos = rect.y;
122
123 // Ensure start and end are in order (swap if not).
124 if (zoomEnd < zoomStart)
125 std::swap( zoomStart, zoomEnd );
126
127 float min, max, minBand = 0;
128 const double rate = pTrack->GetRate();
129 const float halfrate = rate / 2;
130 float maxFreq = 8000.0;
131 const auto &specSettings = SpectrogramSettings::Get(*pTrack);
132 NumberScale scale;
133 const bool spectrumLinear =
135
136
137 bool bDragZoom = WaveChannelVZoomHandle::IsDragZooming(zoomStart, zoomEnd);
138 // Add 100 if spectral to separate the kinds of zoom.
139 const int kSpectral = 100;
140
141 // Possibly override the zoom kind.
142 if( bDragZoom )
143 ZoomKind = kZoomInByDrag;
144
145 float top=2.0;
146 float half=0.5;
147
148 {
149 SpectrogramBounds::Get(*pTrack).GetBounds(*pTrack, min, max);
150 scale = (specSettings.GetScale(min, max));
151 const auto fftLength = specSettings.GetFFTLength();
152 const float binSize = rate / fftLength;
153 maxFreq = SpectrumMaxFreq.Read();
154 // JKC: Following discussions of Bug 1208 I'm allowing zooming in
155 // down to one bin.
156 // const int minBins =
157 // std::min(10, fftLength / 2); //minimum 10 freq bins, unless there are less
158 const int minBins = 1;
159 minBand = minBins * binSize;
160 }
161
162 // Compute min and max.
163 switch(ZoomKind)
164 {
165 default:
166 // If we have covered all the cases, this won't happen.
167 // In release builds Audacity will ignore the zoom.
168 wxFAIL_MSG("Zooming Case not implemented by Audacity");
169 break;
170
171 // VZooming on spectral we don't implement the other zoom presets.
172 // They are also not in the menu.
173 case kZoomReset:
174 {
175 // Zoom out to normal level.
176 min = spectrumLinear ? 0.0f : 1.0f;
177 max = maxFreq;
178 }
179 break;
180 case kZoom1to1:
181 case kZoomDiv2:
182 case kZoomTimes2:
183 case kZoomHalfWave:
184 {
185 // Zoom out full
186 min = spectrumLinear ? 0.0f : 1.0f;
187 max = halfrate;
188 }
189 break;
190 case kZoomInByDrag:
191 {
192 double xmin = 1 - (zoomEnd - ypos) / (float)height;
193 double xmax = 1 - (zoomStart - ypos) / (float)height;
194 const float middle = (xmin + xmax) / 2;
195 const float middleValue = scale.PositionToValue(middle);
196
197 min = std::max(spectrumLinear ? 0.0f : 1.0f,
198 std::min(middleValue - minBand / 2,
199 scale.PositionToValue(xmin)
200 ));
201 max = std::min(halfrate,
202 std::max(middleValue + minBand / 2,
203 scale.PositionToValue(xmax)
204 ));
205 }
206 break;
207 case kZoomIn:
208 {
209 // Center the zoom-in at the click
210 const float p1 = (zoomStart - ypos) / (float)height;
211 const float middle = 1.0f - p1;
212 const float middleValue = scale.PositionToValue(middle);
213
214 if (fixedMousePoint) {
215 min = std::max(spectrumLinear ? 0.0f : 1.0f,
216 std::min(middleValue - minBand * middle,
217 scale.PositionToValue(0.5f * middle)
218 ));
219 max = std::min(halfrate,
220 std::max(middleValue + minBand * p1,
221 scale.PositionToValue(middle + 0.5f * p1)
222 ));
223 }
224 else {
225 min = std::max(spectrumLinear ? 0.0f : 1.0f,
226 std::min(middleValue - minBand / 2,
227 scale.PositionToValue(middle - 0.25f)
228 ));
229 max = std::min(halfrate,
230 std::max(middleValue + minBand / 2,
231 scale.PositionToValue(middle + 0.25f)
232 ));
233 }
234 }
235 break;
236 case kZoomOut:
237 {
238 // Zoom out
239 const float p1 = (zoomStart - ypos) / (float)height;
240 // (Used to zoom out centered at midline, ignoring the click, if linear view.
241 // I think it is better to be consistent. PRL)
242 // Center zoom-out at the midline
243 const float middle = // spectrumLinear ? 0.5f :
244 1.0f - p1;
245
246 if (fixedMousePoint) {
247 min = std::max(spectrumLinear ? 0.0f : 1.0f, scale.PositionToValue(-middle));
248 max = std::min(halfrate, scale.PositionToValue(1.0f + p1));
249 }
250 else {
251 min = std::max(spectrumLinear ? 0.0f : 1.0f, scale.PositionToValue(middle - 1.0f));
252 max = std::min(halfrate, scale.PositionToValue(middle + 1.0f));
253 }
254 }
255 break;
256 }
257
258 // Now actually apply the zoom.
259 SpectrogramBounds::Get(*pTrack).SetBounds(min, max);
260
261 zoomEnd = zoomStart = 0;
262 if( pProject )
263 ProjectHistory::Get( *pProject ).ModifyState(true);
264}
265
267// Table class
268
270{
271 static SpectrumVRulerMenuTable instance;
272 return instance;
273}
274
276
277BeginSection( "Scales" );
278 {
280 for (int ii = 0, nn = names.size(); ii < nn; ++ii) {
282 OnFirstSpectrumScaleID + ii, names[ii].Msgid(),
283 POPUP_MENU_FN( OnSpectrumScaleType ),
284 []( PopupMenuHandler &handler, wxMenu &menu, int id ){
285 WaveTrack *const wt =
286 static_cast<SpectrumVRulerMenuTable&>( handler )
287 .mpData->pTrack;
288 if ( id ==
290 static_cast<int>(SpectrogramSettings::Get(*wt).scaleType))
291 menu.Check(id, true);
292 }
293 );
294 }
295 }
297
298
299BeginSection( "Zoom" );
300 // Accelerators only if zooming enabled.
301 bool bVZoom;
302 gPrefs->Read(wxT("/GUI/VerticalZooming"), &bVZoom, false);
303
304 AppendItem( "Reset", OnZoomResetID, XXO("Zoom Reset"),
305 POPUP_MENU_FN( OnZoomReset ) );
307 MakeLabel( XXO("Zoom to Fit"), bVZoom, XXO("Shift-Right-Click") ),
308 POPUP_MENU_FN( OnZoomFitVertical ) );
310 MakeLabel( XXO("Zoom In"), bVZoom, XXO("Left-Click/Left-Drag") ),
311 POPUP_MENU_FN( OnZoomInVertical ) );
313 MakeLabel( XXO("Zoom Out"), bVZoom, XXO("Shift-Left-Click") ),
314 POPUP_MENU_FN( OnZoomOutVertical ) );
315EndSection();
316
318
319void SpectrumVRulerMenuTable::OnSpectrumScaleType(wxCommandEvent &evt)
320{
321 WaveTrack *const wt = mpData->pTrack;
322
323 const SpectrogramSettings::ScaleType newScaleType =
325 std::max(0,
327 evt.GetId() - OnFirstSpectrumScaleID
328 )));
329 if (SpectrogramSettings::Get(*wt).scaleType != newScaleType) {
330 SpectrogramSettings::Own(*wt).scaleType = newScaleType;
331
332 ProjectHistory::Get( mpData->project ).ModifyState(true);
333
334 using namespace RefreshCode;
335 mpData->result = UpdateVRuler | RefreshAll;
336 }
337}
wxT("CloseDown"))
@ Internal
Indicates internal failure from Audacity.
int min(int a, int b)
XXO("&Cut/Copy/Paste Toolbar")
@ OnZoomOutVerticalID
@ OnZoomFitVerticalID
@ OnZoomInVerticalID
#define END_POPUP_MENU()
#define BEGIN_POPUP_MENU(HandlerClass)
#define POPUP_MENU_FN(memFn)
audacity::BasicSettings * gPrefs
Definition: Prefs.cpp:68
IntSetting SpectrumMaxFreq
EndSection()
bool bVZoom
AppendItem("Reset", OnZoomResetID, XXO("Zoom Reset"), POPUP_MENU_FN(OnZoomReset))
BeginSection("Scales")
static TranslatableStrings names
Definition: TagsEditor.cpp:153
@ OnFirstSpectrumScaleID
AppendRadioItem("Instrument1", OnInstrument1ID, GetWaveColorStr(0), POPUP_MENU_FN(OnWaveColorChange), fn)
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:90
float PositionToValue(float pp) const
Definition: NumberScale.h:155
void ModifyState(bool bWantsAutoSave)
static ProjectHistory & Get(AudacityProject &project)
bool Read(T *pVar) const
overload of Read returning a boolean that is true if the value was previously defined *‍/
Definition: Prefs.h:205
void GetBounds(const WaveTrack &wt, float &min, float &max) const
void SetBounds(float min, float max)
static SpectrogramBounds & Get(WaveTrack &track)
Get either the global default settings, or the track's own if previously created.
static const EnumValueSymbols & GetScaleNames()
static SpectrogramSettings & Get(const WaveTrack &track)
Mutative access to attachment even if the track argument is const.
static SpectrogramSettings & Own(WaveTrack &track)
static PopupMenuTable & Instance()
std::weak_ptr< WaveTrack > mpTrack
SpectrumVZoomHandle(const SpectrumVZoomHandle &)
Result Release(const TrackPanelMouseEvent &event, AudacityProject *pProject, wxWindow *pParent) override
bool HandlesRightClick() override
Whether the handle has any special right-button handling.
void Draw(TrackPanelDrawingContext &context, const wxRect &rect, unsigned iPass) override
Result Drag(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
static void DoZoom(AudacityProject *pProject, WaveTrack *pTrack, WaveChannelViewConstants::ZoomActions ZoomKind, const wxRect &rect, int zoomStart, int zoomEnd, bool fixedMousePoint)
Result Click(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
std::shared_ptr< const Channel > FindChannel() const override
void Enter(bool forward, AudacityProject *) override
wxRect DrawingArea(TrackPanelDrawingContext &, const wxRect &rect, const wxRect &panelRect, unsigned iPass) override
~SpectrumVZoomHandle() override
Result Cancel(AudacityProject *pProject) override
HitTestPreview Preview(const TrackPanelMouseState &state, AudacityProject *pProject) override
std::shared_ptr< Subclass > Lock(const std::weak_ptr< Subclass > &wTrack)
Definition: Track.h:1228
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:347
Result mChangeHighlight
Definition: UIHandle.h:147
unsigned Result
Definition: UIHandle.h:39
A Track that contains audio waveform data.
Definition: WaveTrack.h:222
double GetRate() const override
Definition: WaveTrack.cpp:1085
virtual bool Read(const wxString &key, bool *value) const =0
Namespace containing an enum 'what to do on a refresh?'.
Definition: RefreshCode.h:16
AUDACITY_DLL_API Result DoRelease(const TrackPanelMouseEvent &event, AudacityProject *pProject, wxWindow *pParent, WaveTrack *pTrack, const wxRect &mRect, DoZoomFunction doZoom, PopupMenuTable &table, int zoomStart, int zoomEnd)
AUDACITY_DLL_API Result DoDrag(const TrackPanelMouseEvent &event, AudacityProject *pProject, int zoomStart, int &zoomEnd)
AUDACITY_DLL_API HitTestPreview HitPreview(const wxMouseState &state)
AUDACITY_DLL_API void DoDraw(TrackPanelDrawingContext &context, const wxRect &rect, unsigned iPass, int zoomStart, int zoomEnd)
AUDACITY_DLL_API wxRect DoDrawingArea(const wxRect &rect, const wxRect &panelRect, unsigned iPass)
AUDACITY_DLL_API bool IsDragZooming(int zoomStart, int zoomEnd)
void swap(std::unique_ptr< Alg_seq > &a, std::unique_ptr< Alg_seq > &b)
Definition: NoteTrack.cpp:645