1
0
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:
Paul Licameli 2019-07-06 19:58:48 -04:00
parent fa7de8ce3a
commit f7dc21436d
3 changed files with 187 additions and 119 deletions

View File

@ -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

View File

@ -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,

View File

@ -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,