diff --git a/src/TrackPanel.cpp b/src/TrackPanel.cpp index 382fbb40f..f419eb49d 100644 --- a/src/TrackPanel.cpp +++ b/src/TrackPanel.cpp @@ -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(mCapturedTrack); WaveTrack *partner = static_cast(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 {