17#include "../../SpectrumAnalyst.h"
22#include "../../ProjectSettings.h"
23#include "../../ProjectWindow.h"
24#include "../../RefreshCode.h"
25#include "../../SelectUtilities.h"
26#include "../../SelectionState.h"
27#include "../../SpectralDataManager.h"
28#include "../../TrackArtist.h"
29#include "../../TrackPanelAx.h"
30#include "../../TrackPanel.h"
31#include "../../TrackPanelDrawingContext.h"
32#include "../../TrackPanelMouseEvent.h"
34#include "../../WaveClip.h"
35#include "../../WaveTrack.h"
36#include "../../prefs/SpectrogramSettings.h"
37#include "../../../images/Cursors.h"
38#include "../playabletrack/wavetrack/ui/SpectrumView.h"
71 float minFreq, maxFreq;
75 return trackTopEdge + wxInt64((1.0 - p) * trackHeight);
82 wxInt64 mouseYCoordinate,
86 const double rate = wt->
GetRate();
97 float minFreq, maxFreq;
100 const double p = double(mouseYCoordinate - trackTopEdge) / trackHeight;
109 wxInt64 posTime = viewInfo.
PositionToTime(mousePosX, trackTopEdgeX);
128 pTrackView->
FindTrack()->TypeSwitch<
bool >(
131 return settings.SpectralSelectionEnabled();
136 static auto crosshairCursor =
137 ::MakeCursor(wxCURSOR_IBEAM, CrosshairCursorXpm, 16, 16);
138 return &*crosshairCursor;
143 ( std::shared_ptr<StateSaver> pStateSaver,
144 const std::shared_ptr<TrackView> &pTrackView,
147 const std::shared_ptr<SpectralData> &pSpectralData,
149 : mpStateSaver{ move(pStateSaver) }
150 , mpSpectralData(pSpectralData)
151 , mpView{ pTrackView }
153 const wxMouseState &state = st.
state;
154 auto pTrack = pTrackView->FindTrack().get();
155 auto wt =
dynamic_cast<WaveTrack *
>(pTrack);
175 template <
class A,
class B,
class DIST >
bool within(
A a, B b, DIST d)
177 return (a > b - d) && (a < b + d);
182 const double minFrequency = 1.0;
183 const double maxFrequency = (rate / 2.0);
184 const double frequency =
186 std::max(minFrequency, center));
188 std::min(frequency / minFrequency, maxFrequency / frequency);
228 const auto pView =
mpView.lock();
232 wxMouseEvent &
event = evt.
event;
234 const auto pTrack = sTrack.get();
248 const auto pView =
mpView.lock();
252 wxMouseEvent &
event = evt.
event;
254 const auto pTrack = sTrack.get();
260 auto posXToHopNum = [&](
int x0){
261 double posTime = viewInfo.PositionToTime(x0,
mRect.x);
267 auto posYToFreqBin = [&](
int y0){
270 return static_cast<int>(
std::round(resFreqBin));
273 auto drawCircle = [&](
int h0,
int bm){
281 for (
int i = h0 - h2; i <= h0 + h2; i++)
286 for (
int i = h0 - b2; i <= h0 + b2; i++)
293 radiusError += bChange;
295 if (((radiusError << 1) + hChange) > 0)
298 radiusError += hChange;
306 int dest_xcoord = std::clamp(event.m_x,
mRect.x + 10,
mRect.x +
mRect.width);
307 int dest_ycoord = std::clamp(event.m_y,
mRect.y + 10,
mRect.y +
mRect.height);
309 int h1 = posXToHopNum(dest_xcoord);
310 int b1 = posYToFreqBin(dest_ycoord);
312 mbCtrlDown =
event.ControlDown() ||
event.AltDown();
323 int h0 = posXToHopNum(src_xcoord);
324 int b0 = posYToFreqBin(src_ycoord);
327 int dh = abs(h1-h0), sh = h0<h1 ? 1 : -1;
328 int db = -abs(b1-b0), sb = b0<b1 ? 1 : -1;
329 int err = dh+db, err2;
333 if (h0 == h1 && b0 == b1)
336 if (err2 * 2 >= db) { err += db; h0 += sh; }
337 if (err2 * 2 <= dh) { err += dh; b0 += sb; }
343 if(
auto *sView =
dynamic_cast<SpectrumView*
>(pView.get())){
346 if(resFreqBin != - 1)
355 for(
auto & bins: binsToWork)
356 drawCircle(h0, bins);
362 mpSpectralData->coordHistory.push_back(std::make_pair(dest_xcoord, dest_ycoord));
371 return { tip, pCursor };
386 XO(
"Erased selected area" ),
387 XO(
"Erased selected area" ) );
392 XO(
"Selected area using Brush Tool" ),
393 XO(
"Brush tool selection" ) );
408 const wxRect &rect,
unsigned iPass )
411 auto& dc = context.
dc;
415 dc.SetBrush( *wxTRANSPARENT_BRUSH );
416 dc.SetPen( *wxYELLOW_PEN );
423 auto pView =
mpView.lock();
427 return pView->FindTrack();
@ SELECTION_RESIZE_REGION
static Settings & settings()
std::unique_ptr< wxCursor > MakeCursor(int WXUNUSED(CursorId), const char *const pXpm[36], int HotX, int HotY)
bool within(A a, B b, DIST d)
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Result Drag(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
std::shared_ptr< SelectionStateChanger > mSelectionStateChanger
std::shared_ptr< StateSaver > mpStateSaver
long long mSampleCountLowerBound
std::weak_ptr< TrackView > mpView
HitTestPreview Preview(const TrackPanelMouseState &state, AudacityProject *pProject) override
Result Click(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
void Enter(bool forward, AudacityProject *pProject) override
void Draw(TrackPanelDrawingContext &context, const wxRect &rect, unsigned iPass) override
BrushHandle(const BrushHandle &)
double mFreqSnappingRatio
Result Release(const TrackPanelMouseEvent &event, AudacityProject *pProject, wxWindow *pParent) override
void HandleHopBinData(int hopNum, int freqBinNum)
double mOvertonesThreshold
Result Cancel(AudacityProject *) override
bool Escape(AudacityProject *pProject) override
std::weak_ptr< Track > FindTrack()
long long mSampleCountUpperBound
std::shared_ptr< SpectralData > mpSpectralData
std::shared_ptr< Track > FindTrack()
float PositionToValue(float pp) const
float ValueToPosition(float val) const
void PushState(const TranslatableString &desc, const TranslatableString &shortDesc)
void ModifyState(bool bWantsAutoSave)
static ProjectHistory & Get(AudacityProject &project)
Holds various per-project settings values, and sends events to the project when certain values change...
int GetBrushRadius() const
bool IsSmartSelection() const
sampleCount TimeToLongSamples(double t0) const
Convert correctly between an (absolute) time in seconds and a number of samples.
static int FindFrequencySnappingBin(WaveTrack *wt, long long startSC, int hopSize, double threshold, int targetFreqBin)
static std::vector< int > FindHighestFrequencyBins(WaveTrack *wt, long long int startSC, int hopSize, double threshold, int targetFreqBin)
Spectrogram settings, either for one track or as defaults.
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
std::shared_ptr< Subclass > Lock(const std::weak_ptr< Subclass > &wTrack)
static TrackList & Get(AudacityProject &project)
static TrackPanel & Get(AudacityProject &project)
virtual bool IsSpectral() const
Holds a msgid for the translation catalog; may also bind format arguments.
static ViewInfo & Get(AudacityProject &project)
A Track that contains audio waveform data.
const SpectrogramSettings & GetSpectrogramSettings() const
double GetRate() const override
void GetSpectrumBounds(float *min, float *max) const
double PositionToTime(wxInt64 position, wxInt64 origin=0, bool ignoreFisheye=false) const
Positions or offsets within audio files need a wide type.
long long as_long_long() const
Namespace containing an enum 'what to do on a refresh?'.
wxCursor * CrosshairCursor()
double PositionToFrequency(const WaveTrack *wt, bool maySnap, wxInt64 mouseYCoordinate, wxInt64 trackTopEdge, int trackHeight)
void SetIfNotNull(T *pValue, const T Value)
long long PositionToLongSample(const WaveTrack *wt, const ViewInfo &viewInfo, int trackTopEdgeX, int mousePosX)
bool isSpectralSelectionView(const TrackView *pTrackView)
double findMaxRatio(double center, double rate)
wxInt64 FrequencyToPosition(const WaveTrack *wt, double frequency, wxInt64 trackTopEdge, int trackHeight)
Converts a frequency to screen y position.
fastfloat_really_inline void round(adjusted_mantissa &am, callback cb) noexcept