1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-07-13 15:17:42 +02:00

Vertical ruler zooming uses NumberScale in a generalized way

This commit is contained in:
Paul Licameli 2015-06-18 20:20:06 -04:00
parent 43b7df701b
commit 66e939275f

View File

@ -4593,7 +4593,6 @@ void TrackPanel::HandleVZoomDrag( wxMouseEvent & event )
/// - Zoom in; ensure we don't go too large.
void TrackPanel::HandleVZoomButtonUp( wxMouseEvent & event )
{
int minBins = 0;
if (!mCapturedTrack)
return;
@ -4623,6 +4622,7 @@ void TrackPanel::HandleVZoomButtonUp( wxMouseEvent & event )
// don't do anything if track is not wave
if (mCapturedTrack->GetKind() != Track::Wave)
return;
WaveTrack *track = static_cast<WaveTrack*>(mCapturedTrack);
WaveTrack *partner = static_cast<WaveTrack *>(mTracks->GetLink(track));
int height = track->GetHeight();
@ -4635,223 +4635,173 @@ void TrackPanel::HandleVZoomButtonUp( wxMouseEvent & event )
mZoomStart = temp;
}
float min, max, c, l, binSize = 0.0;
float min, max, c, l, minBand = 0;
const double rate = track->GetRate();
const float halfrate = rate / 2;
const SpectrogramSettings &settings = track->GetSpectrogramSettings();
NumberScale scale(track->GetSpectrogramSettings().GetScale(rate, false, false));
const bool spectral = (track->GetDisplay() == WaveTrack::Spectrum);
const bool spectrumLinear = spectral &&
(track->GetSpectrogramSettings().scaleType == SpectrogramSettings::stLinear);
const bool spectrumLog = spectral &&
(track->GetSpectrogramSettings().scaleType == SpectrogramSettings::stLogarithmic);
if (spectrumLinear) {
const SpectrogramSettings &settings = track->GetSpectrogramSettings();
min = settings.GetMinFreq(rate);
max = settings.GetMaxFreq(rate);
if (spectral) {
if (spectrumLinear) {
min = settings.GetMinFreq(rate);
max = settings.GetMaxFreq(rate);
}
else {
min = settings.GetLogMinFreq(rate);
max = settings.GetLogMaxFreq(rate);
}
const int fftLength = settings.GetFFTLength(false);
binSize = rate / fftLength;
minBins = std::min(10, fftLength / 2); //minimum 10 freq bins, unless there are less
}
else if (spectrumLog) {
const SpectrogramSettings &settings = track->GetSpectrogramSettings();
min = settings.GetLogMinFreq(rate);
max = settings.GetLogMaxFreq(rate);
const int fftLength = settings.GetFFTLength(false);
binSize = rate / fftLength;
minBins = std::min(10, fftLength / 2); //minimum 10 freq bins, unless there are less
const float binSize = rate / fftLength;
const int minBins =
std::min(10, fftLength / 2); //minimum 10 freq bins, unless there are less
minBand = minBins * binSize;
}
else
track->GetDisplayBounds(&min, &max);
if (IsDragZooming()) {
// Drag Zoom
float p1, p2, tmin, tmax;
tmin=min;
tmax=max;
const float tmin = min, tmax = max;
if(spectrumLog) {
double xmin = 1-(mZoomEnd - ypos) / (float)height;
double xmax = 1-(mZoomStart - ypos) / (float)height;
double lmin=log10(tmin), lmax=log10(tmax);
double d=lmax-lmin;
min=std::max(1.0, pow(10, xmin*d+lmin));
max=std::min(rate/2.0, pow(10, xmax*d+lmin));
// Enforce vertical zoom limits
// done in the linear freq domain for now, but not too far out
if(max < min + minBins * binSize)
max = min + minBins * binSize;
if(max > rate/2.) {
max = rate/2.;
min = max - minBins * binSize;
}
if (spectral) {
double xmin = 1 - (mZoomEnd - ypos) / (float)height;
double xmax = 1 - (mZoomStart - 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)
));
}
else {
p1 = (mZoomStart - ypos) / (float)height;
p2 = (mZoomEnd - ypos) / (float)height;
const float p1 = (mZoomStart - ypos) / (float)height;
const float p2 = (mZoomEnd - ypos) / (float)height;
max = (tmax * (1.0-p1) + tmin * p1);
min = (tmax * (1.0-p2) + tmin * p2);
// Enforce vertical zoom limits
if(spectrumLinear) {
if(min < 0.)
min = 0.;
if(max < min + minBins * binSize)
max = min + minBins * binSize;
if(max > rate/2.) {
max = rate/2.;
min = max - minBins * binSize;
}
}
else {
// Waveform view - allow zooming down to a range of ZOOMLIMIT
if (max - min < ZOOMLIMIT) { // if user attempts to go smaller...
c = (min+max)/2; // ...set centre of view to centre of dragged area and top/bottom to ZOOMLIMIT/2 above/below
min = c - ZOOMLIMIT/2.0;
max = c + ZOOMLIMIT/2.0;
}
// Waveform view - allow zooming down to a range of ZOOMLIMIT
if (max - min < ZOOMLIMIT) { // if user attempts to go smaller...
c = (min+max)/2; // ...set centre of view to centre of dragged area and top/bottom to ZOOMLIMIT/2 above/below
min = c - ZOOMLIMIT/2.0;
max = c + ZOOMLIMIT/2.0;
}
}
}
else if (event.ShiftDown() || event.RightUp()) {
// Zoom OUT
// Zoom out to -1.0...1.0 first, then, and only
// then, if they click again, allow one more
// zoom out.
if (spectrumLinear) {
if (spectral) {
if (event.ShiftDown() && event.RightUp()) {
// Zoom out full
min = 0.0;
max = rate/2.;
min = spectrumLinear ? 0.0f : 1.0f;
max = halfrate;
}
else {
// Zoom out
c = 0.5*(min+max);
l = (c - min);
if(c - 2*l <= 0) {
min = 0.0;
max = std::min( rate/2., 2. * max);
}
else {
min = std::max( 0.0f, c - 2*l);
max = std::min( float(rate)/2, c + 2*l);
}
// (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 - (mZoomStart - ypos) / (float)height;
min = std::max(spectrumLinear ? 0.0f : 1.0f, scale.PositionToValue(middle - 1.0f));
max = std::min(halfrate, scale.PositionToValue(middle + 1.0f));
}
}
else {
if(spectrumLog) {
if (event.ShiftDown() && event.RightUp()) {
// Zoom out full
min = 1.0;
max = rate/2.;
}
else {
// Zoom out
float p1;
p1 = (mZoomStart - ypos) / (float)height;
c = 1.0-p1;
double xmin = c - 1.;
double xmax = c + 1.;
double lmin = log10(min), lmax = log10(max);
double d = lmax-lmin;
min = std::max(1.0f,float(pow(10, xmin*d+lmin)));
max = std::min(rate/2., pow(10, xmax*d+lmin));
}
// Zoom out to -1.0...1.0 first, then, and only
// then, if they click again, allow one more
// zoom out.
if (event.ShiftDown() && event.RightUp()) {
// Zoom out full
min = -1.0;
max = 1.0;
}
else {
if (event.ShiftDown() && event.RightUp()) {
// Zoom out full
min = -1.0;
max = 1.0;
// Zoom out
if (min <= -1.0 && max >= 1.0) {
min = -2.0;
max = 2.0;
}
else {
// Zoom out
if (min <= -1.0 && max >= 1.0) {
min = -2.0;
max = 2.0;
}
else {
c = 0.5*(min+max);
l = (c - min);
// limit to +/- 1 range unless already outside that range...
float minRange = (min < -1) ? -2.0 : -1.0;
float maxRange = (max > 1) ? 2.0 : 1.0;
// and enforce vertical zoom limits.
min = std::min(maxRange - ZOOMLIMIT, std::max(minRange, c - 2*l));
max = std::max(minRange + ZOOMLIMIT, std::min(maxRange, c + 2*l));
}
c = 0.5*(min + max);
l = (c - min);
// limit to +/- 1 range unless already outside that range...
float minRange = (min < -1) ? -2.0 : -1.0;
float maxRange = (max > 1) ? 2.0 : 1.0;
// and enforce vertical zoom limits.
min = std::min(maxRange - ZOOMLIMIT, std::max(minRange, c - 2 * l));
max = std::max(minRange + ZOOMLIMIT, std::min(maxRange, c + 2 * l));
}
}
}
}
else {
// Zoom IN
float p1;
if (spectrumLinear) {
c = 0.5*(min+max);
// Enforce maximum vertical zoom
l = std::max( minBins * binSize, (c - min));
if (spectral) {
// Center the zoom-in at the click
const float middle = 1.0f - (mZoomStart - ypos) / (float)height;
const float middleValue = scale.PositionToValue(middle);
p1 = (mZoomStart - ypos) / (float)height;
c = (max * (1.0-p1) + min * p1);
min = std::max( 0.0, c - 0.5*l);
max = std::min( float(rate)/2, min + l);
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)
));
}
else {
if(spectrumLog) {
p1 = (mZoomStart - ypos) / (float)height;
c = 1.0-p1;
double xmin = c - 0.25;
double xmax = c + 0.25;
double lmin = log10(min), lmax = log10(max);
double d = lmax-lmin;
min = std::max(1.0f, float(pow(10, xmin*d+lmin)));
max = std::min(rate/2., pow(10, xmax*d+lmin));
// Enforce vertical zoom limits
// done in the linear freq domain for now, but not too far out
if(max < min + minBins * binSize)
max = min + minBins * binSize;
if(max > rate/2.) {
max = rate/2.;
min = max - minBins * binSize;
}
// Zoom in centered on cursor
float p1;
if (min < -1.0 || max > 1.0) {
min = -1.0;
max = 1.0;
}
else {
// Zoom in centered on cursor
if (min < -1.0 || max > 1.0) {
min = -1.0;
max = 1.0;
}
else {
c = 0.5*(min+max);
// Enforce maximum vertical zoom
l = std::max( ZOOMLIMIT, (c - min));
c = 0.5*(min + max);
// Enforce maximum vertical zoom
l = std::max(ZOOMLIMIT, (c - min));
p1 = (mZoomStart - ypos) / (float)height;
c = (max * (1.0-p1) + min * p1);
min = c - 0.5*l;
max = c + 0.5*l;
}
p1 = (mZoomStart - ypos) / (float)height;
c = (max * (1.0 - p1) + min * p1);
min = c - 0.5*l;
max = c + 0.5*l;
}
}
}
if (spectrumLinear) {
SpectrogramSettings &settings = track->GetSpectrogramSettings();
settings.SetMinFreq(min);
settings.SetMaxFreq(max);
if (partner) {
// To do: share memory with reference counting?
SpectrogramSettings &settings = partner->GetSpectrogramSettings();
if (spectral) {
if (spectrumLinear) {
SpectrogramSettings &settings = track->GetSpectrogramSettings();
settings.SetMinFreq(min);
settings.SetMaxFreq(max);
if (partner) {
// To do: share memory with reference counting?
SpectrogramSettings &settings = partner->GetSpectrogramSettings();
settings.SetMinFreq(min);
settings.SetMaxFreq(max);
}
}
}
else if(spectrumLog) {
SpectrogramSettings &settings = track->GetSpectrogramSettings();
settings.SetLogMinFreq(min);
settings.SetLogMaxFreq(max);
if (partner) {
// To do: share memory with reference counting?
SpectrogramSettings &settings = partner->GetSpectrogramSettings();
else {
SpectrogramSettings &settings = track->GetSpectrogramSettings();
settings.SetLogMinFreq(min);
settings.SetLogMaxFreq(max);
if (partner) {
// To do: share memory with reference counting?
SpectrogramSettings &settings = partner->GetSpectrogramSettings();
settings.SetLogMinFreq(min);
settings.SetLogMaxFreq(max);
}
}
}
else {