mirror of
https://github.com/cookiengineer/audacity
synced 2025-08-07 23:51:14 +02:00
Some preliminary changes to SpectrogramSettings, for View Settings project
This commit is contained in:
commit
ca767c0f7a
@ -39,13 +39,13 @@
|
||||
* 9: Gaussian(a=4.5)
|
||||
*/
|
||||
|
||||
#include "FFT.h"
|
||||
|
||||
#include <wx/intl.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "FFT.h"
|
||||
|
||||
static int **gFFTBitTable = NULL;
|
||||
static const int MaxFastBits = 16;
|
||||
|
||||
|
@ -32,6 +32,8 @@
|
||||
#ifndef __AUDACITY_FFT_H__
|
||||
#define __AUDACITY_FFT_H__
|
||||
|
||||
#include <wx/defs.h>
|
||||
|
||||
/*
|
||||
Salvo Ventura - November 2006
|
||||
Added more window functions:
|
||||
|
@ -477,6 +477,8 @@ audacity_SOURCES = \
|
||||
prefs/QualityPrefs.h \
|
||||
prefs/RecordingPrefs.cpp \
|
||||
prefs/RecordingPrefs.h \
|
||||
prefs/SpectrogramSettings.cpp \
|
||||
prefs/SpectrogramSettings.h \
|
||||
prefs/SpectrumPrefs.cpp \
|
||||
prefs/SpectrumPrefs.h \
|
||||
prefs/ThemePrefs.cpp \
|
||||
|
@ -173,7 +173,7 @@ audio tracks.
|
||||
#include "LabelTrack.h"
|
||||
#include "TimeTrack.h"
|
||||
#include "Prefs.h"
|
||||
#include "prefs/SpectrumPrefs.h"
|
||||
#include "prefs/SpectrogramSettings.h"
|
||||
#include "Sequence.h"
|
||||
#include "Spectrum.h"
|
||||
#include "ViewInfo.h"
|
||||
@ -692,7 +692,7 @@ void TrackArtist::UpdateVRuler(Track *t, wxRect & rect)
|
||||
// All waves have a ruler in the info panel
|
||||
// The ruler needs a bevelled surround.
|
||||
if (t->GetKind() == Track::Wave) {
|
||||
WaveTrack *wt = (WaveTrack *)t;
|
||||
WaveTrack *wt = static_cast<WaveTrack*>(t);
|
||||
int display = wt->GetDisplay();
|
||||
|
||||
if (display == WaveTrack::WaveformDisplay) {
|
||||
@ -802,16 +802,10 @@ void TrackArtist::UpdateVRuler(Track *t, wxRect & rect)
|
||||
if (rect.height < 60)
|
||||
return;
|
||||
|
||||
double rate = wt->GetRate();
|
||||
int freq = lrint(rate/2.);
|
||||
|
||||
int maxFreq = GetSpectrumMaxFreq(freq);
|
||||
if(maxFreq > freq)
|
||||
maxFreq = freq;
|
||||
|
||||
int minFreq = GetSpectrumMinFreq(0);
|
||||
if(minFreq < 0)
|
||||
minFreq = 0;
|
||||
const SpectrogramSettings &settings = wt->GetSpectrogramSettings();
|
||||
const double rate = wt->GetRate();
|
||||
const int maxFreq = settings.GetMaxFreq(rate);
|
||||
const int minFreq = settings.GetMinFreq(rate);
|
||||
|
||||
/*
|
||||
draw the ruler
|
||||
@ -842,16 +836,10 @@ void TrackArtist::UpdateVRuler(Track *t, wxRect & rect)
|
||||
if (rect.height < 10)
|
||||
return;
|
||||
|
||||
double rate = wt->GetRate();
|
||||
int freq = lrint(rate/2.);
|
||||
|
||||
int maxFreq = GetSpectrumLogMaxFreq(freq);
|
||||
if(maxFreq > freq)
|
||||
maxFreq = freq;
|
||||
|
||||
int minFreq = GetSpectrumLogMinFreq(freq/1000.0);
|
||||
if(minFreq < 1)
|
||||
minFreq = 1;
|
||||
const SpectrogramSettings &settings = wt->GetSpectrogramSettings();
|
||||
const double rate = wt->GetRate();
|
||||
const int maxFreq = settings.GetLogMaxFreq(rate);
|
||||
const int minFreq = settings.GetLogMinFreq(rate);
|
||||
|
||||
/*
|
||||
draw the ruler
|
||||
@ -2042,6 +2030,8 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &waveTrackCache,
|
||||
#endif
|
||||
|
||||
const WaveTrack *const track = waveTrackCache.GetTrack();
|
||||
const SpectrogramSettings &settings = track->GetSpectrogramSettings();
|
||||
|
||||
const int display = track->GetDisplay();
|
||||
const bool autocorrelation = (WaveTrack::PitchDisplay == display);
|
||||
const bool logF = (WaveTrack::SpectrumLogDisplay == display
|
||||
@ -2079,7 +2069,6 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &waveTrackCache,
|
||||
}
|
||||
#endif
|
||||
|
||||
const SpectrogramSettings &settings = SpectrogramSettings::defaults();
|
||||
const bool &isGrayscale = settings.isGrayscale;
|
||||
const int &range = settings.range;
|
||||
const int &gain = settings.gain;
|
||||
@ -2104,7 +2093,7 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &waveTrackCache,
|
||||
return;
|
||||
unsigned char *data = image->GetData();
|
||||
|
||||
const int half = GetSpectrumWindowSize(!autocorrelation) / 2;
|
||||
const int half = settings.GetFFTLength(autocorrelation) / 2;
|
||||
const double binUnit = rate / (2 * half);
|
||||
const float *freq = 0;
|
||||
const sampleCount *where = 0;
|
||||
@ -2115,28 +2104,8 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &waveTrackCache,
|
||||
t0, pps, autocorrelation);
|
||||
}
|
||||
|
||||
int ifreq = lrint(rate / 2);
|
||||
|
||||
int maxFreq;
|
||||
if (!logF)
|
||||
maxFreq = GetSpectrumMaxFreq(ifreq);
|
||||
else
|
||||
maxFreq = GetSpectrumLogMaxFreq(ifreq);
|
||||
if(maxFreq > ifreq)
|
||||
maxFreq = ifreq;
|
||||
|
||||
int minFreq;
|
||||
if (!logF) {
|
||||
minFreq = GetSpectrumMinFreq(0);
|
||||
if(minFreq < 0)
|
||||
minFreq = 0;
|
||||
}
|
||||
else {
|
||||
minFreq = GetSpectrumLogMinFreq(ifreq/1000.0);
|
||||
if(minFreq < 1)
|
||||
// Paul L: I suspect this line is now unreachable
|
||||
minFreq = 1.0;
|
||||
}
|
||||
const int minFreq = logF ? settings.GetLogMinFreq(rate) : settings.GetMinFreq(rate);
|
||||
const int maxFreq = logF ? settings.GetLogMaxFreq(rate) : settings.GetMaxFreq(rate);
|
||||
|
||||
float minBin = ((double)minFreq / binUnit);
|
||||
float maxBin = ((double)maxFreq / binUnit);
|
||||
@ -3217,66 +3186,6 @@ void TrackArtist::UpdatePrefs()
|
||||
gPrefs->Flush();
|
||||
}
|
||||
|
||||
// Get various preference values
|
||||
int TrackArtist::GetSpectrumMinFreq(int deffreq)
|
||||
{
|
||||
const int &minFreq = SpectrogramSettings::defaults().minFreq;
|
||||
return minFreq < 0 ? deffreq : minFreq;
|
||||
}
|
||||
|
||||
int TrackArtist::GetSpectrumMaxFreq(int deffreq)
|
||||
{
|
||||
const int &maxFreq = SpectrogramSettings::defaults().maxFreq;
|
||||
return maxFreq < 0 ? deffreq : maxFreq;
|
||||
}
|
||||
|
||||
int TrackArtist::GetSpectrumLogMinFreq(int deffreq)
|
||||
{
|
||||
const int &logMinFreq = SpectrogramSettings::defaults().logMinFreq;
|
||||
return logMinFreq < 0 ? deffreq : logMinFreq;
|
||||
}
|
||||
|
||||
int TrackArtist::GetSpectrumLogMaxFreq(int deffreq)
|
||||
{
|
||||
const int &logMaxFreq = SpectrogramSettings::defaults().logMaxFreq;
|
||||
return logMaxFreq < 0 ? deffreq : logMaxFreq;
|
||||
}
|
||||
|
||||
int TrackArtist::GetSpectrumWindowSize(bool includeZeroPadding)
|
||||
{
|
||||
includeZeroPadding;
|
||||
const int &windowSize = SpectrogramSettings::defaults().windowSize;
|
||||
#ifdef EXPERIMENTAL_ZERO_PADDED_SPECTROGRAMS
|
||||
if (includeZeroPadding) {
|
||||
const int &zeroPaddingFactor = SpectrogramSettings::defaults().zeroPaddingFactor;
|
||||
return windowSize * zeroPaddingFactor;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
return windowSize;
|
||||
}
|
||||
|
||||
// Set various preference values
|
||||
void TrackArtist::SetSpectrumMinFreq(int freq)
|
||||
{
|
||||
SpectrogramSettings::defaults().minFreq = freq;
|
||||
}
|
||||
|
||||
void TrackArtist::SetSpectrumMaxFreq(int freq)
|
||||
{
|
||||
SpectrogramSettings::defaults().maxFreq = freq;
|
||||
}
|
||||
|
||||
void TrackArtist::SetSpectrumLogMinFreq(int freq)
|
||||
{
|
||||
SpectrogramSettings::defaults().logMinFreq = freq;
|
||||
}
|
||||
|
||||
void TrackArtist::SetSpectrumLogMaxFreq(int freq)
|
||||
{
|
||||
SpectrogramSettings::defaults().logMaxFreq = freq;
|
||||
}
|
||||
|
||||
// Draws the sync-lock bitmap, tiled; always draws stationary relative to the DC
|
||||
//
|
||||
// AWD: now that the tiles don't link together, we're drawing a tilted grid, at
|
||||
|
@ -73,16 +73,6 @@ class AUDACITY_DLL_API TrackArtist {
|
||||
|
||||
void InvalidateSpectrumCache(TrackList *tracks);
|
||||
void InvalidateSpectrumCache(WaveTrack *track);
|
||||
int GetSpectrumMinFreq(int deffreq);
|
||||
int GetSpectrumMaxFreq(int deffreq);
|
||||
int GetSpectrumLogMinFreq(int deffreq);
|
||||
int GetSpectrumLogMaxFreq(int deffreq);
|
||||
int GetSpectrumWindowSize(bool includeZeroPadding);
|
||||
|
||||
void SetSpectrumMinFreq(int freq);
|
||||
void SetSpectrumMaxFreq(int freq);
|
||||
void SetSpectrumLogMinFreq(int freq);
|
||||
void SetSpectrumLogMaxFreq(int freq);
|
||||
|
||||
void SetBackgroundBrushes(wxBrush unselectedBrush, wxBrush selectedBrush,
|
||||
wxPen unselectedPen, wxPen selectedPen) {
|
||||
|
@ -217,7 +217,7 @@ is time to refresh some aspect of the screen.
|
||||
|
||||
#include "ondemand/ODManager.h"
|
||||
|
||||
#include "prefs/SpectrumPrefs.h"
|
||||
#include "prefs/SpectrogramSettings.h"
|
||||
|
||||
#include "toolbars/ControlToolBar.h"
|
||||
#include "toolbars/ToolManager.h"
|
||||
@ -230,7 +230,7 @@ is time to refresh some aspect of the screen.
|
||||
|
||||
#include <wx/arrimpl.cpp>
|
||||
|
||||
#define ZOOMLIMIT 0.001
|
||||
#define ZOOMLIMIT 0.001f
|
||||
|
||||
WX_DEFINE_OBJARRAY(TrackClipArray);
|
||||
|
||||
@ -2992,10 +2992,10 @@ inline double findMaxRatio(double center, double rate)
|
||||
|
||||
}
|
||||
|
||||
void TrackPanel::SnapCenterOnce(WaveTrack *pTrack, bool up)
|
||||
void TrackPanel::SnapCenterOnce(const WaveTrack *pTrack, bool up)
|
||||
{
|
||||
// Always spectrogram, never pitch view, pass true
|
||||
const int windowSize = mTrackArtist->GetSpectrumWindowSize(true);
|
||||
const SpectrogramSettings &settings = pTrack->GetSpectrogramSettings();
|
||||
const int windowSize = settings.GetFFTLength(false);
|
||||
const double rate = pTrack->GetRate();
|
||||
const double nyq = rate / 2.0;
|
||||
const double binFrequency = rate / windowSize;
|
||||
@ -3032,7 +3032,7 @@ void TrackPanel::SnapCenterOnce(WaveTrack *pTrack, bool up)
|
||||
(snappedFrequency / ratio, snappedFrequency * ratio);
|
||||
}
|
||||
|
||||
void TrackPanel::StartSnappingFreqSelection (WaveTrack *pTrack)
|
||||
void TrackPanel::StartSnappingFreqSelection (const WaveTrack *pTrack)
|
||||
{
|
||||
static const sampleCount minLength = 8;
|
||||
|
||||
@ -3057,12 +3057,13 @@ void TrackPanel::StartSnappingFreqSelection (WaveTrack *pTrack)
|
||||
// Use same settings as are now used for spectrogram display,
|
||||
// except, shrink the window as needed so we get some answers
|
||||
|
||||
// Always spectrogram, never pitch view, pass true
|
||||
int windowSize = mTrackArtist->GetSpectrumWindowSize(true);
|
||||
const SpectrogramSettings &settings = pTrack->GetSpectrogramSettings();
|
||||
int windowSize = settings.GetFFTLength(false);
|
||||
|
||||
while(windowSize > effectiveLength)
|
||||
windowSize >>= 1;
|
||||
const int windowType = SpectrogramSettings::defaults().windowType;
|
||||
const int windowType = settings.windowType;
|
||||
|
||||
mFrequencySnapper->Calculate(
|
||||
SpectrumAnalyst::Spectrum, windowType, windowSize, rate,
|
||||
&frequencySnappingData[0], length);
|
||||
@ -3087,8 +3088,8 @@ void TrackPanel::MoveSnappingFreqSelection (int mouseYCoordinate,
|
||||
// I am not worrying about that odd case.
|
||||
const double rate = wt->GetRate();
|
||||
const double frequency =
|
||||
PositionToFrequency(false, mouseYCoordinate,
|
||||
trackTopEdge, trackHeight, rate, logF);
|
||||
PositionToFrequency(wt, false, mouseYCoordinate,
|
||||
trackTopEdge, trackHeight, logF);
|
||||
const double snappedFrequency =
|
||||
mFrequencySnapper->FindPeak(frequency, NULL);
|
||||
const double maxRatio = findMaxRatio(snappedFrequency, rate);
|
||||
@ -3124,10 +3125,9 @@ void TrackPanel::StartFreqSelection (int mouseYCoordinate, int trackTopEdge,
|
||||
if (isSpectrogramTrack(pTrack, &logF)) {
|
||||
mFreqSelTrack = static_cast<WaveTrack*>(pTrack);
|
||||
mFreqSelMode = FREQ_SEL_FREE;
|
||||
const double rate = mFreqSelTrack->GetRate();
|
||||
mFreqSelPin =
|
||||
PositionToFrequency(false, mouseYCoordinate,
|
||||
trackTopEdge, trackHeight, rate, logF);
|
||||
PositionToFrequency(mFreqSelTrack, false, mouseYCoordinate,
|
||||
trackTopEdge, trackHeight, logF);
|
||||
mViewInfo->selectedRegion.setFrequencies(mFreqSelPin, mFreqSelPin);
|
||||
}
|
||||
}
|
||||
@ -3152,8 +3152,8 @@ void TrackPanel::ExtendFreqSelection(int mouseYCoordinate, int trackTopEdge,
|
||||
;
|
||||
const double rate = wt->GetRate();
|
||||
const double frequency =
|
||||
PositionToFrequency(true, mouseYCoordinate,
|
||||
trackTopEdge, trackHeight, rate, logF);
|
||||
PositionToFrequency(wt, true, mouseYCoordinate,
|
||||
trackTopEdge, trackHeight, logF);
|
||||
|
||||
// Dragging center?
|
||||
if (mFreqSelMode == FREQ_SEL_DRAG_CENTER) {
|
||||
@ -3528,13 +3528,15 @@ enum { FREQ_SNAP_DISTANCE = 10 };
|
||||
|
||||
/// Converts a position (mouse Y coordinate) to
|
||||
/// frequency, in Hz.
|
||||
double TrackPanel::PositionToFrequency(bool maySnap,
|
||||
double TrackPanel::PositionToFrequency(const WaveTrack *wt,
|
||||
bool maySnap,
|
||||
wxInt64 mouseYCoordinate,
|
||||
wxInt64 trackTopEdge,
|
||||
int trackHeight,
|
||||
double rate,
|
||||
bool logF) const
|
||||
{
|
||||
const double rate = wt->GetRate();
|
||||
|
||||
// Handle snapping
|
||||
if (maySnap &&
|
||||
mouseYCoordinate - trackTopEdge < FREQ_SNAP_DISTANCE)
|
||||
@ -3544,42 +3546,38 @@ double TrackPanel::PositionToFrequency(bool maySnap,
|
||||
return -1;
|
||||
|
||||
const double p = double(mouseYCoordinate - trackTopEdge) / trackHeight;
|
||||
const int freq = lrint(rate/2.);
|
||||
|
||||
if (logF)
|
||||
{
|
||||
const double maxFreq =
|
||||
std::min(freq, mTrackArtist->GetSpectrumLogMaxFreq(freq));
|
||||
const double minFreq =
|
||||
std::max(1, mTrackArtist->GetSpectrumLogMinFreq(1));
|
||||
const SpectrogramSettings &settings = wt->GetSpectrogramSettings();
|
||||
const double maxFreq = settings.GetLogMaxFreq(rate);
|
||||
const double minFreq = settings.GetLogMinFreq(rate);
|
||||
return exp(p * log(minFreq) + (1.0 - p) * log(maxFreq));
|
||||
}
|
||||
else
|
||||
{
|
||||
const double maxFreq =
|
||||
std::min(freq, mTrackArtist->GetSpectrumMaxFreq(freq));
|
||||
const double minFreq =
|
||||
std::max(0, mTrackArtist->GetSpectrumMinFreq(0));
|
||||
const SpectrogramSettings &settings = wt->GetSpectrogramSettings();
|
||||
const double maxFreq = settings.GetMaxFreq(rate);
|
||||
const double minFreq = settings.GetMinFreq(rate);
|
||||
return p * minFreq + (1.0 - p) * maxFreq;
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts a frequency to screen y position.
|
||||
wxInt64 TrackPanel::FrequencyToPosition(double frequency,
|
||||
wxInt64 TrackPanel::FrequencyToPosition(const WaveTrack *wt,
|
||||
double frequency,
|
||||
wxInt64 trackTopEdge,
|
||||
int trackHeight,
|
||||
double rate,
|
||||
bool logF) const
|
||||
{
|
||||
const int freq = lrint(rate/2.);
|
||||
const double rate = wt->GetRate();
|
||||
double p = 0;
|
||||
|
||||
if (logF)
|
||||
{
|
||||
const double maxFreq =
|
||||
std::min(freq, mTrackArtist->GetSpectrumLogMaxFreq(freq));
|
||||
const double minFreq =
|
||||
std::max(1, mTrackArtist->GetSpectrumLogMinFreq(1));
|
||||
const SpectrogramSettings &settings = wt->GetSpectrogramSettings();
|
||||
const double maxFreq = settings.GetLogMaxFreq(rate);
|
||||
const double minFreq = settings.GetLogMinFreq(rate);
|
||||
if (maxFreq > minFreq)
|
||||
{
|
||||
const double
|
||||
@ -3591,10 +3589,9 @@ wxInt64 TrackPanel::FrequencyToPosition(double frequency,
|
||||
}
|
||||
else
|
||||
{
|
||||
const double maxFreq =
|
||||
std::min(freq, mTrackArtist->GetSpectrumMaxFreq(freq));
|
||||
const double minFreq =
|
||||
std::max(0, mTrackArtist->GetSpectrumMinFreq(0));
|
||||
const SpectrogramSettings &settings = wt->GetSpectrogramSettings();
|
||||
const double maxFreq = settings.GetMaxFreq(rate);
|
||||
const double minFreq = settings.GetMinFreq(rate);
|
||||
if (maxFreq > minFreq)
|
||||
p = (frequency - minFreq) / (maxFreq - minFreq);
|
||||
}
|
||||
@ -3687,12 +3684,10 @@ bool mayDragWidth, bool onlyWithinSnapDistance,
|
||||
isSpectrogramTrack(pTrack, &logF)) {
|
||||
const WaveTrack *const wt = static_cast<const WaveTrack*>(pTrack);
|
||||
const wxInt64 bottomSel = (f0 >= 0)
|
||||
? FrequencyToPosition(f0, rect.y, rect.height,
|
||||
wt->GetRate(), logF)
|
||||
? FrequencyToPosition(wt, f0, rect.y, rect.height, logF)
|
||||
: rect.y + rect.height;
|
||||
const wxInt64 topSel = (f1 >= 0)
|
||||
? FrequencyToPosition(f1, rect.y, rect.height,
|
||||
wt->GetRate(), logF)
|
||||
? FrequencyToPosition(wt, f1, rect.y, rect.height, logF)
|
||||
: rect.y;
|
||||
wxInt64 signedBottomDist = int(event.m_y - bottomSel);
|
||||
wxInt64 verticalDist = abs(signedBottomDist);
|
||||
@ -3710,8 +3705,7 @@ bool mayDragWidth, bool onlyWithinSnapDistance,
|
||||
#endif
|
||||
) {
|
||||
const wxInt64 centerSel =
|
||||
FrequencyToPosition(fc, rect.y, rect.height,
|
||||
wt->GetRate(), logF);
|
||||
FrequencyToPosition(wt, fc, rect.y, rect.height, logF);
|
||||
const wxInt64 centerDist = abs(int(event.m_y - centerSel));
|
||||
if (centerDist < verticalDist)
|
||||
chooseCenter = true, verticalDist = centerDist,
|
||||
@ -4682,8 +4676,8 @@ void TrackPanel::HandleVZoomButtonUp( wxMouseEvent & event )
|
||||
// don't do anything if track is not wave
|
||||
if (mCapturedTrack->GetKind() != Track::Wave)
|
||||
return;
|
||||
WaveTrack *track = (WaveTrack *)mCapturedTrack;
|
||||
WaveTrack *partner = (WaveTrack *)mTracks->GetLink(track);
|
||||
WaveTrack *track = static_cast<WaveTrack*>(mCapturedTrack);
|
||||
WaveTrack *partner = static_cast<WaveTrack *>(mTracks->GetLink(track));
|
||||
int height = track->GetHeight();
|
||||
int ypos = mCapturedRect.y;
|
||||
|
||||
@ -4695,40 +4689,27 @@ void TrackPanel::HandleVZoomButtonUp( wxMouseEvent & event )
|
||||
}
|
||||
|
||||
float min, max, c, l, binSize = 0.0;
|
||||
bool spectrum, spectrumLog;
|
||||
int windowSize;
|
||||
double rate = ((WaveTrack *)track)->GetRate();
|
||||
spectrum = (((WaveTrack *) track)->GetDisplay() == WaveTrack::SpectrumDisplay) ||
|
||||
(((WaveTrack *) track)->GetDisplay() == WaveTrack::SpectralSelectionDisplay) ;
|
||||
spectrumLog=(((WaveTrack *) track)->GetDisplay() == WaveTrack::SpectrumLogDisplay) ||
|
||||
(((WaveTrack *) track)->GetDisplay() == WaveTrack::SpectralSelectionLogDisplay)
|
||||
;
|
||||
const double rate = track->GetRate();
|
||||
const bool spectrum = (track->GetDisplay() == WaveTrack::SpectrumDisplay) ||
|
||||
(track->GetDisplay() == WaveTrack::SpectralSelectionDisplay);
|
||||
const bool spectrumLog = (track->GetDisplay() == WaveTrack::SpectrumLogDisplay) ||
|
||||
(track->GetDisplay() == WaveTrack::SpectralSelectionLogDisplay);
|
||||
if(spectrum) {
|
||||
min = mTrackArtist->GetSpectrumMinFreq(0);
|
||||
if(min < 0)
|
||||
min = 0;
|
||||
max = mTrackArtist->GetSpectrumMaxFreq(8000);
|
||||
if(max > rate/2.)
|
||||
max = rate/2.;
|
||||
|
||||
// Always spectrogram, never pitch view, pass true
|
||||
windowSize = mTrackArtist->GetSpectrumWindowSize(true);
|
||||
binSize = rate / windowSize;
|
||||
minBins = wxMin(10, windowSize/2); //minimum 10 freq bins, unless there are less
|
||||
const SpectrogramSettings &settings = track->GetSpectrogramSettings();
|
||||
min = settings.GetMinFreq(rate);
|
||||
max = settings.GetMaxFreq(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) {
|
||||
min = mTrackArtist->GetSpectrumLogMinFreq(lrint(rate/1000.0));
|
||||
if(min < 1)
|
||||
min = 1;
|
||||
max = mTrackArtist->GetSpectrumLogMaxFreq(lrint(rate/2.));
|
||||
if(max > rate/2.)
|
||||
max = rate/2.;
|
||||
|
||||
// Always spectrogram, never pitch view, pass true
|
||||
windowSize = mTrackArtist->GetSpectrumWindowSize(true);
|
||||
binSize = rate / windowSize;
|
||||
minBins = wxMin(10, windowSize/2); //minimum 10 freq bins, unless there are less
|
||||
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
|
||||
}
|
||||
else
|
||||
track->GetDisplayBounds(&min, &max);
|
||||
@ -4743,8 +4724,8 @@ void TrackPanel::HandleVZoomButtonUp( wxMouseEvent & event )
|
||||
double xmax = 1-(mZoomStart - ypos) / (float)height;
|
||||
double lmin=log10(tmin), lmax=log10(tmax);
|
||||
double d=lmax-lmin;
|
||||
min=wxMax(1.0, pow(10, xmin*d+lmin));
|
||||
max=wxMin(rate/2.0, pow(10, xmax*d+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)
|
||||
@ -4798,11 +4779,11 @@ void TrackPanel::HandleVZoomButtonUp( wxMouseEvent & event )
|
||||
l = (c - min);
|
||||
if(c - 2*l <= 0) {
|
||||
min = 0.0;
|
||||
max = wxMin( rate/2., 2. * max);
|
||||
max = std::min( rate/2., 2. * max);
|
||||
}
|
||||
else {
|
||||
min = wxMax( 0.0, c - 2*l);
|
||||
max = wxMin( rate/2., c + 2*l);
|
||||
min = std::max( 0.0f, c - 2*l);
|
||||
max = std::min( float(rate)/2, c + 2*l);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4822,8 +4803,8 @@ void TrackPanel::HandleVZoomButtonUp( wxMouseEvent & event )
|
||||
double xmax = c + 1.;
|
||||
double lmin = log10(min), lmax = log10(max);
|
||||
double d = lmax-lmin;
|
||||
min = wxMax(1,pow(10, xmin*d+lmin));
|
||||
max = wxMin(rate/2., pow(10, xmax*d+lmin));
|
||||
min = std::max(1.0f,float(pow(10, xmin*d+lmin)));
|
||||
max = std::min(rate/2., pow(10, xmax*d+lmin));
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -4845,8 +4826,8 @@ void TrackPanel::HandleVZoomButtonUp( wxMouseEvent & event )
|
||||
float minRange = (min < -1) ? -2.0 : -1.0;
|
||||
float maxRange = (max > 1) ? 2.0 : 1.0;
|
||||
// and enforce vertical zoom limits.
|
||||
min = wxMin(maxRange - ZOOMLIMIT, wxMax(minRange, c - 2*l));
|
||||
max = wxMax(minRange + ZOOMLIMIT, wxMin(maxRange, c + 2*l));
|
||||
min = std::min(maxRange - ZOOMLIMIT, std::max(minRange, c - 2*l));
|
||||
max = std::max(minRange + ZOOMLIMIT, std::min(maxRange, c + 2*l));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4858,12 +4839,12 @@ void TrackPanel::HandleVZoomButtonUp( wxMouseEvent & event )
|
||||
if(spectrum) {
|
||||
c = 0.5*(min+max);
|
||||
// Enforce maximum vertical zoom
|
||||
l = wxMax( minBins * binSize, (c - min));
|
||||
l = std::max( minBins * binSize, (c - min));
|
||||
|
||||
p1 = (mZoomStart - ypos) / (float)height;
|
||||
c = (max * (1.0-p1) + min * p1);
|
||||
min = wxMax( 0.0, c - 0.5*l);
|
||||
max = wxMin( rate/2., min + l);
|
||||
min = std::max( 0.0, c - 0.5*l);
|
||||
max = std::min( float(rate)/2, min + l);
|
||||
}
|
||||
else {
|
||||
if(spectrumLog) {
|
||||
@ -4873,8 +4854,8 @@ void TrackPanel::HandleVZoomButtonUp( wxMouseEvent & event )
|
||||
double xmax = c + 0.25;
|
||||
double lmin = log10(min), lmax = log10(max);
|
||||
double d = lmax-lmin;
|
||||
min = wxMax(1,pow(10, xmin*d+lmin));
|
||||
max = wxMin(rate/2., pow(10, xmax*d+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)
|
||||
@ -4893,7 +4874,7 @@ void TrackPanel::HandleVZoomButtonUp( wxMouseEvent & event )
|
||||
else {
|
||||
c = 0.5*(min+max);
|
||||
// Enforce maximum vertical zoom
|
||||
l = wxMax( ZOOMLIMIT, (c - min));
|
||||
l = std::max( ZOOMLIMIT, (c - min));
|
||||
|
||||
p1 = (mZoomStart - ypos) / (float)height;
|
||||
c = (max * (1.0-p1) + min * p1);
|
||||
@ -4905,13 +4886,27 @@ void TrackPanel::HandleVZoomButtonUp( wxMouseEvent & event )
|
||||
}
|
||||
|
||||
if(spectrum) {
|
||||
mTrackArtist->SetSpectrumMaxFreq(max);
|
||||
mTrackArtist->SetSpectrumMinFreq(min);
|
||||
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);
|
||||
}
|
||||
mTrackArtist->InvalidateSpectrumCache(mTracks);
|
||||
}
|
||||
else if(spectrumLog) {
|
||||
mTrackArtist->SetSpectrumLogMaxFreq(max);
|
||||
mTrackArtist->SetSpectrumLogMinFreq(min);
|
||||
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);
|
||||
}
|
||||
mTrackArtist->InvalidateSpectrumCache(mTracks);
|
||||
}
|
||||
else {
|
||||
|
@ -337,9 +337,9 @@ protected:
|
||||
|
||||
#ifdef EXPERIMENTAL_SPECTRAL_EDITING
|
||||
public:
|
||||
void SnapCenterOnce (WaveTrack *pTrack, bool up);
|
||||
void SnapCenterOnce (const WaveTrack *pTrack, bool up);
|
||||
protected:
|
||||
void StartSnappingFreqSelection (WaveTrack *pTrack);
|
||||
void StartSnappingFreqSelection (const WaveTrack *pTrack);
|
||||
void MoveSnappingFreqSelection (int mouseYCoordinate,
|
||||
int trackTopEdge,
|
||||
int trackHeight, Track *pTrack);
|
||||
@ -494,9 +494,9 @@ protected:
|
||||
virtual wxRect FindTrackRect(Track * target, bool label);
|
||||
|
||||
virtual int GetVRulerWidth() const;
|
||||
virtual int GetVRulerOffset() const { return mTrackInfo.GetTrackInfoWidth(); };
|
||||
virtual int GetVRulerOffset() const { return mTrackInfo.GetTrackInfoWidth(); }
|
||||
|
||||
virtual int GetLabelWidth() const { return mTrackInfo.GetTrackInfoWidth() + GetVRulerWidth(); };
|
||||
virtual int GetLabelWidth() const { return mTrackInfo.GetTrackInfoWidth() + GetVRulerWidth(); }
|
||||
|
||||
// JKC Nov-2011: These four functions only used from within a dll such as mod-track-panel
|
||||
// They work around some messy problems with constructors.
|
||||
@ -693,16 +693,16 @@ protected:
|
||||
void HandleCenterFrequencyClick
|
||||
(bool shiftDown, Track *pTrack, double value);
|
||||
|
||||
double PositionToFrequency(bool maySnap,
|
||||
double PositionToFrequency(const WaveTrack *wt,
|
||||
bool maySnap,
|
||||
wxInt64 mouseYCoordinate,
|
||||
wxInt64 trackTopEdge,
|
||||
int trackHeight,
|
||||
double rate,
|
||||
bool logF) const;
|
||||
wxInt64 FrequencyToPosition(double frequency,
|
||||
wxInt64 FrequencyToPosition(const WaveTrack *wt,
|
||||
double frequency,
|
||||
wxInt64 trackTopEdge,
|
||||
int trackHeight,
|
||||
double rate,
|
||||
bool logF) const;
|
||||
#endif
|
||||
|
||||
|
@ -33,7 +33,7 @@
|
||||
#include "Resample.h"
|
||||
#include "Project.h"
|
||||
|
||||
#include "prefs/SpectrumPrefs.h"
|
||||
#include "prefs/SpectrogramSettings.h"
|
||||
|
||||
#include <wx/listimpl.cpp>
|
||||
WX_DEFINE_LIST(WaveClipList);
|
||||
@ -902,8 +902,8 @@ bool WaveClip::GetSpectrogram(WaveTrackCache &waveTrackCache,
|
||||
double t0, double pixelsPerSecond,
|
||||
bool autocorrelation)
|
||||
{
|
||||
const SpectrogramSettings &settings = SpectrogramSettings::defaults();
|
||||
|
||||
const WaveTrack *const track = waveTrackCache.GetTrack();
|
||||
const SpectrogramSettings &settings = track->GetSpectrogramSettings();
|
||||
const int &frequencyGain = settings.frequencyGain;
|
||||
const int &windowSize = settings.windowSize;
|
||||
const int &windowType = settings.windowType;
|
||||
|
@ -54,6 +54,7 @@ Track classes.
|
||||
#include "ondemand/ODManager.h"
|
||||
|
||||
#include "effects/TimeWarper.h"
|
||||
#include "prefs/SpectrumPrefs.h"
|
||||
|
||||
using std::max;
|
||||
|
||||
@ -74,6 +75,7 @@ WaveTrack *TrackFactory::NewWaveTrack(sampleFormat format, double rate)
|
||||
|
||||
WaveTrack::WaveTrack(DirManager *projDirManager, sampleFormat format, double rate):
|
||||
Track(projDirManager)
|
||||
, mpSpectrumSettings(0)
|
||||
{
|
||||
if (format == (sampleFormat)0)
|
||||
{
|
||||
@ -105,6 +107,9 @@ WaveTrack::WaveTrack(DirManager *projDirManager, sampleFormat format, double rat
|
||||
|
||||
WaveTrack::WaveTrack(WaveTrack &orig):
|
||||
Track(orig)
|
||||
, mpSpectrumSettings(orig.mpSpectrumSettings
|
||||
? new SpectrogramSettings(*orig.mpSpectrumSettings) : 0
|
||||
)
|
||||
{
|
||||
mDisplay = FindDefaultViewMode();
|
||||
mLastDisplay = -1;
|
||||
@ -139,9 +144,12 @@ void WaveTrack::Merge(const Track &orig)
|
||||
{
|
||||
if (orig.GetKind() == Wave)
|
||||
{
|
||||
mDisplay = ((WaveTrack &)orig).mDisplay;
|
||||
mGain = ((WaveTrack &)orig).mGain;
|
||||
mPan = ((WaveTrack &)orig).mPan;
|
||||
const WaveTrack &wt = static_cast<const WaveTrack&>(orig);
|
||||
mDisplay = wt.mDisplay;
|
||||
mGain = wt.mGain;
|
||||
mPan = wt.mPan;
|
||||
SetSpectrogramSettings(wt.mpSpectrumSettings
|
||||
? new SpectrogramSettings(*wt.mpSpectrumSettings) : 0);
|
||||
}
|
||||
Track::Merge(orig);
|
||||
}
|
||||
@ -159,6 +167,7 @@ WaveTrack::~WaveTrack()
|
||||
if (mDisplayLocations)
|
||||
delete [] mDisplayLocations;
|
||||
|
||||
delete mpSpectrumSettings;
|
||||
}
|
||||
|
||||
double WaveTrack::GetOffset() const
|
||||
@ -624,6 +633,38 @@ bool WaveTrack::ClearAndAddCutLine(double t0, double t1)
|
||||
return HandleClear(t0, t1, true, false);
|
||||
}
|
||||
|
||||
const SpectrogramSettings &WaveTrack::GetSpectrogramSettings() const
|
||||
{
|
||||
if (mpSpectrumSettings)
|
||||
return *mpSpectrumSettings;
|
||||
else
|
||||
return SpectrogramSettings::defaults();
|
||||
}
|
||||
|
||||
SpectrogramSettings &WaveTrack::GetSpectrogramSettings()
|
||||
{
|
||||
if (mpSpectrumSettings)
|
||||
return *mpSpectrumSettings;
|
||||
else
|
||||
return SpectrogramSettings::defaults();
|
||||
}
|
||||
|
||||
SpectrogramSettings &WaveTrack::GetIndependentSpectrogramSettings()
|
||||
{
|
||||
if (!mpSpectrumSettings)
|
||||
mpSpectrumSettings =
|
||||
new SpectrogramSettings(SpectrogramSettings::defaults());
|
||||
return *mpSpectrumSettings;
|
||||
}
|
||||
|
||||
void WaveTrack::SetSpectrogramSettings(SpectrogramSettings *pSettings)
|
||||
{
|
||||
if (mpSpectrumSettings != pSettings) {
|
||||
delete mpSpectrumSettings;
|
||||
mpSpectrumSettings = pSettings;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// ClearAndPaste() is a specialized version of HandleClear()
|
||||
// followed by Paste() and is used mostly by effects that
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <wx/longlong.h>
|
||||
#include <wx/thread.h>
|
||||
|
||||
class SpectrogramSettings;
|
||||
class TimeWarper;
|
||||
|
||||
//
|
||||
@ -145,6 +146,11 @@ class AUDACITY_DLL_API WaveTrack: public Track {
|
||||
sampleFormat GetSampleFormat() { return mFormat; }
|
||||
bool ConvertToSampleFormat(sampleFormat format);
|
||||
|
||||
const SpectrogramSettings &GetSpectrogramSettings() const;
|
||||
SpectrogramSettings &GetSpectrogramSettings();
|
||||
SpectrogramSettings &GetIndependentSpectrogramSettings();
|
||||
void SetSpectrogramSettings(SpectrogramSettings *pSettings);
|
||||
|
||||
//
|
||||
// High-level editing
|
||||
//
|
||||
@ -490,6 +496,8 @@ class AUDACITY_DLL_API WaveTrack: public Track {
|
||||
wxCriticalSection mAppendCriticalSection;
|
||||
double mLegacyProjectFileOffset;
|
||||
int mAutoSaveIdent;
|
||||
|
||||
SpectrogramSettings *mpSpectrumSettings;
|
||||
};
|
||||
|
||||
// This is meant to be a short-lived object, during whose lifetime,
|
||||
|
320
src/prefs/SpectrogramSettings.cpp
Normal file
320
src/prefs/SpectrogramSettings.cpp
Normal file
@ -0,0 +1,320 @@
|
||||
/**********************************************************************
|
||||
|
||||
Audacity: A Digital Audio Editor
|
||||
|
||||
SpectrogramSettings.cpp
|
||||
|
||||
Paul Licameli
|
||||
|
||||
*******************************************************************//**
|
||||
|
||||
\class SpectrogramSettings
|
||||
\brief Spectrogram settings, either for one track or as defaults.
|
||||
|
||||
*//*******************************************************************/
|
||||
|
||||
#include "../Audacity.h"
|
||||
#include "SpectrogramSettings.h"
|
||||
#include "../FFT.h"
|
||||
#include "../Prefs.h"
|
||||
#include "../RealFFTf.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
SpectrogramSettings::SpectrogramSettings()
|
||||
: hFFT(0)
|
||||
, window(0)
|
||||
{
|
||||
UpdatePrefs();
|
||||
}
|
||||
|
||||
SpectrogramSettings::SpectrogramSettings(const SpectrogramSettings &other)
|
||||
: minFreq(other.minFreq)
|
||||
, maxFreq(other.maxFreq)
|
||||
, logMinFreq(other.logMinFreq)
|
||||
, logMaxFreq(other.logMaxFreq)
|
||||
, range(other.range)
|
||||
, gain(other.gain)
|
||||
, frequencyGain(other.frequencyGain)
|
||||
, windowType(other.windowType)
|
||||
, windowSize(other.windowSize)
|
||||
#ifdef EXPERIMENTAL_ZERO_PADDED_SPECTROGRAMS
|
||||
, zeroPaddingFactor(other.zeroPaddingFactor)
|
||||
#endif
|
||||
, isGrayscale(other.isGrayscale)
|
||||
#ifdef EXPERIMENTAL_FFT_Y_GRID
|
||||
, fftYGrid(other.fftYGrid)
|
||||
#endif
|
||||
#ifdef EXPERIMENTAL_FIND_NOTES
|
||||
, fftFindNotes(other.fftFindNotes)
|
||||
, findNotesMinA(other.findNotesMinA)
|
||||
, numberOfMaxima(other.numberOfMaxima)
|
||||
, findNotesQuantize(other.findNotesQuantize)
|
||||
#endif
|
||||
|
||||
// Do not copy these!
|
||||
, hFFT(0)
|
||||
, window(0)
|
||||
{
|
||||
}
|
||||
|
||||
SpectrogramSettings &SpectrogramSettings::operator= (const SpectrogramSettings &other)
|
||||
{
|
||||
if (this != &other) {
|
||||
minFreq = other.minFreq;
|
||||
maxFreq = other.maxFreq;
|
||||
logMinFreq = other.logMinFreq;
|
||||
logMaxFreq = other.logMaxFreq;
|
||||
range = other.range;
|
||||
gain = other.gain;
|
||||
frequencyGain = other.frequencyGain;
|
||||
windowType = other.windowType;
|
||||
windowSize = other.windowSize;
|
||||
#ifdef EXPERIMENTAL_ZERO_PADDED_SPECTROGRAMS
|
||||
zeroPaddingFactor = other.zeroPaddingFactor;
|
||||
#endif
|
||||
isGrayscale = other.isGrayscale;
|
||||
#ifdef EXPERIMENTAL_FFT_Y_GRID
|
||||
fftYGrid = other.fftYGrid;
|
||||
#endif
|
||||
#ifdef EXPERIMENTAL_FIND_NOTES
|
||||
fftFindNotes = other.fftFindNotes;
|
||||
findNotesMinA = other.findNotesMinA;
|
||||
numberOfMaxima = other.numberOfMaxima;
|
||||
findNotesQuantize = other.findNotesQuantize;
|
||||
#endif
|
||||
|
||||
// Do not copy these!
|
||||
hFFT = 0;
|
||||
window = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
SpectrogramSettings& SpectrogramSettings::defaults()
|
||||
{
|
||||
static SpectrogramSettings instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void SpectrogramSettings::UpdatePrefs()
|
||||
{
|
||||
bool destroy = false;
|
||||
|
||||
minFreq = gPrefs->Read(wxT("/Spectrum/MinFreq"), -1L);
|
||||
maxFreq = gPrefs->Read(wxT("/Spectrum/MaxFreq"), 8000L);
|
||||
|
||||
// These preferences are not written anywhere in the program as of now,
|
||||
// but I keep this legacy here. Who knows, someone might edit prefs files
|
||||
// directly. PRL
|
||||
logMaxFreq = gPrefs->Read(wxT("/SpectrumLog/MaxFreq"), -1);
|
||||
if (logMaxFreq < 0)
|
||||
logMaxFreq = maxFreq;
|
||||
logMinFreq = gPrefs->Read(wxT("/SpectrumLog/MinFreq"), -1);
|
||||
if (logMinFreq < 0)
|
||||
logMinFreq = minFreq;
|
||||
if (logMinFreq < 1)
|
||||
logMinFreq = 1;
|
||||
|
||||
range = gPrefs->Read(wxT("/Spectrum/Range"), 80L);
|
||||
gain = gPrefs->Read(wxT("/Spectrum/Gain"), 20L);
|
||||
frequencyGain = gPrefs->Read(wxT("/Spectrum/FrequencyGain"), 0L);
|
||||
|
||||
const int newWindowSize = gPrefs->Read(wxT("/Spectrum/FFTSize"), 256);
|
||||
if (newWindowSize != windowSize) {
|
||||
destroy = true;
|
||||
windowSize = newWindowSize;
|
||||
}
|
||||
|
||||
#ifdef EXPERIMENTAL_ZERO_PADDED_SPECTROGRAMS
|
||||
const int newZeroPaddingFactor = gPrefs->Read(wxT("/Spectrum/ZeroPaddingFactor"), 1);
|
||||
if (newZeroPaddingFactor != zeroPaddingFactor) {
|
||||
destroy = true;
|
||||
zeroPaddingFactor = newZeroPaddingFactor;
|
||||
}
|
||||
#endif
|
||||
|
||||
int newWindowType;
|
||||
gPrefs->Read(wxT("/Spectrum/WindowType"), &newWindowType, 3);
|
||||
if (newWindowType != windowType) {
|
||||
destroy = true;
|
||||
windowType = newWindowType;
|
||||
}
|
||||
|
||||
isGrayscale = (gPrefs->Read(wxT("/Spectrum/Grayscale"), 0L) != 0);
|
||||
|
||||
#ifdef EXPERIMENTAL_FFT_Y_GRID
|
||||
fftYGrid = (gPrefs->Read(wxT("/Spectrum/FFTYGrid"), 0L) != 0);
|
||||
#endif //EXPERIMENTAL_FFT_Y_GRID
|
||||
|
||||
#ifdef EXPERIMENTAL_FIND_NOTES
|
||||
fftFindNotes = (gPrefs->Read(wxT("/Spectrum/FFTFindNotes"), 0L) != 0);
|
||||
findNotesMinA = gPrefs->Read(wxT("/Spectrum/FindNotesMinA"), -30.0);
|
||||
numberOfMaxima = gPrefs->Read(wxT("/Spectrum/FindNotesN"), 5L);
|
||||
findNotesQuantize = (gPrefs->Read(wxT("/Spectrum/FindNotesQuantize"), 0L) != 0);
|
||||
#endif //EXPERIMENTAL_FIND_NOTES
|
||||
|
||||
if (destroy)
|
||||
DestroyWindows();
|
||||
}
|
||||
|
||||
SpectrogramSettings::~SpectrogramSettings()
|
||||
{
|
||||
DestroyWindows();
|
||||
}
|
||||
|
||||
void SpectrogramSettings::DestroyWindows()
|
||||
{
|
||||
#ifdef EXPERIMENTAL_USE_REALFFTF
|
||||
if (hFFT != NULL) {
|
||||
EndFFT(hFFT);
|
||||
hFFT = NULL;
|
||||
}
|
||||
if (window != NULL) {
|
||||
delete[] window;
|
||||
window = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
enum { WINDOW, TWINDOW, DWINDOW };
|
||||
void RecreateWindow(
|
||||
float *&window, int which, int fftLen,
|
||||
int padding, int windowType, int windowSize, double &scale)
|
||||
{
|
||||
if (window != NULL)
|
||||
delete[] window;
|
||||
// Create the requested window function
|
||||
window = new float[fftLen];
|
||||
int ii;
|
||||
|
||||
wxASSERT(windowSize % 2 == 0);
|
||||
const int endOfWindow = padding + windowSize;
|
||||
// Left and right padding
|
||||
for (ii = 0; ii < padding; ++ii) {
|
||||
window[ii] = 0.0;
|
||||
window[fftLen - ii - 1] = 0.0;
|
||||
}
|
||||
// Default rectangular window in the middle
|
||||
for (; ii < endOfWindow; ++ii)
|
||||
window[ii] = 1.0;
|
||||
// Overwrite middle as needed
|
||||
switch (which) {
|
||||
case WINDOW:
|
||||
WindowFunc(windowType, windowSize, window + padding);
|
||||
// NewWindowFunc(windowType, windowSize, extra, window + padding);
|
||||
break;
|
||||
case TWINDOW:
|
||||
wxASSERT(false);
|
||||
#if 0
|
||||
// Future, reassignment
|
||||
NewWindowFunc(windowType, windowSize, extra, window + padding);
|
||||
for (int ii = padding, multiplier = -windowSize / 2; ii < endOfWindow; ++ii, ++multiplier)
|
||||
window[ii] *= multiplier;
|
||||
break;
|
||||
#endif
|
||||
case DWINDOW:
|
||||
wxASSERT(false);
|
||||
#if 0
|
||||
// Future, reassignment
|
||||
DerivativeOfWindowFunc(windowType, windowSize, extra, window + padding);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
wxASSERT(false);
|
||||
}
|
||||
// Scale the window function to give 0dB spectrum for 0dB sine tone
|
||||
if (which == WINDOW) {
|
||||
scale = 0.0;
|
||||
for (ii = padding; ii < endOfWindow; ++ii)
|
||||
scale += window[ii];
|
||||
if (scale > 0)
|
||||
scale = 2.0 / scale;
|
||||
}
|
||||
for (ii = padding; ii < endOfWindow; ++ii)
|
||||
window[ii] *= scale;
|
||||
}
|
||||
}
|
||||
|
||||
void SpectrogramSettings::CacheWindows() const
|
||||
{
|
||||
#ifdef EXPERIMENTAL_USE_REALFFTF
|
||||
if (hFFT == NULL || window == NULL) {
|
||||
|
||||
double scale;
|
||||
const int fftLen = windowSize * zeroPaddingFactor;
|
||||
const int padding = (windowSize * (zeroPaddingFactor - 1)) / 2;
|
||||
|
||||
if (hFFT != NULL)
|
||||
EndFFT(hFFT);
|
||||
hFFT = InitializeFFT(fftLen);
|
||||
RecreateWindow(window, WINDOW, fftLen, padding, windowType, windowSize, scale);
|
||||
}
|
||||
#endif // EXPERIMENTAL_USE_REALFFTF
|
||||
}
|
||||
|
||||
int SpectrogramSettings::GetMinFreq(double rate) const
|
||||
{
|
||||
const int top = lrint(rate / 2.);
|
||||
return std::max(0, std::min(top, minFreq));
|
||||
}
|
||||
|
||||
int SpectrogramSettings::GetMaxFreq(double rate) const
|
||||
{
|
||||
const int top = lrint(rate / 2.);
|
||||
if (maxFreq < 0)
|
||||
return top;
|
||||
else
|
||||
return std::max(0, std::min(top, maxFreq));
|
||||
}
|
||||
|
||||
int SpectrogramSettings::GetLogMinFreq(double rate) const
|
||||
{
|
||||
const int top = lrint(rate / 2.);
|
||||
if (logMinFreq < 0)
|
||||
return top / 1000.0;
|
||||
else
|
||||
return std::max(1, std::min(top, logMinFreq));
|
||||
}
|
||||
|
||||
int SpectrogramSettings::GetLogMaxFreq(double rate) const
|
||||
{
|
||||
const int top = lrint(rate / 2.);
|
||||
if (logMaxFreq < 0)
|
||||
return top;
|
||||
else
|
||||
return std::max(1, std::min(top, logMaxFreq));
|
||||
}
|
||||
|
||||
void SpectrogramSettings::SetMinFreq(int freq)
|
||||
{
|
||||
minFreq = freq;
|
||||
}
|
||||
|
||||
void SpectrogramSettings::SetMaxFreq(int freq)
|
||||
{
|
||||
maxFreq = freq;
|
||||
}
|
||||
|
||||
void SpectrogramSettings::SetLogMinFreq(int freq)
|
||||
{
|
||||
logMinFreq = freq;
|
||||
}
|
||||
|
||||
void SpectrogramSettings::SetLogMaxFreq(int freq)
|
||||
{
|
||||
logMaxFreq = freq;
|
||||
}
|
||||
|
||||
int SpectrogramSettings::GetFFTLength(bool autocorrelation) const
|
||||
{
|
||||
return windowSize
|
||||
#ifdef EXPERIMENTAL_ZERO_PADDED_SPECTROGRAMS
|
||||
* (!autocorrelation ? zeroPaddingFactor : 1);
|
||||
#endif
|
||||
;
|
||||
}
|
81
src/prefs/SpectrogramSettings.h
Normal file
81
src/prefs/SpectrogramSettings.h
Normal file
@ -0,0 +1,81 @@
|
||||
/**********************************************************************
|
||||
|
||||
Audacity: A Digital Audio Editor
|
||||
|
||||
SpectrogramSettings.h
|
||||
|
||||
Paul Licameli
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef __AUDACITY_SPECTROGRAM_SETTINGS__
|
||||
#define __AUDACITY_SPECTROGRAM_SETTINGS__
|
||||
|
||||
#include "../Experimental.h"
|
||||
|
||||
struct FFTParam;
|
||||
|
||||
class SpectrogramSettings
|
||||
{
|
||||
public:
|
||||
static SpectrogramSettings &defaults();
|
||||
SpectrogramSettings();
|
||||
SpectrogramSettings(const SpectrogramSettings &other);
|
||||
SpectrogramSettings& operator= (const SpectrogramSettings &other);
|
||||
~SpectrogramSettings();
|
||||
|
||||
void UpdatePrefs();
|
||||
void DestroyWindows();
|
||||
void CacheWindows() const;
|
||||
|
||||
private:
|
||||
int minFreq;
|
||||
int maxFreq;
|
||||
int logMinFreq;
|
||||
int logMaxFreq;
|
||||
public:
|
||||
int GetMinFreq(double rate) const;
|
||||
int GetMaxFreq(double rate) const;
|
||||
int GetLogMinFreq(double rate) const;
|
||||
int GetLogMaxFreq(double rate) const;
|
||||
|
||||
void SetMinFreq(int freq);
|
||||
void SetMaxFreq(int freq);
|
||||
void SetLogMinFreq(int freq);
|
||||
void SetLogMaxFreq(int freq);
|
||||
|
||||
public:
|
||||
int range;
|
||||
int gain;
|
||||
int frequencyGain;
|
||||
|
||||
int windowType;
|
||||
int windowSize;
|
||||
#ifdef EXPERIMENTAL_ZERO_PADDED_SPECTROGRAMS
|
||||
int zeroPaddingFactor;
|
||||
#endif
|
||||
|
||||
int GetFFTLength(bool autocorrelation) const; // window size (times zero padding, if STFT)
|
||||
|
||||
bool isGrayscale;
|
||||
|
||||
#ifdef EXPERIMENTAL_FFT_Y_GRID
|
||||
bool fftYGrid;
|
||||
#endif //EXPERIMENTAL_FFT_Y_GRID
|
||||
|
||||
#ifdef EXPERIMENTAL_FIND_NOTES
|
||||
bool fftFindNotes;
|
||||
bool findNotesMinA;
|
||||
bool numberOfMaxima;
|
||||
bool findNotesQuantize;
|
||||
#endif //EXPERIMENTAL_FIND_NOTES
|
||||
|
||||
// Following fields are derived from preferences.
|
||||
|
||||
#ifdef EXPERIMENTAL_USE_REALFFTF
|
||||
// Variables used for computing the spectrum
|
||||
mutable FFTParam *hFFT;
|
||||
mutable float *window;
|
||||
#endif
|
||||
};
|
||||
#endif
|
@ -346,175 +346,3 @@ PrefsPanel *SpectrumPrefsFactory::Create(wxWindow *parent)
|
||||
{
|
||||
return new SpectrumPrefs(parent);
|
||||
}
|
||||
|
||||
SpectrogramSettings::SpectrogramSettings()
|
||||
: hFFT(0)
|
||||
, window(0)
|
||||
{
|
||||
UpdatePrefs();
|
||||
}
|
||||
|
||||
SpectrogramSettings& SpectrogramSettings::defaults()
|
||||
{
|
||||
static SpectrogramSettings instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void SpectrogramSettings::UpdatePrefs()
|
||||
{
|
||||
bool destroy = false;
|
||||
|
||||
minFreq = gPrefs->Read(wxT("/Spectrum/MinFreq"), -1L);
|
||||
maxFreq = gPrefs->Read(wxT("/Spectrum/MaxFreq"), 8000L);
|
||||
|
||||
// These preferences are not written anywhere in the program as of now,
|
||||
// but I keep this legacy here. Who knows, someone might edit prefs files
|
||||
// directly. PRL
|
||||
logMaxFreq = gPrefs->Read(wxT("/SpectrumLog/MaxFreq"), -1);
|
||||
if (logMaxFreq < 0)
|
||||
logMaxFreq = maxFreq;
|
||||
logMinFreq = gPrefs->Read(wxT("/SpectrumLog/MinFreq"), -1);
|
||||
if (logMinFreq < 0)
|
||||
logMinFreq = minFreq;
|
||||
if (logMinFreq < 1)
|
||||
logMinFreq = 1;
|
||||
|
||||
range = gPrefs->Read(wxT("/Spectrum/Range"), 80L);
|
||||
gain = gPrefs->Read(wxT("/Spectrum/Gain"), 20L);
|
||||
frequencyGain = gPrefs->Read(wxT("/Spectrum/FrequencyGain"), 0L);
|
||||
|
||||
const int newWindowSize = gPrefs->Read(wxT("/Spectrum/FFTSize"), 256);
|
||||
if (newWindowSize != windowSize) {
|
||||
destroy = true;
|
||||
windowSize = newWindowSize;
|
||||
}
|
||||
|
||||
#ifdef EXPERIMENTAL_ZERO_PADDED_SPECTROGRAMS
|
||||
const int newZeroPaddingFactor = gPrefs->Read(wxT("/Spectrum/ZeroPaddingFactor"), 1);
|
||||
if (newZeroPaddingFactor != zeroPaddingFactor) {
|
||||
destroy = true;
|
||||
zeroPaddingFactor = newZeroPaddingFactor;
|
||||
}
|
||||
#endif
|
||||
|
||||
int newWindowType;
|
||||
gPrefs->Read(wxT("/Spectrum/WindowType"), &newWindowType, 3);
|
||||
if (newWindowType != windowType) {
|
||||
destroy = true;
|
||||
windowType = newWindowType;
|
||||
}
|
||||
|
||||
isGrayscale = (gPrefs->Read(wxT("/Spectrum/Grayscale"), 0L) != 0);
|
||||
|
||||
#ifdef EXPERIMENTAL_FFT_Y_GRID
|
||||
fftYGrid = (gPrefs->Read(wxT("/Spectrum/FFTYGrid"), 0L) != 0);
|
||||
#endif //EXPERIMENTAL_FFT_Y_GRID
|
||||
|
||||
#ifdef EXPERIMENTAL_FIND_NOTES
|
||||
fftFindNotes = (gPrefs->Read(wxT("/Spectrum/FFTFindNotes"), 0L) != 0);
|
||||
findNotesMinA = gPrefs->Read(wxT("/Spectrum/FindNotesMinA"), -30.0);
|
||||
numberOfMaxima = gPrefs->Read(wxT("/Spectrum/FindNotesN"), 5L);
|
||||
findNotesQuantize = (gPrefs->Read(wxT("/Spectrum/FindNotesQuantize"), 0L) != 0);
|
||||
#endif //EXPERIMENTAL_FIND_NOTES
|
||||
|
||||
if (destroy)
|
||||
DestroyWindows();
|
||||
}
|
||||
|
||||
SpectrogramSettings::~SpectrogramSettings()
|
||||
{
|
||||
DestroyWindows();
|
||||
}
|
||||
|
||||
void SpectrogramSettings::DestroyWindows()
|
||||
{
|
||||
#ifdef EXPERIMENTAL_USE_REALFFTF
|
||||
if (hFFT != NULL) {
|
||||
EndFFT(hFFT);
|
||||
hFFT = NULL;
|
||||
}
|
||||
if (window != NULL) {
|
||||
delete[] window;
|
||||
window = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
enum { WINDOW, TWINDOW, DWINDOW };
|
||||
void RecreateWindow(
|
||||
float *&window, int which, int fftLen,
|
||||
int padding, int windowType, int windowSize, double &scale)
|
||||
{
|
||||
if (window != NULL)
|
||||
delete[] window;
|
||||
// Create the requested window function
|
||||
window = new float[fftLen];
|
||||
int ii;
|
||||
|
||||
wxASSERT(windowSize % 2 == 0);
|
||||
const int endOfWindow = padding + windowSize;
|
||||
// Left and right padding
|
||||
for (ii = 0; ii < padding; ++ii) {
|
||||
window[ii] = 0.0;
|
||||
window[fftLen - ii - 1] = 0.0;
|
||||
}
|
||||
// Default rectangular window in the middle
|
||||
for (; ii < endOfWindow; ++ii)
|
||||
window[ii] = 1.0;
|
||||
// Overwrite middle as needed
|
||||
switch (which) {
|
||||
case WINDOW:
|
||||
WindowFunc(windowType, windowSize, window + padding);
|
||||
// NewWindowFunc(windowType, windowSize, extra, window + padding);
|
||||
break;
|
||||
case TWINDOW:
|
||||
wxASSERT(false);
|
||||
#if 0
|
||||
// Future, reassignment
|
||||
NewWindowFunc(windowType, windowSize, extra, window + padding);
|
||||
for (int ii = padding, multiplier = -windowSize / 2; ii < endOfWindow; ++ii, ++multiplier)
|
||||
window[ii] *= multiplier;
|
||||
break;
|
||||
#endif
|
||||
case DWINDOW:
|
||||
wxASSERT(false);
|
||||
#if 0
|
||||
// Future, reassignment
|
||||
DerivativeOfWindowFunc(windowType, windowSize, extra, window + padding);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
wxASSERT(false);
|
||||
}
|
||||
// Scale the window function to give 0dB spectrum for 0dB sine tone
|
||||
if (which == WINDOW) {
|
||||
scale = 0.0;
|
||||
for (ii = padding; ii < endOfWindow; ++ii)
|
||||
scale += window[ii];
|
||||
if (scale > 0)
|
||||
scale = 2.0 / scale;
|
||||
}
|
||||
for (ii = padding; ii < endOfWindow; ++ii)
|
||||
window[ii] *= scale;
|
||||
}
|
||||
}
|
||||
|
||||
void SpectrogramSettings::CacheWindows() const
|
||||
{
|
||||
#ifdef EXPERIMENTAL_USE_REALFFTF
|
||||
if (hFFT == NULL || window == NULL) {
|
||||
|
||||
double scale;
|
||||
const int fftLen = windowSize * zeroPaddingFactor;
|
||||
const int padding = (windowSize * (zeroPaddingFactor - 1)) / 2;
|
||||
|
||||
if (hFFT != NULL)
|
||||
EndFFT(hFFT);
|
||||
hFFT = InitializeFFT(fftLen);
|
||||
RecreateWindow(window, WINDOW, fftLen, padding, windowType, windowSize, scale);
|
||||
}
|
||||
#endif // EXPERIMENTAL_USE_REALFFTF
|
||||
}
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "../Experimental.h"
|
||||
|
||||
#include "PrefsPanel.h"
|
||||
#include "SpectrogramSettings.h"
|
||||
|
||||
class wxTextCtrl;
|
||||
struct FFTParam;
|
||||
@ -74,56 +75,6 @@ class SpectrumPrefs:public PrefsPanel
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
class SpectrogramSettings
|
||||
{
|
||||
public:
|
||||
static SpectrogramSettings &defaults();
|
||||
SpectrogramSettings();
|
||||
~SpectrogramSettings();
|
||||
|
||||
void UpdatePrefs();
|
||||
void DestroyWindows();
|
||||
void CacheWindows() const;
|
||||
|
||||
int minFreq;
|
||||
int maxFreq;
|
||||
|
||||
int logMinFreq;
|
||||
int logMaxFreq;
|
||||
|
||||
int range;
|
||||
int gain;
|
||||
int frequencyGain;
|
||||
|
||||
int windowType;
|
||||
int windowSize;
|
||||
#ifdef EXPERIMENTAL_ZERO_PADDED_SPECTROGRAMS
|
||||
int zeroPaddingFactor;
|
||||
#endif
|
||||
|
||||
bool isGrayscale;
|
||||
|
||||
#ifdef EXPERIMENTAL_FFT_Y_GRID
|
||||
bool fftYGrid;
|
||||
#endif //EXPERIMENTAL_FFT_Y_GRID
|
||||
|
||||
#ifdef EXPERIMENTAL_FIND_NOTES
|
||||
bool fftFindNotes;
|
||||
bool findNotesMinA;
|
||||
bool numberOfMaxima;
|
||||
bool findNotesQuantize;
|
||||
#endif //EXPERIMENTAL_FIND_NOTES
|
||||
|
||||
// Following fields are derived from preferences.
|
||||
|
||||
#ifdef EXPERIMENTAL_USE_REALFFTF
|
||||
// Variables used for computing the spectrum
|
||||
mutable FFTParam *hFFT;
|
||||
mutable float *window;
|
||||
#endif
|
||||
};
|
||||
|
||||
class SpectrumPrefsFactory : public PrefsPanelFactory
|
||||
{
|
||||
public:
|
||||
|
@ -286,6 +286,7 @@
|
||||
<ClCompile Include="..\..\..\src\PlatformCompatibility.cpp" />
|
||||
<ClCompile Include="..\..\..\src\PluginManager.cpp" />
|
||||
<ClCompile Include="..\..\..\src\Prefs.cpp" />
|
||||
<ClCompile Include="..\..\..\src\prefs\SpectrogramSettings.cpp" />
|
||||
<ClCompile Include="..\..\..\src\Printing.cpp" />
|
||||
<ClCompile Include="..\..\..\src\Profiler.cpp" />
|
||||
<ClCompile Include="..\..\..\src\Project.cpp" />
|
||||
@ -532,6 +533,7 @@
|
||||
<ClInclude Include="..\..\..\src\import\MultiFormatReader.h" />
|
||||
<ClInclude Include="..\..\..\src\import\SpecPowerMeter.h" />
|
||||
<ClInclude Include="..\..\..\src\ModuleManager.h" />
|
||||
<ClInclude Include="..\..\..\src\prefs\SpectrogramSettings.h" />
|
||||
<ClInclude Include="..\..\..\src\RevisionIdent.h" />
|
||||
<ClInclude Include="..\..\..\src\SelectedRegion.h" />
|
||||
<ClInclude Include="..\..\..\src\SseMathFuncs.h" />
|
||||
|
@ -840,6 +840,9 @@
|
||||
<ClCompile Include="..\..\..\src\ViewInfo.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\src\prefs\SpectrogramSettings.cpp">
|
||||
<Filter>src/prefs</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\src\AboutDialog.h">
|
||||
@ -1679,6 +1682,9 @@
|
||||
<ClInclude Include="..\..\..\src\AudacityHeaders.h">
|
||||
<Filter>src</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\src\prefs\SpectrogramSettings.h">
|
||||
<Filter>src/prefs</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="..\..\audacity.ico">
|
||||
|
Loading…
x
Reference in New Issue
Block a user