mirror of
https://github.com/cookiengineer/audacity
synced 2025-08-03 17:39:25 +02:00
Separate functions for vertical zooming of spectrum and waveform
This commit is contained in:
parent
fa7de8ce3a
commit
f7dc21436d
@ -125,7 +125,10 @@ unsigned WaveTrackVRulerControls::HandleWheelRotation
|
|||||||
}
|
}
|
||||||
else if (event.CmdDown() && !event.ShiftDown()) {
|
else if (event.CmdDown() && !event.ShiftDown()) {
|
||||||
const int yy = event.m_y;
|
const int yy = event.m_y;
|
||||||
WaveTrackVZoomHandle::DoZoom(
|
auto doZoom = (wt->GetDisplay() == Spectrum)
|
||||||
|
? WaveTrackVZoomHandle::DoSpectrumZoom
|
||||||
|
: WaveTrackVZoomHandle::DoWaveformZoom;
|
||||||
|
doZoom(
|
||||||
pProject, wt,
|
pProject, wt,
|
||||||
(steps < 0)
|
(steps < 0)
|
||||||
? kZoomOut
|
? kZoomOut
|
||||||
|
@ -39,6 +39,7 @@ public:
|
|||||||
wxRect rect;
|
wxRect rect;
|
||||||
unsigned result;
|
unsigned result;
|
||||||
int yy;
|
int yy;
|
||||||
|
WaveTrackVZoomHandle::DoZoomFunction doZoom;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool IsDragZooming(int zoomStart, int zoomEnd)
|
bool IsDragZooming(int zoomStart, int zoomEnd)
|
||||||
@ -67,10 +68,10 @@ void WaveTrackVZoomHandle::Enter(bool)
|
|||||||
// ZoomKind says how to zoom.
|
// ZoomKind says how to zoom.
|
||||||
// If ZoomStart and ZoomEnd are not equal, this may override
|
// If ZoomStart and ZoomEnd are not equal, this may override
|
||||||
// the zoomKind and cause a drag-zoom-in.
|
// the zoomKind and cause a drag-zoom-in.
|
||||||
void WaveTrackVZoomHandle::DoZoom
|
void WaveTrackVZoomHandle::DoSpectrumZoom(
|
||||||
(AudacityProject *pProject,
|
AudacityProject *pProject,
|
||||||
WaveTrack *pTrack,
|
WaveTrack *pTrack,
|
||||||
WaveTrackViewConstants::ZoomActions inZoomKind,
|
WaveTrackViewConstants::ZoomActions ZoomKind,
|
||||||
const wxRect &rect, int zoomStart, int zoomEnd,
|
const wxRect &rect, int zoomStart, int zoomEnd,
|
||||||
bool fixedMousePoint)
|
bool fixedMousePoint)
|
||||||
{
|
{
|
||||||
@ -90,9 +91,7 @@ void WaveTrackVZoomHandle::DoZoom
|
|||||||
float maxFreq = 8000.0;
|
float maxFreq = 8000.0;
|
||||||
const SpectrogramSettings &specSettings = pTrack->GetSpectrogramSettings();
|
const SpectrogramSettings &specSettings = pTrack->GetSpectrogramSettings();
|
||||||
NumberScale scale;
|
NumberScale scale;
|
||||||
const bool spectral =
|
const bool spectrumLinear =
|
||||||
(pTrack->GetDisplay() == Spectrum);
|
|
||||||
const bool spectrumLinear = spectral &&
|
|
||||||
(pTrack->GetSpectrogramSettings().scaleType == SpectrogramSettings::stLinear);
|
(pTrack->GetSpectrogramSettings().scaleType == SpectrogramSettings::stLinear);
|
||||||
|
|
||||||
|
|
||||||
@ -102,15 +101,12 @@ void WaveTrackVZoomHandle::DoZoom
|
|||||||
|
|
||||||
// Possibly override the zoom kind.
|
// Possibly override the zoom kind.
|
||||||
if( bDragZoom )
|
if( bDragZoom )
|
||||||
inZoomKind = kZoomInByDrag;
|
ZoomKind = kZoomInByDrag;
|
||||||
|
|
||||||
// If we are actually zooming a spectrum rather than a wave.
|
|
||||||
int ZoomKind = (int)inZoomKind + (spectral ? kSpectral : 0);
|
|
||||||
|
|
||||||
float top=2.0;
|
float top=2.0;
|
||||||
float half=0.5;
|
float half=0.5;
|
||||||
|
|
||||||
if (spectral) {
|
{
|
||||||
pTrack->GetSpectrumBounds(&min, &max);
|
pTrack->GetSpectrumBounds(&min, &max);
|
||||||
scale = (specSettings.GetScale(min, max));
|
scale = (specSettings.GetScale(min, max));
|
||||||
const auto fftLength = specSettings.GetFFTLength();
|
const auto fftLength = specSettings.GetFFTLength();
|
||||||
@ -123,7 +119,150 @@ void WaveTrackVZoomHandle::DoZoom
|
|||||||
const int minBins = 1;
|
const int minBins = 1;
|
||||||
minBand = minBins * binSize;
|
minBand = minBins * binSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Compute min and max.
|
||||||
|
switch(ZoomKind)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
// If we have covered all the cases, this won't happen.
|
||||||
|
// In release builds Audacity will ignore the zoom.
|
||||||
|
wxFAIL_MSG("Zooming Case not implemented by Audacity");
|
||||||
|
break;
|
||||||
|
|
||||||
|
// VZooming on spectral we don't implement the other zoom presets.
|
||||||
|
// They are also not in the menu.
|
||||||
|
case kZoomReset:
|
||||||
|
{
|
||||||
|
// Zoom out to normal level.
|
||||||
|
min = spectrumLinear ? 0.0f : 1.0f;
|
||||||
|
max = maxFreq;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case kZoom1to1:
|
||||||
|
case kZoomDiv2:
|
||||||
|
case kZoomTimes2:
|
||||||
|
case kZoomHalfWave:
|
||||||
|
{
|
||||||
|
// Zoom out full
|
||||||
|
min = spectrumLinear ? 0.0f : 1.0f;
|
||||||
|
max = halfrate;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case kZoomInByDrag:
|
||||||
|
{
|
||||||
|
double xmin = 1 - (zoomEnd - ypos) / (float)height;
|
||||||
|
double xmax = 1 - (zoomStart - ypos) / (float)height;
|
||||||
|
const float middle = (xmin + xmax) / 2;
|
||||||
|
const float middleValue = scale.PositionToValue(middle);
|
||||||
|
|
||||||
|
min = std::max(spectrumLinear ? 0.0f : 1.0f,
|
||||||
|
std::min(middleValue - minBand / 2,
|
||||||
|
scale.PositionToValue(xmin)
|
||||||
|
));
|
||||||
|
max = std::min(halfrate,
|
||||||
|
std::max(middleValue + minBand / 2,
|
||||||
|
scale.PositionToValue(xmax)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case kZoomIn:
|
||||||
|
{
|
||||||
|
// Center the zoom-in at the click
|
||||||
|
const float p1 = (zoomStart - ypos) / (float)height;
|
||||||
|
const float middle = 1.0f - p1;
|
||||||
|
const float middleValue = scale.PositionToValue(middle);
|
||||||
|
|
||||||
|
if (fixedMousePoint) {
|
||||||
|
min = std::max(spectrumLinear ? 0.0f : 1.0f,
|
||||||
|
std::min(middleValue - minBand * middle,
|
||||||
|
scale.PositionToValue(0.5f * middle)
|
||||||
|
));
|
||||||
|
max = std::min(halfrate,
|
||||||
|
std::max(middleValue + minBand * p1,
|
||||||
|
scale.PositionToValue(middle + 0.5f * p1)
|
||||||
|
));
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
|
min = std::max(spectrumLinear ? 0.0f : 1.0f,
|
||||||
|
std::min(middleValue - minBand / 2,
|
||||||
|
scale.PositionToValue(middle - 0.25f)
|
||||||
|
));
|
||||||
|
max = std::min(halfrate,
|
||||||
|
std::max(middleValue + minBand / 2,
|
||||||
|
scale.PositionToValue(middle + 0.25f)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case kZoomOut:
|
||||||
|
{
|
||||||
|
// Zoom out
|
||||||
|
const float p1 = (zoomStart - ypos) / (float)height;
|
||||||
|
// (Used to zoom out centered at midline, ignoring the click, if linear view.
|
||||||
|
// I think it is better to be consistent. PRL)
|
||||||
|
// Center zoom-out at the midline
|
||||||
|
const float middle = // spectrumLinear ? 0.5f :
|
||||||
|
1.0f - p1;
|
||||||
|
|
||||||
|
if (fixedMousePoint) {
|
||||||
|
min = std::max(spectrumLinear ? 0.0f : 1.0f, scale.PositionToValue(-middle));
|
||||||
|
max = std::min(halfrate, scale.PositionToValue(1.0f + p1));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
min = std::max(spectrumLinear ? 0.0f : 1.0f, scale.PositionToValue(middle - 1.0f));
|
||||||
|
max = std::min(halfrate, scale.PositionToValue(middle + 1.0f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now actually apply the zoom.
|
||||||
|
for (auto channel : TrackList::Channels(pTrack))
|
||||||
|
channel->SetSpectrumBounds(min, max);
|
||||||
|
|
||||||
|
zoomEnd = zoomStart = 0;
|
||||||
|
if( pProject )
|
||||||
|
ProjectHistory::Get( *pProject ).ModifyState(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ZoomKind says how to zoom.
|
||||||
|
// If ZoomStart and ZoomEnd are not equal, this may override
|
||||||
|
// the zoomKind and cause a drag-zoom-in.
|
||||||
|
void WaveTrackVZoomHandle::DoWaveformZoom(
|
||||||
|
AudacityProject *pProject,
|
||||||
|
WaveTrack *pTrack,
|
||||||
|
WaveTrackViewConstants::ZoomActions ZoomKind,
|
||||||
|
const wxRect &rect, int zoomStart, int zoomEnd,
|
||||||
|
bool fixedMousePoint)
|
||||||
|
{
|
||||||
|
using namespace WaveTrackViewConstants;
|
||||||
|
static const float ZOOMLIMIT = 0.001f;
|
||||||
|
|
||||||
|
int height = rect.height;
|
||||||
|
int ypos = rect.y;
|
||||||
|
|
||||||
|
// Ensure start and end are in order (swap if not).
|
||||||
|
if (zoomEnd < zoomStart)
|
||||||
|
std::swap( zoomStart, zoomEnd );
|
||||||
|
|
||||||
|
float min, max, minBand = 0;
|
||||||
|
const double rate = pTrack->GetRate();
|
||||||
|
const float halfrate = rate / 2;
|
||||||
|
float maxFreq = 8000.0;
|
||||||
|
const SpectrogramSettings &specSettings = pTrack->GetSpectrogramSettings();
|
||||||
|
NumberScale scale;
|
||||||
|
|
||||||
|
bool bDragZoom = IsDragZooming(zoomStart, zoomEnd);
|
||||||
|
// Add 100 if spectral to separate the kinds of zoom.
|
||||||
|
|
||||||
|
// Possibly override the zoom kind.
|
||||||
|
if( bDragZoom )
|
||||||
|
ZoomKind = kZoomInByDrag;
|
||||||
|
|
||||||
|
float top=2.0;
|
||||||
|
float half=0.5;
|
||||||
|
|
||||||
|
{
|
||||||
pTrack->GetDisplayBounds(&min, &max);
|
pTrack->GetDisplayBounds(&min, &max);
|
||||||
const WaveformSettings &waveSettings = pTrack->GetWaveformSettings();
|
const WaveformSettings &waveSettings = pTrack->GetWaveformSettings();
|
||||||
const bool linear = waveSettings.isLinear();
|
const bool linear = waveSettings.isLinear();
|
||||||
@ -237,101 +376,11 @@ void WaveTrackVZoomHandle::DoZoom
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// VZooming on spectral we don't implement the other zoom presets.
|
|
||||||
// They are also not in the menu.
|
|
||||||
case kZoomReset + kSpectral:
|
|
||||||
{
|
|
||||||
// Zoom out to normal level.
|
|
||||||
min = spectrumLinear ? 0.0f : 1.0f;
|
|
||||||
max = maxFreq;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case kZoom1to1 + kSpectral:
|
|
||||||
case kZoomDiv2 + kSpectral:
|
|
||||||
case kZoomTimes2 + kSpectral:
|
|
||||||
case kZoomHalfWave + kSpectral:
|
|
||||||
{
|
|
||||||
// Zoom out full
|
|
||||||
min = spectrumLinear ? 0.0f : 1.0f;
|
|
||||||
max = halfrate;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case kZoomInByDrag + kSpectral:
|
|
||||||
{
|
|
||||||
double xmin = 1 - (zoomEnd - ypos) / (float)height;
|
|
||||||
double xmax = 1 - (zoomStart - ypos) / (float)height;
|
|
||||||
const float middle = (xmin + xmax) / 2;
|
|
||||||
const float middleValue = scale.PositionToValue(middle);
|
|
||||||
|
|
||||||
min = std::max(spectrumLinear ? 0.0f : 1.0f,
|
|
||||||
std::min(middleValue - minBand / 2,
|
|
||||||
scale.PositionToValue(xmin)
|
|
||||||
));
|
|
||||||
max = std::min(halfrate,
|
|
||||||
std::max(middleValue + minBand / 2,
|
|
||||||
scale.PositionToValue(xmax)
|
|
||||||
));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case kZoomIn + kSpectral:
|
|
||||||
{
|
|
||||||
// Center the zoom-in at the click
|
|
||||||
const float p1 = (zoomStart - ypos) / (float)height;
|
|
||||||
const float middle = 1.0f - p1;
|
|
||||||
const float middleValue = scale.PositionToValue(middle);
|
|
||||||
|
|
||||||
if (fixedMousePoint) {
|
|
||||||
min = std::max(spectrumLinear ? 0.0f : 1.0f,
|
|
||||||
std::min(middleValue - minBand * middle,
|
|
||||||
scale.PositionToValue(0.5f * middle)
|
|
||||||
));
|
|
||||||
max = std::min(halfrate,
|
|
||||||
std::max(middleValue + minBand * p1,
|
|
||||||
scale.PositionToValue(middle + 0.5f * p1)
|
|
||||||
));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
min = std::max(spectrumLinear ? 0.0f : 1.0f,
|
|
||||||
std::min(middleValue - minBand / 2,
|
|
||||||
scale.PositionToValue(middle - 0.25f)
|
|
||||||
));
|
|
||||||
max = std::min(halfrate,
|
|
||||||
std::max(middleValue + minBand / 2,
|
|
||||||
scale.PositionToValue(middle + 0.25f)
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case kZoomOut + kSpectral:
|
|
||||||
{
|
|
||||||
// Zoom out
|
|
||||||
const float p1 = (zoomStart - ypos) / (float)height;
|
|
||||||
// (Used to zoom out centered at midline, ignoring the click, if linear view.
|
|
||||||
// I think it is better to be consistent. PRL)
|
|
||||||
// Center zoom-out at the midline
|
|
||||||
const float middle = // spectrumLinear ? 0.5f :
|
|
||||||
1.0f - p1;
|
|
||||||
|
|
||||||
if (fixedMousePoint) {
|
|
||||||
min = std::max(spectrumLinear ? 0.0f : 1.0f, scale.PositionToValue(-middle));
|
|
||||||
max = std::min(halfrate, scale.PositionToValue(1.0f + p1));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
min = std::max(spectrumLinear ? 0.0f : 1.0f, scale.PositionToValue(middle - 1.0f));
|
|
||||||
max = std::min(halfrate, scale.PositionToValue(middle + 1.0f));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now actually apply the zoom.
|
// Now actually apply the zoom.
|
||||||
for (auto channel : TrackList::Channels(pTrack)) {
|
for (auto channel : TrackList::Channels(pTrack))
|
||||||
if (spectral)
|
|
||||||
channel->SetSpectrumBounds(min, max);
|
|
||||||
else
|
|
||||||
channel->SetDisplayBounds(min, max);
|
channel->SetDisplayBounds(min, max);
|
||||||
}
|
|
||||||
|
|
||||||
zoomEnd = zoomStart = 0;
|
zoomEnd = zoomStart = 0;
|
||||||
if( pProject )
|
if( pProject )
|
||||||
@ -401,9 +450,10 @@ void WaveTrackVRulerMenuTable::InitMenu(Menu *, void *pUserData)
|
|||||||
void WaveTrackVRulerMenuTable::OnZoom(
|
void WaveTrackVRulerMenuTable::OnZoom(
|
||||||
WaveTrackViewConstants::ZoomActions iZoomCode )
|
WaveTrackViewConstants::ZoomActions iZoomCode )
|
||||||
{
|
{
|
||||||
WaveTrackVZoomHandle::DoZoom
|
mpData->doZoom(
|
||||||
(::GetActiveProject(), mpData->pTrack,
|
::GetActiveProject(), mpData->pTrack,
|
||||||
iZoomCode, mpData->rect, mpData->yy, mpData->yy, false);
|
iZoomCode, mpData->rect, mpData->yy, mpData->yy, false
|
||||||
|
);
|
||||||
|
|
||||||
using namespace RefreshCode;
|
using namespace RefreshCode;
|
||||||
mpData->result = UpdateVRuler | RefreshAll;
|
mpData->result = UpdateVRuler | RefreshAll;
|
||||||
@ -648,7 +698,10 @@ UIHandle::Result WaveTrackVZoomHandle::Release
|
|||||||
!(event.ShiftDown() || event.CmdDown()))
|
!(event.ShiftDown() || event.CmdDown()))
|
||||||
{
|
{
|
||||||
InitMenuData data {
|
InitMenuData data {
|
||||||
pTrack.get(), mRect, RefreshCode::RefreshNone, event.m_y
|
pTrack.get(), mRect, RefreshCode::RefreshNone, event.m_y,
|
||||||
|
(pTrack->GetDisplay() == Spectrum)
|
||||||
|
? WaveTrackVZoomHandle::DoSpectrumZoom
|
||||||
|
: WaveTrackVZoomHandle::DoWaveformZoom
|
||||||
};
|
};
|
||||||
|
|
||||||
PopupMenuTable *const pTable =
|
PopupMenuTable *const pTable =
|
||||||
@ -687,7 +740,10 @@ UIHandle::Result WaveTrackVZoomHandle::Release
|
|||||||
if( bVZoom ) {
|
if( bVZoom ) {
|
||||||
if( shiftDown )
|
if( shiftDown )
|
||||||
mZoomStart = mZoomEnd;
|
mZoomStart = mZoomEnd;
|
||||||
DoZoom(pProject, pTrack.get(),
|
auto doZoom = (pTrack->GetDisplay() == Spectrum)
|
||||||
|
? WaveTrackVZoomHandle::DoSpectrumZoom
|
||||||
|
: WaveTrackVZoomHandle::DoWaveformZoom;
|
||||||
|
doZoom(pProject, pTrack.get(),
|
||||||
shiftDown
|
shiftDown
|
||||||
? (rightUp ? kZoom1to1 : kZoomOut)
|
? (rightUp ? kZoom1to1 : kZoomOut)
|
||||||
: kZoomIn,
|
: kZoomIn,
|
||||||
|
@ -28,8 +28,17 @@ public:
|
|||||||
|
|
||||||
WaveTrackVZoomHandle &operator=(const WaveTrackVZoomHandle&) = default;
|
WaveTrackVZoomHandle &operator=(const WaveTrackVZoomHandle&) = default;
|
||||||
|
|
||||||
static void DoZoom
|
using DoZoomFunction = void (*)( AudacityProject *pProject,
|
||||||
(AudacityProject *pProject,
|
WaveTrack *pTrack,
|
||||||
|
WaveTrackViewConstants::ZoomActions ZoomKind,
|
||||||
|
const wxRect &rect, int zoomStart, int zoomEnd,
|
||||||
|
bool fixedMousePoint);
|
||||||
|
static void DoSpectrumZoom( AudacityProject *pProject,
|
||||||
|
WaveTrack *pTrack,
|
||||||
|
WaveTrackViewConstants::ZoomActions ZoomKind,
|
||||||
|
const wxRect &rect, int zoomStart, int zoomEnd,
|
||||||
|
bool fixedMousePoint);
|
||||||
|
static void DoWaveformZoom( AudacityProject *pProject,
|
||||||
WaveTrack *pTrack,
|
WaveTrack *pTrack,
|
||||||
WaveTrackViewConstants::ZoomActions ZoomKind,
|
WaveTrackViewConstants::ZoomActions ZoomKind,
|
||||||
const wxRect &rect, int zoomStart, int zoomEnd,
|
const wxRect &rect, int zoomStart, int zoomEnd,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user