diff --git a/Makefile.in b/Makefile.in index 41edc3c418ac7c90e737f1b39a6d239978bc6836..eda9edbcb9b273b50b8180f9d30dcb7972369aab 100644 --- a/Makefile.in +++ b/Makefile.in @@ -90,6 +90,22 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = . +<<<<<<< HEAD +======= +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/configure $(am__configure_deps) $(dist_doc_DATA) \ + $(dist_pkgdata_DATA) $(nobase_dist_pkgdata_DATA) ABOUT-NLS \ + autotools/ar-lib autotools/compile autotools/config.guess \ + autotools/config.rpath autotools/config.sub autotools/depcomp \ + autotools/install-sh autotools/missing autotools/ltmain.sh \ + $(top_srcdir)/autotools/ar-lib \ + $(top_srcdir)/autotools/config.guess \ + $(top_srcdir)/autotools/config.rpath \ + $(top_srcdir)/autotools/config.sub \ + $(top_srcdir)/autotools/install-sh \ + $(top_srcdir)/autotools/ltmain.sh \ + $(top_srcdir)/autotools/missing +>>>>>>> upstream/master ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_c99_func_lrint.m4 \ $(top_srcdir)/m4/ac_c99_func_lrintf.m4 \ @@ -902,16 +918,22 @@ dist-xz: distdir $(am__post_remove_distdir) dist-tarZ: distdir +<<<<<<< HEAD @echo WARNING: "Support for distribution archives compressed with" \ "legacy program 'compress' is deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 +======= +>>>>>>> upstream/master tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir +<<<<<<< HEAD @echo WARNING: "Support for shar distribution archives is" \ "deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 +======= +>>>>>>> upstream/master shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__post_remove_distdir) @@ -952,11 +974,18 @@ distcheck: dist dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ +<<<<<<< HEAD && $(am__cd) $(distdir)/_build/sub \ && ../../configure \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ --srcdir=../.. --prefix="$$dc_install_base" \ +======= + && $(am__cd) $(distdir)/_build \ + && ../configure --srcdir=.. --prefix="$$dc_install_base" \ + $(AM_DISTCHECK_CONFIGURE_FLAGS) \ + $(DISTCHECK_CONFIGURE_FLAGS) \ +>>>>>>> upstream/master && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ diff --git a/images/Cursors.h b/images/Cursors.h index 83da26ff38cfd37881ef96cf05793e6bddbb7278..cb7d51f8338ca4eac0616f26dee6aaeb84ed86a9 100644 --- a/images/Cursors.h +++ b/images/Cursors.h @@ -56,3 +56,5 @@ #endif #endif + +wxCursor * MakeCursor(int WXUNUSED(CursorId), const char * pXpm[36], int HotX, int HotY); diff --git a/mac/Audacity.xcodeproj/project.pbxproj b/mac/Audacity.xcodeproj/project.pbxproj index e5d651dda01de65816d2eec00c35d84090c6ecca..9957af97d7cc1dac581cb43ff5c01d444f6266d2 100644 --- a/mac/Audacity.xcodeproj/project.pbxproj +++ b/mac/Audacity.xcodeproj/project.pbxproj @@ -842,6 +842,7 @@ 288A544B1346D1BA0050D774 /* chanmap.c in Sources */ = {isa = PBXBuildFile; fileRef = 288A54481346D1BA0050D774 /* chanmap.c */; }; 288A544C1346D1BA0050D774 /* chanmap.h in Headers */ = {isa = PBXBuildFile; fileRef = 288A54491346D1BA0050D774 /* chanmap.h */; }; 288A544D1346D1BA0050D774 /* id3.c in Sources */ = {isa = PBXBuildFile; fileRef = 288A544A1346D1BA0050D774 /* id3.c */; }; + 2890498E1B6716B40038A543 /* SpectrogramSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2890498C1B6716B40038A543 /* SpectrogramSettings.cpp */; }; 2891B2870C531D2C0044FBE3 /* FindClipping.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2891B2850C531D2C0044FBE3 /* FindClipping.cpp */; }; 2892CE24131AFAE200E1E17D /* LICENSE.txt in Install miscellany */ = {isa = PBXBuildFile; fileRef = 288F0977131A3EE00008E860 /* LICENSE.txt */; }; 2892CE25131AFAEF00E1E17D /* README.txt in Install miscellany */ = {isa = PBXBuildFile; fileRef = 288F097A131A3F130008E860 /* README.txt */; }; @@ -2072,6 +2073,7 @@ 280A8B4619F4403B0091DE70 /* ModuleManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ModuleManager.h; sourceTree = "<group>"; }; 280A8B4819F440880091DE70 /* EffectRack.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EffectRack.cpp; sourceTree = "<group>"; }; 280A8B4919F440880091DE70 /* EffectRack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EffectRack.h; sourceTree = "<group>"; }; + 280F5C8B1B676699003022C5 /* NumberScale.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NumberScale.h; sourceTree = "<group>"; }; 28105D9B0AD09FB200BB4269 /* portmixer.h */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 3; lastKnownFileType = sourcecode.c.h; path = portmixer.h; sourceTree = "<group>"; tabWidth = 3; }; 28105DA00AD09FC500BB4269 /* px_mac_coreaudio.c */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 3; lastKnownFileType = sourcecode.c.c; path = px_mac_coreaudio.c; sourceTree = "<group>"; tabWidth = 3; }; 28105DA10AD09FC500BB4269 /* px_mixer.c */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 3; lastKnownFileType = sourcecode.c.c; path = px_mixer.c; sourceTree = "<group>"; tabWidth = 3; }; @@ -2550,6 +2552,8 @@ 288A544A1346D1BA0050D774 /* id3.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; path = id3.c; sourceTree = "<group>"; }; 288F0977131A3EE00008E860 /* LICENSE.txt */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; name = LICENSE.txt; path = ../LICENSE.txt; sourceTree = "<group>"; }; 288F097A131A3F130008E860 /* README.txt */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; name = README.txt; path = ../README.txt; sourceTree = "<group>"; }; + 2890498C1B6716B40038A543 /* SpectrogramSettings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SpectrogramSettings.cpp; sourceTree = "<group>"; }; + 2890498D1B6716B40038A543 /* SpectrogramSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpectrogramSettings.h; sourceTree = "<group>"; }; 2891B2850C531D2C0044FBE3 /* FindClipping.cpp */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 3; lastKnownFileType = sourcecode.cpp.cpp; path = FindClipping.cpp; sourceTree = "<group>"; tabWidth = 3; }; 2891B2860C531D2C0044FBE3 /* FindClipping.h */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 3; lastKnownFileType = sourcecode.c.h; path = FindClipping.h; sourceTree = "<group>"; tabWidth = 3; }; 28948425101DF8FC005B0713 /* EffectsPrefs.cpp */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 3; lastKnownFileType = sourcecode.cpp.cpp; path = EffectsPrefs.cpp; sourceTree = "<group>"; tabWidth = 3; }; @@ -3880,6 +3884,7 @@ 280A8B4619F4403B0091DE70 /* ModuleManager.h */, 1790B0AF09883BFD008A330A /* NoteTrack.cpp */, 1790B0B009883BFD008A330A /* NoteTrack.h */, + 280F5C8B1B676699003022C5 /* NumberScale.h */, EDF3B7AF1588C0D50032D35F /* Paulstretch.cpp */, EDF3B7AE1588C0D50032D35F /* Paulstretch.h */, 1790B0B109883BFD008A330A /* PitchName.cpp */, @@ -4226,6 +4231,8 @@ 1790B0CA09883BFD008A330A /* SpectrumPrefs.cpp */, 1790B0CB09883BFD008A330A /* SpectrumPrefs.h */, 28456AC00A2C180E00C23C1E /* ThemePrefs.cpp */, + 2890498C1B6716B40038A543 /* SpectrogramSettings.cpp */, + 2890498D1B6716B40038A543 /* SpectrogramSettings.h */, 28456AC10A2C180E00C23C1E /* ThemePrefs.h */, 284B27E00FC66CCD005EAC96 /* TracksPrefs.cpp */, 284B27E10FC66CCD005EAC96 /* TracksPrefs.h */, @@ -7528,6 +7535,8 @@ 28D000A51A32920C00367B21 /* DeviceChange.cpp in Sources */, 28D8425C1AD8D69D00551353 /* SelectedRegion.cpp in Sources */, 2888A1631AE25F9A00E06FDC /* Diags.cpp in Sources */, + 28DDE3A21AE3771100C784FE /* ViewInfo.cpp in Sources */, + 2890498E1B6716B40038A543 /* SpectrogramSettings.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/plug-ins/SpectralEditMulti.ny b/plug-ins/SpectralEditMulti.ny index 57175dcf72bc68a5f09f2eb461ae82c1653b431b..c609fd20d821a9d79191f9723677e13b6bf1c9d8 100644 --- a/plug-ins/SpectralEditMulti.ny +++ b/plug-ins/SpectralEditMulti.ny @@ -45,7 +45,5 @@ (T (sum (prod env (wet sig f0 f1 fc)) (prod (diff 1.0 env) sig)))))) -(if (string-not-equal (get '*TRACK* 'VIEW) "spectral" :end1 8 :end2 8) - "Use this effect in the 'Spectral Selection'\nor 'Spectral Selection log(f)' view." - (catch 'error-message - (multichan-expand #'result *track*))) +(catch 'error-message + (multichan-expand #'result *track*)) diff --git a/plug-ins/SpectralEditParametricEQ.ny b/plug-ins/SpectralEditParametricEQ.ny index 20d7403bd2c0729cd59426d95eebfd73253d5fab..45671cf6d3d543c196cabd73d54c57be2531a6c1 100644 --- a/plug-ins/SpectralEditParametricEQ.ny +++ b/plug-ins/SpectralEditParametricEQ.ny @@ -19,20 +19,23 @@ (defmacro validate (hz) "Ensure frequency is below Nyquist" - `(setf hz (min (/ *sound-srate* 2.0),hz))) + `(setf ,hz (max 0 (min (/ *sound-srate* 2.0) ,hz)))) (defun wet (sig gain f0 f1) ;; (re)calculate bw and fc to ensure we do not exceed Nyquist frequency - (let ((fc (sqrt (* f0 (validate f1)))) - (bw (/ (log (/ (validate f1) f0)) - (log 2.0)))) + (validate f0) + (validate f1) + (let ((fc (sqrt (* f0 f1))) + (bw (/ (log (/ f1 f0)) + (log 2.0)))) + (when (= bw 0) + (throw 'error-message (format nil "~aBandwidth is zero.~%Select a frequency range." p-err))) (eq-band sig fc gain (/ bw 2)))) (defun result (sig) (let* ((f0 (get '*selection* 'low-hz)) (f1 (get '*selection* 'high-hz)) - (bw (get '*selection* 'bandwidth)) (tn (truncate len)) (rate (snd-srate sig)) (transition (truncate (* 0.01 rate))) ; 10 ms @@ -43,26 +46,16 @@ (cond ((not (or f0 f1)) (throw 'error-message (format nil "~aPlease select frequencies." p-err))) - ((not f0) + ((or (not f0) (= f0 0)) (throw 'error-message (format nil "~aLow frequency is undefined." p-err))) ((not f1) (throw 'error-message (format nil "~aHigh frequency is undefined." p-err))) - ((= bw 0) - (throw 'error-message (format nil "~aBandwidth is zero.~%Select a frequency range." p-err))) ;; If seleted frequency band is above Nyquist, do nothing. ((< f0 (/ *sound-srate* 2.0)) (sum (prod env (wet sig control-gain f0 f1)) (prod (diff 1.0 env) sig)))))) -(cond - ((not (get '*TRACK* 'VIEW)) ; 'View is NIL during Preview - (setf p-err (format nil "This effect requires a frequency selection in the~%~ - 'Spectrogram' or 'Spectrogram (log f)' track view.~%~%")) - (catch 'error-message - (multichan-expand #'result *track*))) - ((string-not-equal (get '*TRACK* 'VIEW) "spectral" :end1 8 :end2 8) - "Use this effect in the 'Spectral Selection'\nor 'Spectral Selection log(f)' view.") - (T (setf p-err "") - (if (= control-gain 0) ; Allow dry preview - "Gain is zero. Nothing to do." - (catch 'error-message - (multichan-expand #'result *track*))))) +(catch 'error-message + (setf p-err "") + (if (= control-gain 0) ; Allow dry preview + "Gain is zero. Nothing to do." + (multichan-expand #'result *track*))) diff --git a/plug-ins/SpectralEditShelves.ny b/plug-ins/SpectralEditShelves.ny index ff6c4060a5e1edc114895a61be49bbaebaa1dd23..6f523023cbf1bb4f2ad693dcfb820da356645567 100644 --- a/plug-ins/SpectralEditShelves.ny +++ b/plug-ins/SpectralEditShelves.ny @@ -19,7 +19,7 @@ (defmacro validate (hz) "Ensure frequency is below Nyquist" - `(setf hz (min (/ *sound-srate* 2.0),hz))) + `(setf ,hz (max 0 (min (/ *sound-srate* 2.0) ,hz)))) (defun mid-shelf (sig lf hf gain) "Combines high shelf and low shelf filters" @@ -30,9 +30,14 @@ (defun wet (sig gain f0 f1) (cond - ((not f0) (eq-lowshelf sig f1 gain)) - ((not f1) (eq-highshelf sig f0 gain)) - (t (mid-shelf sig f0 (validate f1) gain)))) + ((not f0) (eq-lowshelf sig (validate f1) gain)) + ((not f1) (eq-highshelf sig (validate f0) gain)) + (t + (validate f0) + (validate f1) + (when (= f0 f1) + (throw 'error-message "Please select a frequency range.")) + (mid-shelf sig f0 f1 gain)))) (defun result (sig) (let* @@ -48,8 +53,6 @@ (cond ((not (or f0 f1)) (throw 'error-message (format nil "~aPlease select frequencies." p-err))) - ((and f0 f1 (= f0 f1)) (throw 'error-message - "Please select a frequency range.")) ; shelf is above Nyquist frequency so do nothing ((and f0 (>= f0 (/ *sound-srate* 2.0))) nil) (T (sum (prod env (wet sig control-gain f0 f1)) @@ -63,18 +66,9 @@ (>= (get '*selection* 'high-hz)(/ *sound-srate* 2))) (remprop '*selection* 'high-hz)) -(cond - ((not (get '*TRACK* 'VIEW)) ; 'View is NIL during Preview - (setf p-err (format nil "This effect requires a frequency selection in the~%~ - 'Spectral Selection' or 'Spectral Selection log(f)'~%~ - track view.~%~%")) - (catch 'error-message - (multichan-expand #'result *track*))) - ((string-not-equal (get '*TRACK* 'VIEW) "spectral" :end1 8 :end2 8) - "Use this effect in the 'Spectral Selection'\nor 'Spectral Selection log(f)' view.") - (T (setf p-err "") - (if (= control-gain 0) ; Allow dry preview - "Gain is zero. Nothing to do." - (catch 'error-message - (multichan-expand #'result *track*))))) +(catch 'error-message + (setf p-err "") + (if (= control-gain 0) ; Allow dry preview + "Gain is zero. Nothing to do." + (multichan-expand #'result *track*))) diff --git a/src/Audacity.h b/src/Audacity.h index 7b934bca42e4339331488e8a86a66566d937554f..1ad029cbb2da17da7cbd4eead62a35320f840915 100644 --- a/src/Audacity.h +++ b/src/Audacity.h @@ -152,8 +152,11 @@ void QuitAudacity(); #endif #endif -// This macro is used widely, so declared here. -#define QUANTIZED_TIME(time, rate) ((double)((sampleCount)floor(((double)(time) * (rate)) + 0.5))) / (rate) +// These macros are used widely, so declared here. +#define QUANTIZED_TIME(time, rate) (((double)((sampleCount)floor(((double)(time) * (rate)) + 0.5))) / (rate)) +// dB - linear amplitude convesions +#define DB_TO_LINEAR(x) (pow(10.0, (x) / 20.0)) +#define LINEAR_TO_DB(x) (20.0 * log10(x)) // Marks strings for extraction only...must use wxGetTranslation() to translate. #define XO(s) wxT(s) diff --git a/src/AudacityApp.cpp b/src/AudacityApp.cpp index d4b3ebc1d145f436cba72863d07d7e84634b89d8..97b7ee0c0743b18c840ec477da54bd5df2d99705 100644 --- a/src/AudacityApp.cpp +++ b/src/AudacityApp.cpp @@ -92,6 +92,9 @@ It handles initialization and termination by subclassing wxApp. #include "ondemand/ODManager.h" #include "commands/Keyboard.h" #include "widgets/ErrorDialog.h" +#include "prefs/DirectoriesPrefs.h" +#include "prefs/SpectrogramSettings.h" +#include "prefs/WaveformSettings.h" //temporarilly commented out till it is added to all projects //#include "Profiler.h" @@ -123,9 +126,7 @@ It handles initialization and termination by subclassing wxApp. // Windows specific linker control...only needed once so // this is a good place (unless we want to add another file). #if defined(__WXMSW__) -//#if wxCHECK_VERSION(3, 0, 2) && !wxCHECK_VERSION(3, 1, 0) -#include <wx/init.h> -//#endif + // These lines ensure that Audacity gets WindowsXP themes. // Without them we get the old-style Windows98/2000 look under XP. # if !defined(__WXWINCE__) @@ -209,15 +210,6 @@ It handles initialization and termination by subclassing wxApp. # if defined(EXPERIMENTAL_CRASH_REPORT) # pragma comment(lib, "wxmsw" V "u" D "_qa") # endif -# pragma comment(lib, "wxbase" V "u" D) -# pragma comment(lib, "wxbase" V "u" D "_net.lib") -# pragma comment(lib, "wxmsw" V "u" D "_adv.lib") -# pragma comment(lib, "wxmsw" V "u" D "_core.lib") -# pragma comment(lib, "wxmsw" V "u" D "_html.lib") -# pragma comment(lib, "wxpng" D) -# pragma comment(lib, "wxzlib" D) -# pragma comment(lib, "wxjpeg" D) -# pragma comment(lib, "wxtiff" D) # undef V # undef D @@ -231,6 +223,9 @@ It handles initialization and termination by subclassing wxApp. //////////////////////////////////////////////////////////// DEFINE_EVENT_TYPE(EVT_OPEN_AUDIO_FILE); +DEFINE_EVENT_TYPE(EVT_CAPTURE_KEYBOARD); +DEFINE_EVENT_TYPE(EVT_RELEASE_KEYBOARD); +DEFINE_EVENT_TYPE(EVT_CAPTURE_KEY); #ifdef __WXGTK__ static void wxOnAssert(const wxChar *fileName, int lineNumber, const wxChar *msg) @@ -249,6 +244,8 @@ static void wxOnAssert(const wxChar *fileName, int lineNumber, const wxChar *msg } #endif +static wxFrame *gParentFrame = NULL; + static bool gInited = false; bool gIsQuitting = false; @@ -259,8 +256,6 @@ void QuitAudacity(bool bForce) gIsQuitting = true; - wxTheApp->SetExitOnFrameDelete(true); - // Try to close each open window. If the user hits Cancel // in a Save Changes dialog, don't continue. // BG: unless force is true @@ -295,8 +290,14 @@ void QuitAudacity(bool bForce) } } + LWSlider::DeleteSharedTipPanel(); + ModuleManager::Get().Dispatch(AppQuiting); + if (gParentFrame) + gParentFrame->Destroy(); + gParentFrame = NULL; + #ifdef EXPERIMENTAL_SCOREALIGN CloseScoreAlignDialog(); #endif @@ -648,12 +649,12 @@ public: }; }; -#if !defined(__WXMAC__) && !defined(__WXMSW__) +#ifndef __WXMAC__ IMPLEMENT_APP(AudacityApp) /* make the application class known to wxWidgets for dynamic construction */ #endif -#if defined(__WXMAC__) || defined(__WXMSW__) +#ifdef __WXMAC__ // This should be removed when Lame and FFmpeg support is converted // from loadable libraries to commands. // @@ -668,8 +669,6 @@ IMPLEMENT_APP(AudacityApp) // one tried. IMPLEMENT_APP_NO_MAIN(AudacityApp) IMPLEMENT_WX_THEME_SUPPORT - -#if defined(__WXMAC__) int main(int argc, char *argv[]) { if (getenv("DYLD_LIBRARY_PATH")) { @@ -678,31 +677,8 @@ int main(int argc, char *argv[]) unsetenv("DYLD_LIBRARY_PATH"); execve(argv[0], argv, environ); } - - wxDISABLE_DEBUG_SUPPORT(); - return wxEntry(argc, argv); } - -#elif defined(__WXMSW__) - -extern "C" int WINAPI WinMain(HINSTANCE hInstance, - HINSTANCE hPrevInstance, - wxCmdLineArgType WXUNUSED(lpCmdLine), - int nCmdShow) -{ - wxDISABLE_DEBUG_SUPPORT(); - - // Disable setting of HiDPI aware mode - wxMSWDisableSettingHighDPIAware(); - - /* NB: We pass NULL in place of lpCmdLine to behave the same as */ - /* Borland-specific wWinMain() above. If it becomes needed */ - /* to pass lpCmdLine to wxEntry() here, you'll have to fix */ - /* wWinMain() above too. */ - return wxEntry(hInstance, hPrevInstance, NULL, nCmdShow); -} -#endif #endif #ifdef __WXMAC__ @@ -1012,12 +988,11 @@ void AudacityApp::InitLang( const wxString & lang ) wxSetEnv(wxT("LANG"), wxT("en_US.UTF-8")); #endif - const wxLanguageInfo *info = wxLocale::FindLanguageInfo(lang); - if (!lang) - { - return; - } - mLocale = new wxLocale(info->Language); +#if wxCHECK_VERSION(3,0,0) + mLocale = new wxLocale(wxT(""), lang, wxT(""), true); +#else + mLocale = new wxLocale(wxT(""), lang, wxT(""), true, true); +#endif for(unsigned int i=0; i<audacityPathList.GetCount(); i++) mLocale->AddCatalogLookupPathPrefix(audacityPathList[i]); @@ -1038,7 +1013,12 @@ void AudacityApp::InitLang( const wxString & lang ) // // This must go _after_ creating the wxLocale instance because // creating the wxLocale instance sets the application-wide locale. + Internat::Init(); + + // Some static arrays unconnected with any project want to be informed of language changes. + SpectrogramSettings::InvalidateNames(); + WaveformSettings::InvalidateNames(); } void AudacityApp::OnFatalException() @@ -1096,16 +1076,16 @@ void AudacityApp::GenerateCrashReport(wxDebugReport::Context ctx) } #endif +#if defined(__WXGTK__) +// On wxGTK, there's a focus issue where dialogs do not automatically pass focus +// to the first child. This means that you can use the keyboard to navigate within +// the dialog. Watching for the ACTIVATE event allows us to set the focus ourselves +// when each dialog opens. +// +// See bug #57 +// int AudacityApp::FilterEvent(wxEvent & event) { -#if !wxCHECK_VERSION(3, 0, 0) && defined(__WXGTK__) - // On wxGTK, there's a focus issue where dialogs do not automatically pass focus - // to the first child. This means that you can use the keyboard to navigate within - // the dialog. Watching for the ACTIVATE event allows us to set the focus ourselves - // when each dialog opens. - // - // See bug #57 - // if (event.GetEventType() == wxEVT_ACTIVATE) { wxActivateEvent & e = (wxActivateEvent &) event; @@ -1115,11 +1095,10 @@ int AudacityApp::FilterEvent(wxEvent & event) ((wxWindow *)e.GetEventObject())->SetFocus(); } } - break; -#endif - return Event_Skip; + return -1; } +#endif AudacityApp::AudacityApp() { @@ -1137,9 +1116,6 @@ AudacityApp::AudacityApp() // main frame bool AudacityApp::OnInit() { - // Ensure we have an event loop during initialization - wxEventLoopGuarantor eventLoop; - delete wxLog::SetActiveTarget(new AudacityLogger); mLocale = NULL; @@ -1150,6 +1126,11 @@ bool AudacityApp::OnInit() mChecker = NULL; mIPCServ = NULL; +#if defined(__WXGTK__) + // Workaround for bug 154 -- initialize to false + inKbdHandler = false; +#endif + #if defined(__WXMAC__) // Disable window animation wxSystemOptions::SetOption( wxMAC_WINDOW_PLAIN_TRANSITION, 1 ); @@ -1299,6 +1280,15 @@ bool AudacityApp::OnInit() // If we're waiitng in a dialog before then we can very easily // start multiple instances, defeating the single instance checker. + + + + //JKC We'd like to initialise the module manager WHILE showing the splash screen. + //Can't in wx3.0.1 as MultiDialog interacts poorly with the splash screen. So we do it before. + //TODO: Find out why opening a multidialog wrecks the splash screen. + //best current guess is that it's something to do with doing a DoModal this early + //in the program. + // Initialize the CommandHandler InitCommandHandler(); @@ -1308,6 +1298,64 @@ bool AudacityApp::OnInit() // Initialize the ModuleManager, including loading found modules ModuleManager::Get().Initialize(*mCmdHandler); +#if !wxCHECK_VERSION(3, 0, 0) + FinishInits(); +#endif + + return TRUE; +} + +#if wxCHECK_VERSION(3, 0, 0) +#include <wx/evtloop.h> +static bool bInitsDone = false; +void AudacityApp::OnEventLoopEnter(wxEventLoopBase * pLoop) +{ + if( !pLoop->IsMain() ) + return; + if (bInitsDone) + return; + bInitsDone = true; + FinishInits(); +} +#endif + +// JKC: I've split 'FinishInits()' from 'OnInit()', so that +// we can have a real event loop running. We could (I think) +// put everything that is in OnInit() in here. +// This change was to support wxWidgets 3.0.0 and allow us +// to show a dialog (for module loading) during initialisation. +// without it messing up the splash screen. +// Hasn't actually fixed that yet, but is addressing the point +// they make in their release notes. +void AudacityApp::FinishInits() +{ + +// Until we are ready for wxWidgets 3.x, put a warning dialog up. +// Our problem is that distros may ship with 3.x builds as default. +// We are saying, don't. +// +// wx3 is Ok for experimental builds. +// +// Deliberately not translated. People can search for the english error +// text for more details. This error will only show in versions +// of Audacity that were incorrectly built. +// +// The intention was to do this, if needed, as part of the splash screen. +// However the splash screen is one of the things broken by wx3.0 +// changes in OnInit handling. We also can't put this dialog earlier. +#if wxCHECK_VERSION(3, 0, 0) + ShowErrorDialog( NULL, + wxT("Bad Version"), + wxT( +"Audacity should be built with wxWidgets 2.8.12.\n\n This version \ +of Audacity (") AUDACITY_VERSION_STRING wxT(") is using ") wxVERSION_STRING \ +wxT( ".\n We're not ready for that version of wxWidgets yet.\n\n \ +Click the 'Help' button for known issues."), + wxT("http://wiki.audacityteam.org/wiki/Incorrect_wxWidgets_Version"), + true); +#endif + + // Parse command line and handle options that might require // immediate exit...no need to initialize all of the audio // stuff to display the version string. @@ -1357,6 +1405,9 @@ bool AudacityApp::OnInit() exit(1); } +// No Splash screen on wx3 whislt we sort out the problem +// with showing a dialog AND a splash screen during inits. +#if !wxCHECK_VERSION(3, 0, 0) // BG: Create a temporary window to set as the top window wxImage logoimage((const char **) AudacityLogoWithName_xpm); logoimage.Rescale(logoimage.GetWidth() / 2, logoimage.GetHeight() / 2); @@ -1373,7 +1424,7 @@ bool AudacityApp::OnInit() wxSTAY_ON_TOP); temporarywindow->SetTitle(_("Audacity is starting up...")); SetTopWindow(temporarywindow); - wxEventLoopBase::GetActive()->YieldFor(wxEVT_CATEGORY_UI); +#endif //JKC: Would like to put module loading here. @@ -1403,10 +1454,15 @@ bool AudacityApp::OnInit() mRecentFiles->UseMenu(recentMenu); mRecentFiles->AddFilesToMenu(recentMenu); - SetExitOnFrameDelete(false); + // This invisibale frame will be the "root" of all other frames and will + // become the active frame when no projects are open. + gParentFrame = new wxFrame(NULL, -1, wxEmptyString, wxPoint(0, 0), wxSize(0, 0), 0); #endif //__WXMAC__ + SetExitOnFrameDelete(true); + + AudacityProject *project = CreateNewAudacityProject(); mCmdHandler->SetProject(project); wxWindow * pWnd = MakeHijackPanel() ; @@ -1418,8 +1474,11 @@ bool AudacityApp::OnInit() pWnd->Show( true ); } + +#if !wxCHECK_VERSION(3, 0, 0) temporarywindow->Show(false); delete temporarywindow; +#endif if( project->mShowSplashScreen ) project->OnHelpWelcome(); @@ -1447,7 +1506,7 @@ bool AudacityApp::OnInit() DirManager::SetDontDeleteTempFiles(); delete parser; QuitAudacity(true); - return false; + return; } // @@ -1460,7 +1519,7 @@ bool AudacityApp::OnInit() delete parser; RunBenchmark(NULL); - return false; + return; } for (size_t i = 0, cnt = parser->GetParamCount(); i < cnt; i++) @@ -1479,8 +1538,6 @@ bool AudacityApp::OnInit() mTimer.SetOwner(this, kAudacityAppTimerID); mTimer.Start(200); - - return TRUE; } void AudacityApp::InitCommandHandler() @@ -1556,8 +1613,11 @@ bool AudacityApp::InitTempDir() // Failed wxMessageBox(_("Audacity could not find a place to store temporary files.\nPlease enter an appropriate directory in the preferences dialog.")); - PrefsDialog dialog(NULL); - dialog.ShowTempDirPage(); + // Only want one page of the preferences + DirectoriesPrefsFactory directoriesPrefsFactory; + PrefsDialog::Factories factories; + factories.push_back(&directoriesPrefsFactory); + GlobalPrefsDialog dialog(NULL, factories); dialog.ShowModal(); wxMessageBox(_("Audacity is now going to exit. Please launch Audacity again to use the new temporary directory.")); @@ -2083,7 +2143,7 @@ void AudacityApp::OnMenuPreferences(wxCommandEvent & event) // all platforms. if(gAudacityProjects.GetCount() == 0) { - PrefsDialog dialog(NULL /* parent */ ); + GlobalPrefsDialog dialog(NULL /* parent */ ); dialog.ShowModal(); } else diff --git a/src/AudioIO.cpp b/src/AudioIO.cpp index b8c6c29069e6093245a76abe97ae4decbe26e12e..cfcaaac07cbd887fdda31a7f85d0e7f4e36812cc 100644 --- a/src/AudioIO.cpp +++ b/src/AudioIO.cpp @@ -265,8 +265,9 @@ writing audio. *//*******************************************************************/ #include "Audacity.h" -#include "float_cast.h" #include "Experimental.h" +#include "AudioIO.h" +#include "float_cast.h" #include <math.h> #include <stdlib.h> @@ -294,11 +295,11 @@ writing audio. #include <wx/txtstrm.h> #include "AudacityApp.h" -#include "AudioIO.h" #include "Mix.h" #include "MixerBoard.h" #include "Resample.h" #include "RingBuffer.h" +#include "prefs/GUISettings.h" #include "Prefs.h" #include "Project.h" #include "TimeTrack.h" @@ -308,8 +309,6 @@ writing audio. #include "toolbars/ControlToolBar.h" #include "widgets/Meter.h" -#include "Experimental.h" - #ifdef EXPERIMENTAL_MIDI_OUT #define MIDI_SLEEP 10 /* milliseconds */ #define ROUND(x) (int) ((x)+0.5) @@ -856,6 +855,8 @@ bool AudioIO::ValidateDeviceNames(wxString play, wxString rec) AudioIO::AudioIO() { + mCaptureTracks = mPlaybackTracks = NULL; + mAudioThreadShouldCallFillBuffersOnce = false; mAudioThreadFillBuffersLoopRunning = false; mAudioThreadFillBuffersLoopActive = false; @@ -992,6 +993,9 @@ AudioIO::~AudioIO() #ifdef EXPERIMENTAL_SCRUBBING_SUPPORT delete mScrubQueue; #endif + + delete mCaptureTracks; + delete mPlaybackTracks; } void AudioIO::SetMixer(int inputSource) @@ -1525,11 +1529,11 @@ int AudioIO::StartStream(WaveTrackArray playbackTracks, int silenceLevelDB; gPrefs->Read(wxT("/AudioIO/SilenceLevel"), &silenceLevelDB, -50); int dBRange; - dBRange = gPrefs->Read(wxT("/GUI/EnvdBRange"), ENV_DB_RANGE); + dBRange = gPrefs->Read(ENV_DB_KEY, ENV_DB_RANGE); if(silenceLevelDB < -dBRange) { silenceLevelDB = -dBRange + 3; // meter range was made smaller than SilenceLevel - gPrefs->Write(wxT("/GUI/EnvdBRange"), dBRange); // so set SilenceLevel reasonable + gPrefs->Write(ENV_DB_KEY, dBRange); // so set SilenceLevel reasonable gPrefs->Flush(); } mSilenceLevel = (silenceLevelDB + dBRange)/(double)dBRange; // meter goes -dBRange dB -> 0dB @@ -1542,8 +1546,8 @@ int AudioIO::StartStream(WaveTrackArray playbackTracks, mTime = t0; mSeek = 0; mLastRecordingOffset = 0; - mPlaybackTracks = playbackTracks; - mCaptureTracks = captureTracks; + mPlaybackTracks = new WaveTrackArray(playbackTracks); + mCaptureTracks = new WaveTrackArray(captureTracks); #ifdef EXPERIMENTAL_MIDI_OUT mMidiPlaybackTracks = midiPlaybackTracks; #endif @@ -1563,7 +1567,7 @@ int AudioIO::StartStream(WaveTrackArray playbackTracks, double minScrubStutter = options.minScrubStutter; if (scrubbing) { - if (mCaptureTracks.GetCount() > 0 || + if (mCaptureTracks->GetCount() > 0 || mPlayMode == PLAY_LOOPED || mTimeTrack != NULL || options.maxScrubSpeed < GetMinScrubSpeed()) @@ -1625,8 +1629,8 @@ int AudioIO::StartStream(WaveTrackArray playbackTracks, // Capacity of the playback buffer. mPlaybackRingBufferSecs = 10.0; - mCaptureRingBufferSecs = 4.5 + 0.5 * std::min(size_t(16), mCaptureTracks.GetCount()); - mMinCaptureSecsToCopy = 0.2 + 0.2 * std::min(size_t(16), mCaptureTracks.GetCount()); + mCaptureRingBufferSecs = 4.5 + 0.5 * std::min(size_t(16), mCaptureTracks->GetCount()); + mMinCaptureSecsToCopy = 0.2 + 0.2 * std::min(size_t(16), mCaptureTracks->GetCount()); unsigned int playbackChannels = 0; unsigned int captureChannels = 0; @@ -1641,7 +1645,7 @@ int AudioIO::StartStream(WaveTrackArray playbackTracks, if( captureTracks.GetCount() > 0 ) { // For capture, every input channel gets its own track - captureChannels = mCaptureTracks.GetCount(); + captureChannels = mCaptureTracks->GetCount(); // I don't deal with the possibility of the capture tracks // having different sample formats, since it will never happen // with the current code. This code wouldn't *break* if this @@ -1650,7 +1654,7 @@ int AudioIO::StartStream(WaveTrackArray playbackTracks, // we would set the sound card to capture in 16 bits and the second // track wouldn't get the benefit of all 24 bits the card is capable // of. - captureFormat = mCaptureTracks[0]->GetSampleFormat(); + captureFormat = (*mCaptureTracks)[0]->GetSampleFormat(); // Tell project that we are about to start recording if (mListener) @@ -1711,12 +1715,12 @@ int AudioIO::StartStream(WaveTrackArray playbackTracks, return 0; } - mPlaybackBuffers = new RingBuffer* [mPlaybackTracks.GetCount()]; - mPlaybackMixers = new Mixer* [mPlaybackTracks.GetCount()]; + mPlaybackBuffers = new RingBuffer* [mPlaybackTracks->GetCount()]; + mPlaybackMixers = new Mixer* [mPlaybackTracks->GetCount()]; // Set everything to zero in case we have to delete these due to a memory exception. - memset(mPlaybackBuffers, 0, sizeof(RingBuffer*)*mPlaybackTracks.GetCount()); - memset(mPlaybackMixers, 0, sizeof(Mixer*)*mPlaybackTracks.GetCount()); + memset(mPlaybackBuffers, 0, sizeof(RingBuffer*)*mPlaybackTracks->GetCount()); + memset(mPlaybackMixers, 0, sizeof(Mixer*)*mPlaybackTracks->GetCount()); const Mixer::WarpOptions &warpOptions = #ifdef EXPERIMENTAL_SCRUBBING_SUPPORT @@ -1724,12 +1728,12 @@ int AudioIO::StartStream(WaveTrackArray playbackTracks, #endif Mixer::WarpOptions(mTimeTrack); - for (unsigned int i = 0; i < mPlaybackTracks.GetCount(); i++) + for (unsigned int i = 0; i < mPlaybackTracks->GetCount(); i++) { mPlaybackBuffers[i] = new RingBuffer(floatSample, playbackBufferSize); // MB: use normal time for the end time, not warped time! - mPlaybackMixers[i] = new Mixer(1, &mPlaybackTracks[i], + mPlaybackMixers[i] = new Mixer(1, &(*mPlaybackTracks)[i], warpOptions, mT0, mT1, 1, playbackMixBufferSize, false, @@ -1753,17 +1757,17 @@ int AudioIO::StartStream(WaveTrackArray playbackTracks, return 0; } - mCaptureBuffers = new RingBuffer* [mCaptureTracks.GetCount()]; - mResample = new Resample* [mCaptureTracks.GetCount()]; + mCaptureBuffers = new RingBuffer* [mCaptureTracks->GetCount()]; + mResample = new Resample* [mCaptureTracks->GetCount()]; mFactor = sampleRate / mRate; // Set everything to zero in case we have to delete these due to a memory exception. - memset(mCaptureBuffers, 0, sizeof(RingBuffer*)*mCaptureTracks.GetCount()); - memset(mResample, 0, sizeof(Resample*)*mCaptureTracks.GetCount()); + memset(mCaptureBuffers, 0, sizeof(RingBuffer*)*mCaptureTracks->GetCount()); + memset(mResample, 0, sizeof(Resample*)*mCaptureTracks->GetCount()); - for( unsigned int i = 0; i < mCaptureTracks.GetCount(); i++ ) + for( unsigned int i = 0; i < mCaptureTracks->GetCount(); i++ ) { - mCaptureBuffers[i] = new RingBuffer( mCaptureTracks[i]->GetSampleFormat(), + mCaptureBuffers[i] = new RingBuffer( (*mCaptureTracks)[i]->GetSampleFormat(), captureBufferSize ); mResample[i] = new Resample(true, mFactor, mFactor); // constant rate resampling } @@ -1791,9 +1795,9 @@ int AudioIO::StartStream(WaveTrackArray playbackTracks, // group determination should mimic what is done in audacityAudioCallback() // when calling RealtimeProcess(). int group = 0; - for (size_t i = 0, cnt = mPlaybackTracks.GetCount(); i < cnt; i++) + for (size_t i = 0, cnt = mPlaybackTracks->GetCount(); i < cnt; i++) { - WaveTrack *vt = gAudioIO->mPlaybackTracks[i]; + WaveTrack *vt = (*gAudioIO->mPlaybackTracks)[i]; int chanCnt = 1; if (vt->GetLinked()) @@ -1815,7 +1819,7 @@ int AudioIO::StartStream(WaveTrackArray playbackTracks, // Calculate the new time position mTime = std::max(mT0, std::min(mT1, *options.pStartTime)); // Reset mixer positions for all playback tracks - unsigned numMixers = mPlaybackTracks.GetCount(); + unsigned numMixers = mPlaybackTracks->GetCount(); for (unsigned ii = 0; ii < numMixers; ++ii) mPlaybackMixers[ii]->Reposition(mTime); if(mTimeTrack) @@ -1919,7 +1923,7 @@ void AudioIO::StartStreamCleanup(bool bOnlyBuffers) if(mPlaybackBuffers) { - for( unsigned int i = 0; i < mPlaybackTracks.GetCount(); i++ ) + for( unsigned int i = 0; i < mPlaybackTracks->GetCount(); i++ ) delete mPlaybackBuffers[i]; delete [] mPlaybackBuffers; mPlaybackBuffers = NULL; @@ -1927,7 +1931,7 @@ void AudioIO::StartStreamCleanup(bool bOnlyBuffers) if(mPlaybackMixers) { - for( unsigned int i = 0; i < mPlaybackTracks.GetCount(); i++ ) + for( unsigned int i = 0; i < mPlaybackTracks->GetCount(); i++ ) delete mPlaybackMixers[i]; delete [] mPlaybackMixers; mPlaybackMixers = NULL; @@ -1935,7 +1939,7 @@ void AudioIO::StartStreamCleanup(bool bOnlyBuffers) if(mCaptureBuffers) { - for( unsigned int i = 0; i < mCaptureTracks.GetCount(); i++ ) + for( unsigned int i = 0; i < mCaptureTracks->GetCount(); i++ ) delete mCaptureBuffers[i]; delete [] mCaptureBuffers; mCaptureBuffers = NULL; @@ -1943,7 +1947,7 @@ void AudioIO::StartStreamCleanup(bool bOnlyBuffers) if(mResample) { - for( unsigned int i = 0; i < mCaptureTracks.GetCount(); i++ ) + for( unsigned int i = 0; i < mCaptureTracks->GetCount(); i++ ) delete mResample[i]; delete [] mResample; mResample = NULL; @@ -2268,9 +2272,9 @@ void AudioIO::StopStream() // we allocated in StartStream() // - if( mPlaybackTracks.GetCount() > 0 ) + if( mPlaybackTracks->GetCount() > 0 ) { - for( unsigned int i = 0; i < mPlaybackTracks.GetCount(); i++ ) + for( unsigned int i = 0; i < mPlaybackTracks->GetCount(); i++ ) { delete mPlaybackBuffers[i]; delete mPlaybackMixers[i]; @@ -2283,7 +2287,7 @@ void AudioIO::StopStream() // // Offset all recorded tracks to account for latency // - if( mCaptureTracks.GetCount() > 0 ) + if( mCaptureTracks->GetCount() > 0 ) { // // We only apply latency correction when we actually played back @@ -2298,15 +2302,15 @@ void AudioIO::StopStream() double recordingOffset = mLastRecordingOffset + latencyCorrection / 1000.0; - for( unsigned int i = 0; i < mCaptureTracks.GetCount(); i++ ) + for( unsigned int i = 0; i < mCaptureTracks->GetCount(); i++ ) { delete mCaptureBuffers[i]; delete mResample[i]; - WaveTrack* track = mCaptureTracks[i]; + WaveTrack* track = (*mCaptureTracks)[i]; track->Flush(); - if (mPlaybackTracks.GetCount() > 0) + if (mPlaybackTracks->GetCount() > 0) { // only do latency correction if some tracks are being played back WaveTrackArray playbackTracks; AudacityProject *p = GetActiveProject(); @@ -2873,7 +2877,7 @@ int AudioIO::GetCommonlyAvailPlayback() int commonlyAvail = mPlaybackBuffers[0]->AvailForPut(); unsigned int i; - for( i = 1; i < mPlaybackTracks.GetCount(); i++ ) + for( i = 1; i < mPlaybackTracks->GetCount(); i++ ) { int thisBlockAvail = mPlaybackBuffers[i]->AvailForPut(); @@ -2889,7 +2893,7 @@ int AudioIO::GetCommonlyAvailCapture() int commonlyAvail = mCaptureBuffers[0]->AvailForGet(); unsigned int i; - for( i = 1; i < mCaptureTracks.GetCount(); i++ ) + for( i = 1; i < mCaptureTracks->GetCount(); i++ ) { int avail = mCaptureBuffers[i]->AvailForGet(); if( avail < commonlyAvail ) @@ -3266,7 +3270,7 @@ void AudioIO::FillBuffers() { unsigned int i; - if( mPlaybackTracks.GetCount() > 0 ) + if( mPlaybackTracks->GetCount() > 0 ) { // Though extremely unlikely, it is possible that some buffers // will have more samples available than others. This could happen @@ -3323,7 +3327,7 @@ void AudioIO::FillBuffers() mWarpedTime += deltat; } - for( i = 0; i < mPlaybackTracks.GetCount(); i++ ) + for( i = 0; i < mPlaybackTracks->GetCount(); i++ ) { // The mixer here isn't actually mixing: it's just doing // resampling, format conversion, and possibly time track @@ -3400,7 +3404,7 @@ void AudioIO::FillBuffers() startTime = startSample / mRate; endTime = endSample / mRate; speed = double(abs(endSample - startSample)) / mScrubDuration; - for (i = 0; i < mPlaybackTracks.GetCount(); i++) + for (i = 0; i < mPlaybackTracks->GetCount(); i++) mPlaybackMixers[i]->SetTimesAndSpeed(startTime, endTime, speed); } } @@ -3415,7 +3419,7 @@ void AudioIO::FillBuffers() // and if yes, restart from the beginning. if (mWarpedTime >= mWarpedLength) { - for (i = 0; i < mPlaybackTracks.GetCount(); i++) + for (i = 0; i < mPlaybackTracks->GetCount(); i++) mPlaybackMixers[i]->Restart(); mWarpedTime = 0.0; } @@ -3429,7 +3433,7 @@ void AudioIO::FillBuffers() } } // end of playback buffering - if( mCaptureTracks.GetCount() > 0 ) // start record buffering + if( mCaptureTracks->GetCount() > 0 ) // start record buffering { int commonlyAvail = GetCommonlyAvailCapture(); @@ -3444,12 +3448,12 @@ void AudioIO::FillBuffers() // Append captured samples to the end of the WaveTracks. // The WaveTracks have their own buffering for efficiency. AutoSaveFile blockFileLog; - int numChannels = mCaptureTracks.GetCount(); + int numChannels = mCaptureTracks->GetCount(); for( i = 0; (int)i < numChannels; i++ ) { int avail = commonlyAvail; - sampleFormat trackFormat = mCaptureTracks[i]->GetSampleFormat(); + sampleFormat trackFormat = (*mCaptureTracks)[i]->GetSampleFormat(); AutoSaveFile appendLog; @@ -3457,7 +3461,7 @@ void AudioIO::FillBuffers() { samplePtr temp = NewSamples(avail, trackFormat); mCaptureBuffers[i]->Get (temp, trackFormat, avail); - mCaptureTracks[i]-> Append(temp, trackFormat, avail, 1, + (*mCaptureTracks)[i]-> Append(temp, trackFormat, avail, 1, &appendLog); DeleteSamples(temp); } @@ -3473,7 +3477,7 @@ void AudioIO::FillBuffers() */ size = mResample[i]->Process(mFactor, (float *)temp1, avail, !IsStreamActive(), &size, (float *)temp2, size); - mCaptureTracks[i]-> Append(temp2, floatSample, size, 1, + (*mCaptureTracks)[i]-> Append(temp2, floatSample, size, 1, &appendLog); DeleteSamples(temp1); DeleteSamples(temp2); @@ -3482,7 +3486,7 @@ void AudioIO::FillBuffers() if (!appendLog.IsEmpty()) { blockFileLog.StartTag(wxT("recordingrecovery")); - blockFileLog.WriteAttr(wxT("id"), mCaptureTracks[i]->GetAutoSaveIdent()); + blockFileLog.WriteAttr(wxT("id"), (*mCaptureTracks)[i]->GetAutoSaveIdent()); blockFileLog.WriteAttr(wxT("channel"), (int)i); blockFileLog.WriteAttr(wxT("numchannels"), numChannels); blockFileLog.WriteSubTree(appendLog); @@ -3675,7 +3679,7 @@ bool AudioIO::SetHasSolo(bool hasSolo) void AudioIO::FillMidiBuffers() { bool hasSolo = false; - int numPlaybackTracks = gAudioIO->mPlaybackTracks.GetCount(); + int numPlaybackTracks = gAudioIO->mPlaybackTracks->GetCount(); int t; for(t = 0; t < numPlaybackTracks; t++ ) if( gAudioIO->mPlaybackTracks[t]->GetSolo() ) { @@ -3956,7 +3960,7 @@ int audacityAudioCallback(const void *inputBuffer, void *outputBuffer, const PaStreamCallbackFlags WXUNUSED(statusFlags), void * WXUNUSED(userData) ) { int numPlaybackChannels = gAudioIO->mNumPlaybackChannels; - int numPlaybackTracks = gAudioIO->mPlaybackTracks.GetCount(); + int numPlaybackTracks = gAudioIO->mPlaybackTracks->GetCount(); int numCaptureChannels = gAudioIO->mNumCaptureChannels; int callbackReturn = paContinue; void *tempBuffer = alloca(framesPerBuffer*sizeof(float)* @@ -4137,7 +4141,7 @@ int audacityAudioCallback(const void *inputBuffer, void *outputBuffer, int numSolo = 0; for( t = 0; t < numPlaybackTracks; t++ ) - if( gAudioIO->mPlaybackTracks[t]->GetSolo() ) + if( (*gAudioIO->mPlaybackTracks)[t]->GetSolo() ) numSolo++; #ifdef EXPERIMENTAL_MIDI_OUT int numMidiPlaybackTracks = gAudioIO->mMidiPlaybackTracks.GetCount(); @@ -4162,7 +4166,7 @@ int audacityAudioCallback(const void *inputBuffer, void *outputBuffer, int maxLen = 0; for (t = 0; t < numPlaybackTracks; t++) { - WaveTrack *vt = gAudioIO->mPlaybackTracks[t]; + WaveTrack *vt = (*gAudioIO->mPlaybackTracks)[t]; chans[chanCnt] = vt; @@ -4516,6 +4520,8 @@ int audacityAudioCallback(const void *inputBuffer, void *outputBuffer, // The problem there occurs if Software Playthrough is on. // Could conditionally do the update here if Software Playthrough is off, // and in TrackPanel::OnTimer() if Software Playthrough is on, but not now. + // PRL 12 Jul 2015: and what was in TrackPanel::OnTimer is now handled by means of event + // type EVT_TRACK_PANEL_TIMER //AudacityProject* pProj = GetActiveProject(); //MixerBoard* pMixerBoard = pProj->GetMixerBoard(); //if (pMixerBoard) diff --git a/src/AudioIO.h b/src/AudioIO.h index ad065548219b4a9bf34c570f9b0332f877fe3ce6..d6fcc32846ae1470466e0509c0b33f0291c177c3 100644 --- a/src/AudioIO.h +++ b/src/AudioIO.h @@ -29,10 +29,10 @@ #include "portmixer.h" #endif +#include <wx/event.h> #include <wx/string.h> #include <wx/thread.h> -#include "WaveTrack.h" #include "SampleFormat.h" class AudioIO; @@ -46,6 +46,9 @@ class SelectedRegion; class TimeTrack; class wxDialog; +class AudacityProject; +class WaveTrackArray; + extern AUDACITY_DLL_API AudioIO *gAudioIO; void InitAudioIO(); @@ -571,9 +574,9 @@ private: #endif Resample **mResample; RingBuffer **mCaptureBuffers; - WaveTrackArray mCaptureTracks; + WaveTrackArray *mCaptureTracks; RingBuffer **mPlaybackBuffers; - WaveTrackArray mPlaybackTracks; + WaveTrackArray *mPlaybackTracks; Mixer **mPlaybackMixers; volatile int mStreamToken; diff --git a/src/AutoRecovery.cpp b/src/AutoRecovery.cpp index c8f2a15b708aea95388dee0c0702906fb6a05af9..dd97e025264a163a2d1989cf3aa3ca5f3d785359 100644 --- a/src/AutoRecovery.cpp +++ b/src/AutoRecovery.cpp @@ -19,6 +19,7 @@ recover previous Audacity projects that were closed incorrectly. #include "AudacityApp.h" #include "FileNames.h" #include "blockfile/SimpleBlockFile.h" +#include "Sequence.h" #include "ShuttleGui.h" #include <wx/wxprec.h> @@ -27,6 +28,8 @@ recover previous Audacity projects that were closed incorrectly. #include <wx/dialog.h> #include <wx/app.h> +#include "WaveTrack.h" + enum { ID_RECOVER_ALL = 10000, ID_RECOVER_NONE, diff --git a/src/BatchCommands.cpp b/src/BatchCommands.cpp index 4023d2bad90a142525168eb3e1e6cf0020002edc..bada3f6a0b92a9d6c820d0c86ed865f099e2607b 100644 --- a/src/BatchCommands.cpp +++ b/src/BatchCommands.cpp @@ -17,6 +17,7 @@ See also BatchCommandDialog and BatchProcessDialog. #include "Audacity.h" +#include "BatchCommands.h" #include <wx/defs.h> #include <wx/dir.h> @@ -25,7 +26,6 @@ See also BatchCommandDialog and BatchProcessDialog. #include <wx/textfile.h> #include "Project.h" -#include "BatchCommands.h" #include "commands/CommandManager.h" #include "effects/EffectManager.h" #include "FileNames.h" @@ -41,6 +41,7 @@ See also BatchCommandDialog and BatchProcessDialog. #include "Theme.h" #include "AllThemeResources.h" +#include "Track.h" // KLUDGE: All commands should be on the same footing // however, for historical reasons we distinguish between @@ -682,8 +683,7 @@ bool BatchCommands::ApplyChain(const wxString & filename) { if(proj) { // Chain failed or was cancelled; revert to the previous state - UndoManager *um = proj->GetUndoManager(); - proj->SetStateTo(um->GetCurrentState()); + proj->RollbackState(); } return false; } diff --git a/src/BlockFile.cpp b/src/BlockFile.cpp index ed94a1a5847d818759f216b362df9edb680aa4d3..1c434a2df9abfad3d50bfc2ae85467905bbdccd2 100644 --- a/src/BlockFile.cpp +++ b/src/BlockFile.cpp @@ -42,6 +42,8 @@ out. *//*******************************************************************/ +#include "BlockFile.h" + #include <float.h> #include <math.h> @@ -51,7 +53,6 @@ out. #include <wx/log.h> #include <wx/math.h> -#include "BlockFile.h" #include "Internat.h" // msmeyer: Define this to add debug output via printf() diff --git a/src/BlockFile.h b/src/BlockFile.h index b8254cc43ec5fe829cafd9f9aed60252634c08bb..8f8eb6c1f8578115183f72f51ef7f0934574550e 100644 --- a/src/BlockFile.h +++ b/src/BlockFile.h @@ -16,11 +16,11 @@ #include <wx/ffile.h> #include <wx/filename.h> -#include "WaveTrack.h" - #include "xml/XMLTagHandler.h" #include "xml/XMLWriter.h" +#include "SampleFormat.h" + class SummaryInfo { public: @@ -209,7 +209,7 @@ class AliasBlockFile : public BlockFile // // These methods are for advanced use only! // - wxFileName GetAliasedFileName() { return mAliasedFileName; }; + wxFileName GetAliasedFileName() { return mAliasedFileName; } void ChangeAliasedFileName(wxFileName newAliasedFile); virtual bool IsAlias() { return true; } diff --git a/src/Dependencies.cpp b/src/Dependencies.cpp index 8bff3a9cc0926961e3cb33cc6a2fdd6d93ebc32c..3a3df38e1026c6f30506149733254970fb79f791 100644 --- a/src/Dependencies.cpp +++ b/src/Dependencies.cpp @@ -21,6 +21,8 @@ **********************************************************************/ +#include "Dependencies.h" + #include <wx/button.h> #include <wx/defs.h> #include <wx/dialog.h> @@ -30,13 +32,14 @@ #include <wx/choice.h> #include "BlockFile.h" -#include "Dependencies.h" #include "DirManager.h" #include "Internat.h" #include "Prefs.h" #include "Project.h" +#include "Sequence.h" #include "ShuttleGui.h" -#include "Track.h" +#include "WaveTrack.h" +#include "WaveClip.h" // Note, this #include must occur here, not up with the others! // It must be between the WX_DECLARE_OBJARRAY and WX_DEFINE_OBJARRAY. diff --git a/src/Dependencies.h b/src/Dependencies.h index c4bda4d57278d09bb06483742e950ca76e33d959..70044b23507aa01931c9e8bc064ff672cead1d7a 100644 --- a/src/Dependencies.h +++ b/src/Dependencies.h @@ -15,6 +15,7 @@ #define __AUDACITY_DEPENDENCIES__ #include <wx/dynarray.h> +#include <wx/filename.h> class AudacityProject; diff --git a/src/DirManager.cpp b/src/DirManager.cpp index 8104f56b13b7acc98f724fa5045e5db64f85099a..8d2a570313560d3ffe4a0651be5533cbf8769e56 100644 --- a/src/DirManager.cpp +++ b/src/DirManager.cpp @@ -62,6 +62,7 @@ #include "Audacity.h" +#include "DirManager.h" #include <time.h> // to use time() for srand() @@ -94,16 +95,16 @@ #include "blockfile/PCMAliasBlockFile.h" #include "blockfile/ODPCMAliasBlockFile.h" #include "blockfile/ODDecodeBlockFile.h" -#include "DirManager.h" #include "Internat.h" #include "Project.h" #include "Prefs.h" #include "widgets/Warning.h" #include "widgets/MultiDialog.h" -#include "prefs/PrefsDialog.h" #include "ondemand/ODManager.h" +#include "Track.h" + #if defined(__WXMAC__) #include <mach/mach.h> #include <mach/vm_statistics.h> diff --git a/src/DirManager.h b/src/DirManager.h index bcc10cac7e9ace3000b114836cbe640a57c752b2..dc8af0fc8208c10a43df77f4a142799941f2776e 100644 --- a/src/DirManager.h +++ b/src/DirManager.h @@ -15,8 +15,10 @@ #include <wx/string.h> #include <wx/filename.h> #include <wx/hashmap.h> +#include <wx/utils.h> -#include "WaveTrack.h" +#include "audacity/Types.h" +#include "xml/XMLTagHandler.h" class wxHashTable; class BlockFile; @@ -105,7 +107,7 @@ class DirManager: public XMLTagHandler { void SetMaxSamples(sampleCount max) { mMaxSamples = max; } bool HandleXMLTag(const wxChar *tag, const wxChar **attrs); XMLTagHandler *HandleXMLChild(const wxChar * WXUNUSED(tag)) { return NULL; } - void WriteXML(XMLWriter & WXUNUSED(xmlFile)) { wxASSERT(false); }; // This class only reads tags. + void WriteXML(XMLWriter & WXUNUSED(xmlFile)) { wxASSERT(false); } // This class only reads tags. bool AssignFile(wxFileName &filename,wxString value,bool check); // Clean the temp dir. Note that now where we have auto recovery the temp diff --git a/src/Envelope.cpp b/src/Envelope.cpp index e2eec3ffd83c63a0d3571da1e4ce3bdd04608ca4..d12fcb3a7760054867eddb05b3f27a2346ce61ae 100644 --- a/src/Envelope.cpp +++ b/src/Envelope.cpp @@ -39,7 +39,6 @@ a draggable point type. #include <wx/log.h> #include "AColor.h" -#include "Prefs.h" #include "DirManager.h" #include "TrackArtist.h" @@ -175,23 +174,6 @@ static double Limit( double Lo, double Value, double Hi ) return Value; } -double Envelope::toDB(double value) -{ - if (value == 0) - return 0; - - // TODO: Cache the gPrefs value. Reading it every time is inefficient. - double dBRange = gPrefs->Read(wxT("/GUI/EnvdBRange"), ENV_DB_RANGE); - double sign = (value >= 0 ? 1 : -1); - - wxASSERT( dBRange > 0 ); - double db = 20 * log10(fabs(value)); - double val = (db + dBRange) / dBRange; - - val = Limit( 0.0, val, 1.0 ); - return sign * val; -} - /// TODO: This should probably move to track artist. static void DrawPoint(wxDC & dc, const wxRect & r, int x, int y, bool top) { @@ -205,8 +187,7 @@ static void DrawPoint(wxDC & dc, const wxRect & r, int x, int y, bool top) void Envelope::DrawPoints(wxDC & dc, const wxRect & r, const ZoomInfo &zoomInfo, bool dB, float zoomMin, float zoomMax) { - // TODO: Cache the gPrefs value. Reading it every time is inefficient. - double dBRange = gPrefs->Read(wxT("/GUI/EnvdBRange"), ENV_DB_RANGE); + double dBRange = zoomInfo.dBr; dc.SetPen(AColor::envelopePen); dc.SetBrush(*wxWHITE_BRUSH); @@ -330,13 +311,13 @@ inline int SQR(int x) { return x * x; } /// @dB - display mode either linear or log. /// @zoomMin - vertical scale, typically -1.0 /// @zoomMax - vertical scale, typically +1.0 -float Envelope::ValueOfPixel( int y, int height, bool upper, bool dB, +float Envelope::ValueOfPixel( int y, int height, bool upper, + const ZoomInfo &zoomInfo, bool dB, float zoomMin, float zoomMax) { double dBRange = 0; if (dB) - // TODO: Cache the gPrefs value. Reading it every time is inefficient. - dBRange = gPrefs->Read(wxT("/GUI/EnvdBRange"), ENV_DB_RANGE); + dBRange = zoomInfo.dBr; float v = ::ValueOfPixel(y, height, 0 != mContourOffset, dB, dBRange, zoomMin, zoomMax); @@ -368,8 +349,7 @@ bool Envelope::HandleMouseButtonDown(wxMouseEvent & event, wxRect & r, int bestNum = -1; int bestDistSqr = 100; // Must be within 10 pixel radius. - // TODO: Cache the gPrefs value. Reading it every time is inefficient. - double dBr = gPrefs->Read(wxT("/GUI/EnvdBRange"), ENV_DB_RANGE); + double dBr = zoomInfo.dBr; // Member variables hold state that will be needed in dragging. mButton = event.GetButton(); @@ -457,7 +437,7 @@ bool Envelope::HandleMouseButtonDown(wxMouseEvent & event, wxRect & r, mContourOffset = false; } - double newVal = ValueOfPixel(clip_y, r.height, upper, dB, + double newVal = ValueOfPixel(clip_y, r.height, upper, zoomInfo, dB, zoomMin, zoomMax); mDragPoint = Insert(when - mOffset, newVal); @@ -508,7 +488,7 @@ void Envelope::MoveDraggedPoint( wxMouseEvent & event, wxRect & r, int clip_y = event.m_y - r.y; if(clip_y < 0) clip_y = 0; if(clip_y > r.height) clip_y = r.height; - double newVal = ValueOfPixel(clip_y, r.height, mUpper, dB, + double newVal = ValueOfPixel(clip_y, r.height, mUpper, zoomInfo, dB, zoomMin, zoomMax); // We no longer tolerate multiple envelope points at the same t. diff --git a/src/Envelope.h b/src/Envelope.h index 508c5c76d07d4ad813fb3b8d760c3ff41de1fcb8..c4c08b3e241ca19cef33b7ee92a7843ca439b60a 100644 --- a/src/Envelope.h +++ b/src/Envelope.h @@ -31,8 +31,6 @@ class Envelope; class ZoomInfo; -#define ENV_DB_RANGE 60 - class EnvPoint : public XMLTagHandler { public: @@ -197,10 +195,10 @@ class Envelope : public XMLTagHandler { int bufferLen) const; private: - double toDB(double x); EnvPoint * AddPointAtEnd( double t, double val ); void MarkDragPointForDeletion(); - float ValueOfPixel( int y, int height, bool upper, bool dB, + float ValueOfPixel( int y, int height, bool upper, + const ZoomInfo &zoomInfo, bool dB, float zoomMin, float zoomMax); void BinarySearchForTime( int &Lo, int &Hi, double t ) const; double GetInterpolationStartValueAtPoint( int iPoint ) const; diff --git a/src/FFT.cpp b/src/FFT.cpp index c64535e0f6c74822ecc19504cc1b016dfcc717b9..af1217bf77273a3c871df1dd1be92f4340734dc9 100644 --- a/src/FFT.cpp +++ b/src/FFT.cpp @@ -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; diff --git a/src/FFT.h b/src/FFT.h index 0713441c24086b6a8330158d308de03d6ecb5960..80de2b398d00ff857e55dbd582e3a39fae9976d6 100644 --- a/src/FFT.h +++ b/src/FFT.h @@ -32,6 +32,8 @@ #ifndef __AUDACITY_FFT_H__ #define __AUDACITY_FFT_H__ +#include <wx/defs.h> + /* Salvo Ventura - November 2006 Added more window functions: diff --git a/src/FFmpeg.h b/src/FFmpeg.h index 79cd36261b9ee5707417dccc27047d7bae59e527..aef40ae8b10373fe29fbb47ac7d3913af8ca7c33 100644 --- a/src/FFmpeg.h +++ b/src/FFmpeg.h @@ -128,6 +128,8 @@ extern "C" { #endif #include "Audacity.h" +#include "Experimental.h" + /* rather earlier than normal, but pulls in config*.h and other program stuff * we need for the next bit */ #include <wx/string.h> @@ -141,10 +143,8 @@ extern "C" { #include "Prefs.h" #include <wx/checkbox.h> #include <wx/textctrl.h> -// needed for sampleCount -#include "Sequence.h" -#include "Experimental.h" +#include "audacity/Types.h" // if you needed them, any other audacity header files would go here diff --git a/src/FreqWindow.cpp b/src/FreqWindow.cpp index 3b865e36e72d362795a2ab4ff727facae57b92a6..b793b9f34632014b381ddb3035698d2f1d6390cf 100644 --- a/src/FreqWindow.cpp +++ b/src/FreqWindow.cpp @@ -43,6 +43,8 @@ and in the spectrogram spectral selection. #include "Audacity.h" #include "FreqWindow.h" +#include <algorithm> + #include <wx/brush.h> #include <wx/button.h> #include <wx/choice.h> @@ -67,6 +69,7 @@ and in the spectrogram spectral selection. #include "FFT.h" #include "Internat.h" #include "PitchName.h" +#include "prefs/GUISettings.h" #include "Prefs.h" #include "Project.h" #include "WaveClip.h" @@ -75,10 +78,7 @@ and in the spectrogram spectral selection. #include "FileDialog.h" -//#if defined(__WXGTK__) -//#define GSocket GSocketHack -//#include <gtk/gtk.h> -//#endif +#include "WaveTrack.h" DEFINE_EVENT_TYPE(EVT_FREQWINDOW_RECALC); @@ -253,7 +253,7 @@ FreqWindow::FreqWindow(wxWindow * parent, wxWindowID id, gPrefs->Read(wxT("/FreqWindow/FuncChoice"), &mFunc, 3); gPrefs->Read(wxT("/FreqWindow/AxisChoice"), &mAxis, 0); - gPrefs->Read(wxT("/GUI/EnvdBRange"), &dBRange, ENV_DB_RANGE); + gPrefs->Read(ENV_DB_KEY, &dBRange, ENV_DB_RANGE); if(dBRange < 90.) dBRange = 90.; @@ -534,7 +534,7 @@ bool FreqWindow::Show(bool show) if (show && !shown) { - gPrefs->Read(wxT("/GUI/EnvdBRange"), &dBRange, ENV_DB_RANGE); + gPrefs->Read(ENV_DB_KEY, &dBRange, ENV_DB_RANGE); if(dBRange < 90.) dBRange = 90.; GetAudio(); @@ -1067,7 +1067,7 @@ void FreqWindow::OnExport(wxCommandEvent & WXUNUSED(event)) void FreqWindow::OnReplot(wxCommandEvent & WXUNUSED(event)) { - gPrefs->Read(wxT("/GUI/EnvdBRange"), &dBRange, ENV_DB_RANGE); + gPrefs->Read(ENV_DB_KEY, &dBRange, ENV_DB_RANGE); if(dBRange < 90.) dBRange = 90.; GetAudio(); diff --git a/src/LabelDialog.cpp b/src/LabelDialog.cpp index 5907816930d0bc6e3277c53218ad1134fe36602a..64624127c8f4a47f6bf3508fde5641d01af3926b 100644 --- a/src/LabelDialog.cpp +++ b/src/LabelDialog.cpp @@ -35,7 +35,6 @@ #include "LabelTrack.h" #include "Prefs.h" #include "Project.h" -#include "Track.h" #include "ViewInfo.h" #include "widgets/NumericTextCtrl.h" diff --git a/src/LyricsWindow.cpp b/src/LyricsWindow.cpp index 1424521e88862dbc3a551456dab120e38b3e35a2..7d2acad4ef210403d793e6770ce445d116c74c9c 100644 --- a/src/LyricsWindow.cpp +++ b/src/LyricsWindow.cpp @@ -13,7 +13,9 @@ #include "LyricsWindow.h" #include "Lyrics.h" +#include "AudioIO.h" #include "Project.h" +#include "TrackPanel.h" // for EVT_TRACK_PANEL_TIMER #include <wx/radiobut.h> #include <wx/toolbar.h> @@ -123,10 +125,21 @@ LyricsWindow::LyricsWindow(AudacityProject *parent): // default: // pRadioButton_Highlight->SetValue(true); break; //} + + // Events from the project don't propagate directly to this other frame, so... + mProject->Connect(EVT_TRACK_PANEL_TIMER, + wxCommandEventHandler(LyricsWindow::OnTimer), + NULL, + this); } LyricsWindow::~LyricsWindow() -{} +{ + mProject->Disconnect(EVT_TRACK_PANEL_TIMER, + wxCommandEventHandler(LyricsWindow::OnTimer), + NULL, + this); +} void LyricsWindow::OnCloseWindow(wxCloseEvent & WXUNUSED(event)) { @@ -143,3 +156,18 @@ void LyricsWindow::OnStyle_Highlight(wxCommandEvent & WXUNUSED(event)) mLyricsPanel->SetLyricsStyle(Lyrics::kHighlightLyrics); } +void LyricsWindow::OnTimer(wxCommandEvent &event) +{ + if (mProject->IsAudioActive()) + { + GetLyricsPanel()->Update(gAudioIO->GetStreamTime()); + } + else + { + // Reset lyrics display. + GetLyricsPanel()->Update(mProject->GetSel0()); + } + + // Let other listeners get the notification + event.Skip(); +} diff --git a/src/LyricsWindow.h b/src/LyricsWindow.h index d0afd19d7635d2050e2235516662fc10be116c02..1334ae33ff36c6fc9ab7dc5cd8d59a9a63b00a60 100644 --- a/src/LyricsWindow.h +++ b/src/LyricsWindow.h @@ -32,6 +32,7 @@ class LyricsWindow : public wxFrame { void OnStyle_BouncingBall(wxCommandEvent &evt); void OnStyle_Highlight(wxCommandEvent &evt); + void OnTimer(wxCommandEvent &event); AudacityProject *mProject; Lyrics *mLyricsPanel; diff --git a/src/Makefile.am b/src/Makefile.am index 3953208c89e8e698f1c33525edaf3042e74bcb3d..c5370f4b2a0ab8e4e26c4b44fd8dd63f36c6f6af 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -169,6 +169,7 @@ audacity_SOURCES = \ MixerBoard.h \ ModuleManager.cpp \ ModuleManager.h \ + NumberScale.h \ PitchName.cpp \ PitchName.h \ PlatformCompatibility.cpp \ @@ -239,6 +240,7 @@ audacity_SOURCES = \ WaveClip.h \ WaveTrack.cpp \ WaveTrack.h \ + WaveTrackLocation.h \ WrappedType.cpp \ WrappedType.h \ commands/AppCommandEvent.cpp \ @@ -452,6 +454,7 @@ audacity_SOURCES = \ prefs/ExtImportPrefs.h \ prefs/GUIPrefs.cpp \ prefs/GUIPrefs.h \ + prefs/GUISettings.h \ prefs/ImportExportPrefs.cpp \ prefs/ImportExportPrefs.h \ prefs/KeyConfigPrefs.cpp \ @@ -475,6 +478,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 \ @@ -483,6 +488,10 @@ audacity_SOURCES = \ prefs/TracksPrefs.h \ prefs/WarningsPrefs.cpp \ prefs/WarningsPrefs.h \ + prefs/WaveformPrefs.cpp \ + prefs/WaveformPrefs.h \ + prefs/WaveformSettings.cpp \ + prefs/WaveformSettings.h \ toolbars/ControlToolBar.cpp \ toolbars/ControlToolBar.h \ toolbars/DeviceToolBar.cpp \ diff --git a/src/Makefile.in b/src/Makefile.in index d92565e8e970ff79e77499888b5ed9f4a17f0cc9..8f4c37dc254f3f13afe67f78b663ab795a6c02e6 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -301,17 +301,17 @@ am__audacity_SOURCES_DIST = BlockFile.cpp BlockFile.h DirManager.cpp \ Lyrics.h LyricsWindow.cpp LyricsWindow.h MacroMagic.h \ Matrix.cpp Matrix.h Menus.cpp Menus.h Mix.cpp Mix.h \ MixerBoard.cpp MixerBoard.h ModuleManager.cpp ModuleManager.h \ - PitchName.cpp PitchName.h PlatformCompatibility.cpp \ - PlatformCompatibility.h PluginManager.cpp PluginManager.h \ - Printing.cpp Printing.h Profiler.cpp Profiler.h Project.cpp \ - Project.h RealFFTf.cpp RealFFTf.h RealFFTf48x.cpp \ - RealFFTf48x.h Resample.cpp Resample.h RevisionIdent.h \ - RingBuffer.cpp RingBuffer.h Screenshot.cpp Screenshot.h \ - SelectedRegion.cpp SelectedRegion.h Shuttle.cpp Shuttle.h \ - ShuttleGui.cpp ShuttleGui.h ShuttlePrefs.cpp ShuttlePrefs.h \ - Snap.cpp Snap.h SoundActivatedRecord.cpp \ - SoundActivatedRecord.h Spectrum.cpp Spectrum.h \ - SplashDialog.cpp SplashDialog.h SseMathFuncs.cpp \ + NumberScale.h PitchName.cpp PitchName.h \ + PlatformCompatibility.cpp PlatformCompatibility.h \ + PluginManager.cpp PluginManager.h Printing.cpp Printing.h \ + Profiler.cpp Profiler.h Project.cpp Project.h RealFFTf.cpp \ + RealFFTf.h RealFFTf48x.cpp RealFFTf48x.h Resample.cpp \ + Resample.h RevisionIdent.h RingBuffer.cpp RingBuffer.h \ + Screenshot.cpp Screenshot.h SelectedRegion.cpp \ + SelectedRegion.h Shuttle.cpp Shuttle.h ShuttleGui.cpp \ + ShuttleGui.h ShuttlePrefs.cpp ShuttlePrefs.h Snap.cpp Snap.h \ + SoundActivatedRecord.cpp SoundActivatedRecord.h Spectrum.cpp \ + Spectrum.h SplashDialog.cpp SplashDialog.h SseMathFuncs.cpp \ SseMathFuncs.h Tags.cpp Tags.h Theme.cpp Theme.h \ ThemeAsCeeCode.h TimeDialog.cpp TimeDialog.h \ TimerRecordDialog.cpp TimerRecordDialog.h TimeTrack.cpp \ @@ -319,7 +319,7 @@ am__audacity_SOURCES_DIST = BlockFile.cpp BlockFile.h DirManager.cpp \ TrackPanel.cpp TrackPanel.h TrackPanelAx.cpp TrackPanelAx.h \ UndoManager.cpp UndoManager.h ViewInfo.cpp ViewInfo.h \ VoiceKey.cpp VoiceKey.h WaveClip.cpp WaveClip.h WaveTrack.cpp \ - WaveTrack.h WrappedType.cpp WrappedType.h \ + WaveTrack.h WaveTrackLocation.h WrappedType.cpp WrappedType.h \ commands/AppCommandEvent.cpp commands/AppCommandEvent.h \ commands/BatchEvalCommand.cpp commands/BatchEvalCommand.h \ commands/Command.cpp commands/Command.h \ @@ -416,7 +416,7 @@ am__audacity_SOURCES_DIST = BlockFile.cpp BlockFile.h DirManager.cpp \ prefs/DirectoriesPrefs.cpp prefs/DirectoriesPrefs.h \ prefs/EffectsPrefs.cpp prefs/EffectsPrefs.h \ prefs/ExtImportPrefs.cpp prefs/ExtImportPrefs.h \ - prefs/GUIPrefs.cpp prefs/GUIPrefs.h \ + prefs/GUIPrefs.cpp prefs/GUIPrefs.h prefs/GUISettings.h \ prefs/ImportExportPrefs.cpp prefs/ImportExportPrefs.h \ prefs/KeyConfigPrefs.cpp prefs/KeyConfigPrefs.h \ prefs/LibraryPrefs.cpp prefs/LibraryPrefs.h \ @@ -427,10 +427,13 @@ am__audacity_SOURCES_DIST = BlockFile.cpp BlockFile.h DirManager.cpp \ prefs/PrefsDialog.h prefs/PrefsPanel.h prefs/ProjectsPrefs.cpp \ prefs/ProjectsPrefs.h prefs/QualityPrefs.cpp \ prefs/QualityPrefs.h prefs/RecordingPrefs.cpp \ - prefs/RecordingPrefs.h prefs/SpectrumPrefs.cpp \ + prefs/RecordingPrefs.h prefs/SpectrogramSettings.cpp \ + prefs/SpectrogramSettings.h prefs/SpectrumPrefs.cpp \ prefs/SpectrumPrefs.h prefs/ThemePrefs.cpp prefs/ThemePrefs.h \ prefs/TracksPrefs.cpp prefs/TracksPrefs.h \ prefs/WarningsPrefs.cpp prefs/WarningsPrefs.h \ + prefs/WaveformPrefs.cpp prefs/WaveformPrefs.h \ + prefs/WaveformSettings.cpp prefs/WaveformSettings.h \ toolbars/ControlToolBar.cpp toolbars/ControlToolBar.h \ toolbars/DeviceToolBar.cpp toolbars/DeviceToolBar.h \ toolbars/EditToolBar.cpp toolbars/EditToolBar.h \ @@ -675,10 +678,13 @@ am_audacity_OBJECTS = $(am__objects_1) audacity-AboutDialog.$(OBJEXT) \ prefs/audacity-ProjectsPrefs.$(OBJEXT) \ prefs/audacity-QualityPrefs.$(OBJEXT) \ prefs/audacity-RecordingPrefs.$(OBJEXT) \ + prefs/audacity-SpectrogramSettings.$(OBJEXT) \ prefs/audacity-SpectrumPrefs.$(OBJEXT) \ prefs/audacity-ThemePrefs.$(OBJEXT) \ prefs/audacity-TracksPrefs.$(OBJEXT) \ prefs/audacity-WarningsPrefs.$(OBJEXT) \ + prefs/audacity-WaveformPrefs.$(OBJEXT) \ + prefs/audacity-WaveformSettings.$(OBJEXT) \ toolbars/audacity-ControlToolBar.$(OBJEXT) \ toolbars/audacity-DeviceToolBar.$(OBJEXT) \ toolbars/audacity-EditToolBar.$(OBJEXT) \ @@ -1164,17 +1170,17 @@ audacity_SOURCES = $(libaudacity_la_SOURCES) AboutDialog.cpp \ Lyrics.h LyricsWindow.cpp LyricsWindow.h MacroMagic.h \ Matrix.cpp Matrix.h Menus.cpp Menus.h Mix.cpp Mix.h \ MixerBoard.cpp MixerBoard.h ModuleManager.cpp ModuleManager.h \ - PitchName.cpp PitchName.h PlatformCompatibility.cpp \ - PlatformCompatibility.h PluginManager.cpp PluginManager.h \ - Printing.cpp Printing.h Profiler.cpp Profiler.h Project.cpp \ - Project.h RealFFTf.cpp RealFFTf.h RealFFTf48x.cpp \ - RealFFTf48x.h Resample.cpp Resample.h RevisionIdent.h \ - RingBuffer.cpp RingBuffer.h Screenshot.cpp Screenshot.h \ - SelectedRegion.cpp SelectedRegion.h Shuttle.cpp Shuttle.h \ - ShuttleGui.cpp ShuttleGui.h ShuttlePrefs.cpp ShuttlePrefs.h \ - Snap.cpp Snap.h SoundActivatedRecord.cpp \ - SoundActivatedRecord.h Spectrum.cpp Spectrum.h \ - SplashDialog.cpp SplashDialog.h SseMathFuncs.cpp \ + NumberScale.h PitchName.cpp PitchName.h \ + PlatformCompatibility.cpp PlatformCompatibility.h \ + PluginManager.cpp PluginManager.h Printing.cpp Printing.h \ + Profiler.cpp Profiler.h Project.cpp Project.h RealFFTf.cpp \ + RealFFTf.h RealFFTf48x.cpp RealFFTf48x.h Resample.cpp \ + Resample.h RevisionIdent.h RingBuffer.cpp RingBuffer.h \ + Screenshot.cpp Screenshot.h SelectedRegion.cpp \ + SelectedRegion.h Shuttle.cpp Shuttle.h ShuttleGui.cpp \ + ShuttleGui.h ShuttlePrefs.cpp ShuttlePrefs.h Snap.cpp Snap.h \ + SoundActivatedRecord.cpp SoundActivatedRecord.h Spectrum.cpp \ + Spectrum.h SplashDialog.cpp SplashDialog.h SseMathFuncs.cpp \ SseMathFuncs.h Tags.cpp Tags.h Theme.cpp Theme.h \ ThemeAsCeeCode.h TimeDialog.cpp TimeDialog.h \ TimerRecordDialog.cpp TimerRecordDialog.h TimeTrack.cpp \ @@ -1182,7 +1188,7 @@ audacity_SOURCES = $(libaudacity_la_SOURCES) AboutDialog.cpp \ TrackPanel.cpp TrackPanel.h TrackPanelAx.cpp TrackPanelAx.h \ UndoManager.cpp UndoManager.h ViewInfo.cpp ViewInfo.h \ VoiceKey.cpp VoiceKey.h WaveClip.cpp WaveClip.h WaveTrack.cpp \ - WaveTrack.h WrappedType.cpp WrappedType.h \ + WaveTrack.h WaveTrackLocation.h WrappedType.cpp WrappedType.h \ commands/AppCommandEvent.cpp commands/AppCommandEvent.h \ commands/BatchEvalCommand.cpp commands/BatchEvalCommand.h \ commands/Command.cpp commands/Command.h \ @@ -1279,7 +1285,7 @@ audacity_SOURCES = $(libaudacity_la_SOURCES) AboutDialog.cpp \ prefs/DirectoriesPrefs.cpp prefs/DirectoriesPrefs.h \ prefs/EffectsPrefs.cpp prefs/EffectsPrefs.h \ prefs/ExtImportPrefs.cpp prefs/ExtImportPrefs.h \ - prefs/GUIPrefs.cpp prefs/GUIPrefs.h \ + prefs/GUIPrefs.cpp prefs/GUIPrefs.h prefs/GUISettings.h \ prefs/ImportExportPrefs.cpp prefs/ImportExportPrefs.h \ prefs/KeyConfigPrefs.cpp prefs/KeyConfigPrefs.h \ prefs/LibraryPrefs.cpp prefs/LibraryPrefs.h \ @@ -1290,10 +1296,13 @@ audacity_SOURCES = $(libaudacity_la_SOURCES) AboutDialog.cpp \ prefs/PrefsDialog.h prefs/PrefsPanel.h prefs/ProjectsPrefs.cpp \ prefs/ProjectsPrefs.h prefs/QualityPrefs.cpp \ prefs/QualityPrefs.h prefs/RecordingPrefs.cpp \ - prefs/RecordingPrefs.h prefs/SpectrumPrefs.cpp \ + prefs/RecordingPrefs.h prefs/SpectrogramSettings.cpp \ + prefs/SpectrogramSettings.h prefs/SpectrumPrefs.cpp \ prefs/SpectrumPrefs.h prefs/ThemePrefs.cpp prefs/ThemePrefs.h \ prefs/TracksPrefs.cpp prefs/TracksPrefs.h \ prefs/WarningsPrefs.cpp prefs/WarningsPrefs.h \ + prefs/WaveformPrefs.cpp prefs/WaveformPrefs.h \ + prefs/WaveformSettings.cpp prefs/WaveformSettings.h \ toolbars/ControlToolBar.cpp toolbars/ControlToolBar.h \ toolbars/DeviceToolBar.cpp toolbars/DeviceToolBar.h \ toolbars/EditToolBar.cpp toolbars/EditToolBar.h \ @@ -1377,8 +1386,8 @@ $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) $(am__aclocal_m4_deps): configwin.h: stamp-h1 - @test -f $@ || rm -f stamp-h1 - @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 + @if test ! -f $@; then rm -f stamp-h1; else :; fi + @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) stamp-h1; else :; fi stamp-h1: $(srcdir)/configtemplate.h $(top_builddir)/config.status @rm -f stamp-h1 @@ -1389,8 +1398,8 @@ $(srcdir)/configtemplate.h: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) touch $@ configunix.h: stamp-h2 - @test -f $@ || rm -f stamp-h2 - @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h2 + @if test ! -f $@; then rm -f stamp-h2; else :; fi + @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) stamp-h2; else :; fi stamp-h2: $(srcdir)/configtemplate.h $(top_builddir)/config.status @rm -f stamp-h2 @@ -1771,6 +1780,8 @@ prefs/audacity-QualityPrefs.$(OBJEXT): prefs/$(am__dirstamp) \ prefs/$(DEPDIR)/$(am__dirstamp) prefs/audacity-RecordingPrefs.$(OBJEXT): prefs/$(am__dirstamp) \ prefs/$(DEPDIR)/$(am__dirstamp) +prefs/audacity-SpectrogramSettings.$(OBJEXT): prefs/$(am__dirstamp) \ + prefs/$(DEPDIR)/$(am__dirstamp) prefs/audacity-SpectrumPrefs.$(OBJEXT): prefs/$(am__dirstamp) \ prefs/$(DEPDIR)/$(am__dirstamp) prefs/audacity-ThemePrefs.$(OBJEXT): prefs/$(am__dirstamp) \ @@ -1779,6 +1790,10 @@ prefs/audacity-TracksPrefs.$(OBJEXT): prefs/$(am__dirstamp) \ prefs/$(DEPDIR)/$(am__dirstamp) prefs/audacity-WarningsPrefs.$(OBJEXT): prefs/$(am__dirstamp) \ prefs/$(DEPDIR)/$(am__dirstamp) +prefs/audacity-WaveformPrefs.$(OBJEXT): prefs/$(am__dirstamp) \ + prefs/$(DEPDIR)/$(am__dirstamp) +prefs/audacity-WaveformSettings.$(OBJEXT): prefs/$(am__dirstamp) \ + prefs/$(DEPDIR)/$(am__dirstamp) toolbars/$(am__dirstamp): @$(MKDIR_P) toolbars @: > toolbars/$(am__dirstamp) @@ -2200,10 +2215,13 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@prefs/$(DEPDIR)/audacity-ProjectsPrefs.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@prefs/$(DEPDIR)/audacity-QualityPrefs.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@prefs/$(DEPDIR)/audacity-RecordingPrefs.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@prefs/$(DEPDIR)/audacity-SpectrogramSettings.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@prefs/$(DEPDIR)/audacity-SpectrumPrefs.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@prefs/$(DEPDIR)/audacity-ThemePrefs.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@prefs/$(DEPDIR)/audacity-TracksPrefs.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@prefs/$(DEPDIR)/audacity-WarningsPrefs.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@prefs/$(DEPDIR)/audacity-WaveformPrefs.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@prefs/$(DEPDIR)/audacity-WaveformSettings.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@toolbars/$(DEPDIR)/audacity-ControlToolBar.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@toolbars/$(DEPDIR)/audacity-DeviceToolBar.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@toolbars/$(DEPDIR)/audacity-EditToolBar.Po@am__quote@ @@ -5192,6 +5210,20 @@ prefs/audacity-RecordingPrefs.obj: prefs/RecordingPrefs.cpp @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -c -o prefs/audacity-RecordingPrefs.obj `if test -f 'prefs/RecordingPrefs.cpp'; then $(CYGPATH_W) 'prefs/RecordingPrefs.cpp'; else $(CYGPATH_W) '$(srcdir)/prefs/RecordingPrefs.cpp'; fi` +prefs/audacity-SpectrogramSettings.o: prefs/SpectrogramSettings.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -MT prefs/audacity-SpectrogramSettings.o -MD -MP -MF prefs/$(DEPDIR)/audacity-SpectrogramSettings.Tpo -c -o prefs/audacity-SpectrogramSettings.o `test -f 'prefs/SpectrogramSettings.cpp' || echo '$(srcdir)/'`prefs/SpectrogramSettings.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) prefs/$(DEPDIR)/audacity-SpectrogramSettings.Tpo prefs/$(DEPDIR)/audacity-SpectrogramSettings.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='prefs/SpectrogramSettings.cpp' object='prefs/audacity-SpectrogramSettings.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -c -o prefs/audacity-SpectrogramSettings.o `test -f 'prefs/SpectrogramSettings.cpp' || echo '$(srcdir)/'`prefs/SpectrogramSettings.cpp + +prefs/audacity-SpectrogramSettings.obj: prefs/SpectrogramSettings.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -MT prefs/audacity-SpectrogramSettings.obj -MD -MP -MF prefs/$(DEPDIR)/audacity-SpectrogramSettings.Tpo -c -o prefs/audacity-SpectrogramSettings.obj `if test -f 'prefs/SpectrogramSettings.cpp'; then $(CYGPATH_W) 'prefs/SpectrogramSettings.cpp'; else $(CYGPATH_W) '$(srcdir)/prefs/SpectrogramSettings.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) prefs/$(DEPDIR)/audacity-SpectrogramSettings.Tpo prefs/$(DEPDIR)/audacity-SpectrogramSettings.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='prefs/SpectrogramSettings.cpp' object='prefs/audacity-SpectrogramSettings.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -c -o prefs/audacity-SpectrogramSettings.obj `if test -f 'prefs/SpectrogramSettings.cpp'; then $(CYGPATH_W) 'prefs/SpectrogramSettings.cpp'; else $(CYGPATH_W) '$(srcdir)/prefs/SpectrogramSettings.cpp'; fi` + prefs/audacity-SpectrumPrefs.o: prefs/SpectrumPrefs.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -MT prefs/audacity-SpectrumPrefs.o -MD -MP -MF prefs/$(DEPDIR)/audacity-SpectrumPrefs.Tpo -c -o prefs/audacity-SpectrumPrefs.o `test -f 'prefs/SpectrumPrefs.cpp' || echo '$(srcdir)/'`prefs/SpectrumPrefs.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) prefs/$(DEPDIR)/audacity-SpectrumPrefs.Tpo prefs/$(DEPDIR)/audacity-SpectrumPrefs.Po @@ -5248,6 +5280,34 @@ prefs/audacity-WarningsPrefs.obj: prefs/WarningsPrefs.cpp @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -c -o prefs/audacity-WarningsPrefs.obj `if test -f 'prefs/WarningsPrefs.cpp'; then $(CYGPATH_W) 'prefs/WarningsPrefs.cpp'; else $(CYGPATH_W) '$(srcdir)/prefs/WarningsPrefs.cpp'; fi` +prefs/audacity-WaveformPrefs.o: prefs/WaveformPrefs.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -MT prefs/audacity-WaveformPrefs.o -MD -MP -MF prefs/$(DEPDIR)/audacity-WaveformPrefs.Tpo -c -o prefs/audacity-WaveformPrefs.o `test -f 'prefs/WaveformPrefs.cpp' || echo '$(srcdir)/'`prefs/WaveformPrefs.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) prefs/$(DEPDIR)/audacity-WaveformPrefs.Tpo prefs/$(DEPDIR)/audacity-WaveformPrefs.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='prefs/WaveformPrefs.cpp' object='prefs/audacity-WaveformPrefs.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -c -o prefs/audacity-WaveformPrefs.o `test -f 'prefs/WaveformPrefs.cpp' || echo '$(srcdir)/'`prefs/WaveformPrefs.cpp + +prefs/audacity-WaveformPrefs.obj: prefs/WaveformPrefs.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -MT prefs/audacity-WaveformPrefs.obj -MD -MP -MF prefs/$(DEPDIR)/audacity-WaveformPrefs.Tpo -c -o prefs/audacity-WaveformPrefs.obj `if test -f 'prefs/WaveformPrefs.cpp'; then $(CYGPATH_W) 'prefs/WaveformPrefs.cpp'; else $(CYGPATH_W) '$(srcdir)/prefs/WaveformPrefs.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) prefs/$(DEPDIR)/audacity-WaveformPrefs.Tpo prefs/$(DEPDIR)/audacity-WaveformPrefs.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='prefs/WaveformPrefs.cpp' object='prefs/audacity-WaveformPrefs.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -c -o prefs/audacity-WaveformPrefs.obj `if test -f 'prefs/WaveformPrefs.cpp'; then $(CYGPATH_W) 'prefs/WaveformPrefs.cpp'; else $(CYGPATH_W) '$(srcdir)/prefs/WaveformPrefs.cpp'; fi` + +prefs/audacity-WaveformSettings.o: prefs/WaveformSettings.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -MT prefs/audacity-WaveformSettings.o -MD -MP -MF prefs/$(DEPDIR)/audacity-WaveformSettings.Tpo -c -o prefs/audacity-WaveformSettings.o `test -f 'prefs/WaveformSettings.cpp' || echo '$(srcdir)/'`prefs/WaveformSettings.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) prefs/$(DEPDIR)/audacity-WaveformSettings.Tpo prefs/$(DEPDIR)/audacity-WaveformSettings.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='prefs/WaveformSettings.cpp' object='prefs/audacity-WaveformSettings.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -c -o prefs/audacity-WaveformSettings.o `test -f 'prefs/WaveformSettings.cpp' || echo '$(srcdir)/'`prefs/WaveformSettings.cpp + +prefs/audacity-WaveformSettings.obj: prefs/WaveformSettings.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -MT prefs/audacity-WaveformSettings.obj -MD -MP -MF prefs/$(DEPDIR)/audacity-WaveformSettings.Tpo -c -o prefs/audacity-WaveformSettings.obj `if test -f 'prefs/WaveformSettings.cpp'; then $(CYGPATH_W) 'prefs/WaveformSettings.cpp'; else $(CYGPATH_W) '$(srcdir)/prefs/WaveformSettings.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) prefs/$(DEPDIR)/audacity-WaveformSettings.Tpo prefs/$(DEPDIR)/audacity-WaveformSettings.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='prefs/WaveformSettings.cpp' object='prefs/audacity-WaveformSettings.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -c -o prefs/audacity-WaveformSettings.obj `if test -f 'prefs/WaveformSettings.cpp'; then $(CYGPATH_W) 'prefs/WaveformSettings.cpp'; else $(CYGPATH_W) '$(srcdir)/prefs/WaveformSettings.cpp'; fi` + toolbars/audacity-ControlToolBar.o: toolbars/ControlToolBar.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -MT toolbars/audacity-ControlToolBar.o -MD -MP -MF toolbars/$(DEPDIR)/audacity-ControlToolBar.Tpo -c -o toolbars/audacity-ControlToolBar.o `test -f 'toolbars/ControlToolBar.cpp' || echo '$(srcdir)/'`toolbars/ControlToolBar.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) toolbars/$(DEPDIR)/audacity-ControlToolBar.Tpo toolbars/$(DEPDIR)/audacity-ControlToolBar.Po diff --git a/src/Menus.cpp b/src/Menus.cpp index 3e2bc18f62a8d3c55b1dcb01bd1c927e4b8e1b22..b4665ed36026de7061499103471186dbd4adcaec 100644 --- a/src/Menus.cpp +++ b/src/Menus.cpp @@ -31,6 +31,7 @@ simplifies construction of menu items. *//*******************************************************************/ #include "Audacity.h" +#include "Project.h" #include <iterator> #include <limits> @@ -53,7 +54,6 @@ simplifies construction of menu items. #include "effects/Contrast.h" #include "TrackPanel.h" -#include "Project.h" #include "effects/EffectManager.h" #include "AudacityApp.h" @@ -119,6 +119,8 @@ simplifies construction of menu items. #include "Snap.h" +#include "WaveTrack.h" + #if defined(EXPERIMENTAL_CRASH_REPORT) #include <wx/debugrpt.h> #endif @@ -3551,7 +3553,7 @@ void AudacityProject::OnExportMultiple() void AudacityProject::OnPreferences() { - PrefsDialog dialog(this /* parent */ ); + GlobalPrefsDialog dialog(this /* parent */ ); if (!dialog.ShowModal()) { // Canceled @@ -4730,12 +4732,7 @@ void AudacityProject::DoNextPeakFrequency(bool up) for (Track *t = iter.First(); t; t = iter.Next()) { WaveTrack *const wt = static_cast<WaveTrack*>(t); const int display = wt->GetDisplay(); - if (display == WaveTrack::SpectrumDisplay || - display == WaveTrack::SpectrumLogDisplay || - display == WaveTrack::SpectralSelectionDisplay || - display == WaveTrack::SpectralSelectionLogDisplay - - ) { + if (display == WaveTrack::Spectrum) { pTrack = wt; break; } diff --git a/src/Mix.cpp b/src/Mix.cpp index 50fc1561494fc4178802ba4775e84930c3ded036..3ed5e4b7d3e625860fcf89d794f88df3e160cfd9 100644 --- a/src/Mix.cpp +++ b/src/Mix.cpp @@ -35,11 +35,11 @@ #include "WaveTrack.h" #include "DirManager.h" -#include "Envelope.h" #include "Internat.h" #include "Prefs.h" #include "Project.h" #include "Resample.h" +#include "TimeTrack.h" #include "float_cast.h" //TODO-MB: wouldn't it make more sense to delete the time track after 'mix and render'? diff --git a/src/Mix.h b/src/Mix.h index b4274d5898222a7d430116217802e152766da4b3..475ae6b3176e49da30cc3d4a9abcbc41a13af16a 100644 --- a/src/Mix.h +++ b/src/Mix.h @@ -15,11 +15,13 @@ #include <wx/string.h> #include "SampleFormat.h" -#include "WaveTrack.h" -#include "TimeTrack.h" #include "Resample.h" class DirManager; +class TimeTrack; +class TrackFactory; +class TrackList; +class WaveTrack; /** @brief Mixes together all input tracks, applying any envelopes, amplitude * gain, panning, and real-time effects in the process. diff --git a/src/MixerBoard.cpp b/src/MixerBoard.cpp index c6813ea21d1ee082ade6616e29e78cf8a9478706..b0f9ffaebe8cc694450b6ba3fe8567130002d280 100644 --- a/src/MixerBoard.cpp +++ b/src/MixerBoard.cpp @@ -10,8 +10,8 @@ **********************************************************************/ #include "Audacity.h" - #include "Experimental.h" +#include "MixerBoard.h" #include <math.h> @@ -22,12 +22,14 @@ #include "AColor.h" #include "AudioIO.h" -#include "MixerBoard.h" #ifdef EXPERIMENTAL_MIDI_OUT #include "NoteTrack.h" #endif #include "Project.h" -#include "Track.h" +#include "TrackPanel.h" // for EVT_TRACK_PANEL_TIMER +#include "WaveTrack.h" + +#include "widgets/Meter.h" #include "../images/MusicalInstruments.h" @@ -1015,6 +1017,12 @@ MixerBoard::MixerBoard(AudacityProject* pProject, mPrevT1 = 0.0; mTracks = mProject->GetTracks(); + + // Events from the project don't propagate directly to this other frame, so... + mProject->Connect(EVT_TRACK_PANEL_TIMER, + wxCommandEventHandler(MixerBoard::OnTimer), + NULL, + this); } MixerBoard::~MixerBoard() @@ -1032,6 +1040,11 @@ MixerBoard::~MixerBoard() // private data members mMusicalInstruments.Clear(); + + mProject->Disconnect(EVT_TRACK_PANEL_TIMER, + wxCommandEventHandler(MixerBoard::OnTimer), + NULL, + this); } // Reassign mixer input strips (MixerTrackClusters) to Track Clusters @@ -1691,6 +1704,30 @@ void MixerBoard::OnSize(wxSizeEvent &evt) this->RefreshTrackClusters(true); } +void MixerBoard::OnTimer(wxCommandEvent &event) +{ + // PRL 12 Jul 2015: Moved the below (with comments) out of TrackPanel::OnTimer. + + // Vaughan, 2011-01-28: No longer doing this on timer. + // Now it's in AudioIO::SetMeters() and AudioIO::StopStream(), as with Meter Toolbar meters. + //if (pMixerBoard) + // pMixerBoard->ResetMeters(false); + + //v Vaughan, 2011-02-25: Moved this update back here from audacityAudioCallback. + // See note there. + // Vaughan, 2010-01-30: + // Since all we're doing here is updating the meters, I moved it to + // audacityAudioCallback where it calls gAudioIO->mOutputMeter->UpdateDisplay(). + if (mProject->IsAudioActive()) + { + UpdateMeters(gAudioIO->GetStreamTime(), + (mProject->mLastPlayMode == loopedPlay)); + } + + // Let other listeners get the notification + event.Skip(); +} + // class MixerBoardFrame @@ -1759,5 +1796,3 @@ void MixerBoardFrame::OnSize(wxSizeEvent & WXUNUSED(event)) { mMixerBoard->SetSize(this->GetClientSize()); } - - diff --git a/src/MixerBoard.h b/src/MixerBoard.h index 057420226caf9e017f648404f2dd0c4cb900cb40..0d3ead754bd033df326931925fc2e42eb8823a2a 100644 --- a/src/MixerBoard.h +++ b/src/MixerBoard.h @@ -24,7 +24,6 @@ #include "widgets/AButton.h" #include "widgets/ASlider.h" -#include "widgets/Meter.h" // containment hierarchy: // MixerBoardFrame -> MixerBoard -> MixerBoardScrolledWindow -> MixerTrackCluster(s) @@ -45,7 +44,7 @@ public: bool canUseShift = true, float stepValue = STEP_CONTINUOUS, int orientation = wxHORIZONTAL); - virtual ~MixerTrackSlider() {}; + virtual ~MixerTrackSlider() {} void OnMouseEvent(wxMouseEvent & event); @@ -61,6 +60,7 @@ public: class AudacityProject; +class Meter; class MixerBoard; #ifdef EXPERIMENTAL_MIDI_OUT class Track; @@ -76,7 +76,7 @@ public: WaveTrack* pLeftTrack, WaveTrack* pRightTrack = NULL, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize); - virtual ~MixerTrackCluster() {}; + virtual ~MixerTrackCluster() {} void HandleResize(); // For wxSizeEvents, update gain slider and meter. @@ -265,6 +265,7 @@ private: // event handlers void OnSize(wxSizeEvent &evt); + void OnTimer(wxCommandEvent &event); public: diff --git a/src/NumberScale.h b/src/NumberScale.h new file mode 100644 index 0000000000000000000000000000000000000000..b68a557f5e62dc7846c44f93c4bc484c5edb8cec --- /dev/null +++ b/src/NumberScale.h @@ -0,0 +1,279 @@ +/********************************************************************** + +Audacity: A Digital Audio Editor + +NumberScale.h + +Paul Licameli + +**********************************************************************/ + +#ifndef __AUDACITY_NUMBER_SCALE__ +#define __AUDACITY_NUMBER_SCALE__ + +#include <algorithm> +#include <cmath> +#include <wx/defs.h> +#include <wx/debug.h> + +enum NumberScaleType { + nstLinear, + nstLogarithmic, + nstMel, + nstBark, + nstErb, + nstUndertone, + + nstNumScaleTypes, +}; + + +class NumberScale +{ +public: + NumberScale(NumberScaleType type, + float value0, float value1, float unit) + : mType(type) + { + switch (mType) { + case nstLinear: + { + mValue0 = value0 / unit; + mValue1 = value1 / unit; + mUnit = 1.0; + } + break; + case nstLogarithmic: + { + mValue0 = logf(value0 / unit); + mValue1 = logf(value1 / unit); + mUnit = 1.0; + } + break; + case nstMel: + { + mValue0 = hzToMel(value0); + mValue1 = hzToMel(value1); + mUnit = unit; + } + break; + case nstBark: + { + mValue0 = hzToBark(value0); + mValue1 = hzToBark(value1); + mUnit = unit; + } + break; + case nstErb: + { + mValue0 = hzToErb(value0); + mValue1 = hzToErb(value1); + mUnit = unit; + } + break; + case nstUndertone: + { + mValue0 = hzToUndertone(value0); + mValue1 = hzToUndertone(value1); + mUnit = unit; + } + break; + default: + wxASSERT(false); + } + } + + NumberScale Reversal() const + { + NumberScale result(*this); + std::swap(result.mValue0, result.mValue1); + return result; + } + + bool operator == (const NumberScale& other) const + { + return mType == other.mType + && mValue0 == other.mValue0 + && mValue1 == other.mValue1 + && mUnit == other.mUnit; + } + + bool operator != (const NumberScale &other) const + { + return !(*this == other); + } + + static inline float hzToMel(float hz) + { + return 1127 * log(1 + hz / 700); + } + + static inline float melToHz(float mel) + { + return 700 * (exp(mel / 1127) - 1); + } + + static inline float hzToBark(float hz) + { + // Traunmueller's formula + const float z1 = 26.81 * hz / (1960 + hz) - 0.53; + if (z1 < 2.0) + return z1 + 0.15 * (2.0 - z1); + else if (z1 > 20.1) + return z1 + 0.22 * (z1 - 20.1); + else + return z1; + } + + static inline float barkToHz(float z1) + { + if (z1 < 2.0) + z1 = 2.0 + (z1 - 2.0) / 0.85; + else if (z1 > 20.1) + z1 = 20.1 + (z1 - 20.1) / 1.22; + return 1960 * (z1 + 0.53) / (26.28 - z1); + } + + static inline float hzToErb(float hz) + { + return 11.17268 * log(1 + (46.06538 * hz) / (hz + 14678.49)); + } + + static inline float erbToHz(float erb) + { + return 676170.4 / (47.06538 - exp(0.08950404 * erb)) - 14678.49; + } + + static inline float hzToUndertone(float hz) + { + return -1.0 / std::max (1.0f, hz); + } + + static inline float undertoneToHz(float u) + { + return -1.0 / u; + } + + // Random access + float PositionToValue(float pp) const + { + switch (mType) { + default: + wxASSERT(false); + case nstLinear: + return mValue0 + pp * (mValue1 - mValue0); + case nstLogarithmic: + return exp(mValue0 + pp * (mValue1 - mValue0)); + case nstMel: + return melToHz(mValue0 + pp * (mValue1 - mValue0)) / mUnit; + case nstBark: + return barkToHz(mValue0 + pp * (mValue1 - mValue0)) / mUnit; + case nstErb: + return erbToHz(mValue0 + pp * (mValue1 - mValue0)) / mUnit; + case nstUndertone: + return undertoneToHz(mValue0 + pp * (mValue1 - mValue0)) / mUnit; + } + } + + // STL-idiom iteration + + class Iterator + { + public: + Iterator(NumberScaleType type, float step, float value, float unit) + : mType(type), mStep(step), mValue(value), mUnit(unit) + { + } + + float operator * () const + { + switch (mType) { + default: + wxASSERT(false); + case nstLinear: + case nstLogarithmic: + return mValue; + case nstMel: + return melToHz(mValue) / mUnit; + case nstBark: + return barkToHz(mValue) / mUnit; + case nstErb: + return erbToHz(mValue) / mUnit; + case nstUndertone: + return undertoneToHz(mValue) / mUnit; + } + } + + Iterator &operator ++() + { + switch (mType) { + case nstLinear: + case nstMel: + case nstBark: + case nstErb: + case nstUndertone: + mValue += mStep; + break; + case nstLogarithmic: + mValue *= mStep; + break; + default: + wxASSERT(false); + } + return *this; + } + + private: + const NumberScaleType mType; + const float mStep; + float mValue; + float mUnit; + }; + + Iterator begin(float nPositions) const + { + switch (mType) { + default: + wxASSERT(false); + case nstLinear: + case nstMel: + case nstBark: + case nstErb: + case nstUndertone: + return Iterator + (mType, (mValue1 - mValue0) / nPositions, mValue0, mUnit); + case nstLogarithmic: + return Iterator + (mType, exp((mValue1 - mValue0) / nPositions), exp(mValue0), mUnit); + } + } + + // Inverse + float ValueToPosition(float val) const + { + switch (mType) { + default: + wxASSERT(false); + case nstLinear: + return ((val - mValue0) / (mValue1 - mValue0)); + case nstLogarithmic: + return ((log(val) - mValue0) / (mValue1 - mValue0)); + case nstMel: + return ((hzToMel(val * mUnit) - mValue0) / (mValue1 - mValue0)); + case nstBark: + return ((hzToBark(val * mUnit) - mValue0) / (mValue1 - mValue0)); + case nstErb: + return ((hzToErb(val * mUnit) - mValue0) / (mValue1 - mValue0)); + case nstUndertone: + return ((hzToUndertone(val * mUnit) - mValue0) / (mValue1 - mValue0)); + } + } + +private: + const NumberScaleType mType; + float mValue0; + float mValue1; + float mUnit; +}; + +#endif diff --git a/src/Printing.cpp b/src/Printing.cpp index 3e9f8974dd3dd7e2b1d0e3873d157bce75802e5d..18362f1e94ea674c55a46177c6f05327a7aa1704 100644 --- a/src/Printing.cpp +++ b/src/Printing.cpp @@ -25,7 +25,6 @@ #include <wx/printdlg.h> #include "AColor.h" -#include "Track.h" #include "TrackArtist.h" #include "ViewInfo.h" #include "WaveTrack.h" diff --git a/src/Project.cpp b/src/Project.cpp index 3802101139e3d216abbaeb631ca56cb235117f80..297de91d901366ed0b5613cae7bcb7fa46b4aeb8 100644 --- a/src/Project.cpp +++ b/src/Project.cpp @@ -110,10 +110,10 @@ scroll information. It also has some status flags. #include "Mix.h" #include "NoteTrack.h" #include "Prefs.h" +#include "Sequence.h" #include "Snap.h" #include "Tags.h" #include "TimeTrack.h" -#include "Track.h" #include "TrackPanel.h" #include "WaveTrack.h" #include "DirManager.h" @@ -121,7 +121,6 @@ scroll information. It also has some status flags. #include "prefs/PrefsDialog.h" #include "widgets/LinkingHtmlWindow.h" #include "widgets/ErrorDialog.h" -#include "widgets/Meter.h" #include "widgets/Ruler.h" #include "widgets/Warning.h" #include "xml/XMLFileReader.h" @@ -1162,7 +1161,7 @@ AdornedRulerPanel *AudacityProject::GetRulerPanel() return mRuler; } -int AudacityProject::GetAudioIOToken() +int AudacityProject::GetAudioIOToken() const { return mAudioIOToken; } @@ -1172,6 +1171,12 @@ void AudacityProject::SetAudioIOToken(int token) mAudioIOToken = token; } +bool AudacityProject::IsAudioActive() const +{ + return GetAudioIOToken() > 0 && + gAudioIO->IsStreamActive(GetAudioIOToken()); +} + Tags *AudacityProject::GetTags() { return mTags; @@ -1208,6 +1213,11 @@ void AudacityProject::SetProjectTitle() SetName(name); // to make the nvda screen reader read the correct title } +bool AudacityProject::GetIsEmpty() +{ + return mTracks->IsEmpty(); +} + double AudacityProject::AS_GetRate() { return mRate; @@ -1250,7 +1260,18 @@ void AudacityProject::AS_SetSelectionFormat(const wxString & format) double AudacityProject::SSBL_GetRate() const { - return mRate; + // Return maximum of project rate and all track rates. + double rate = mRate; + + TrackListOfKindIterator iterWaveTrack(Track::Wave, mTracks); + WaveTrack *pWaveTrack = static_cast<WaveTrack*>(iterWaveTrack.First()); + while (pWaveTrack) + { + rate = std::max(rate, pWaveTrack->GetRate()); + pWaveTrack = static_cast<WaveTrack*>(iterWaveTrack.Next()); + } + + return rate; } const wxString & AudacityProject::SSBL_GetFrequencySelectionFormatName() @@ -1282,7 +1303,7 @@ void AudacityProject::SSBL_SetBandwidthSelectionFormatName(const wxString & form void AudacityProject::SSBL_ModifySpectralSelection(double &bottom, double &top, bool done) { #ifdef EXPERIMENTAL_SPECTRAL_EDITING - double nyq = mRate / 2.0; + double nyq = SSBL_GetRate() / 2.0; if (bottom >= 0.0) bottom = std::min(nyq, bottom); if (top >= 0.0) @@ -2949,6 +2970,8 @@ bool AudacityProject::HandleXMLTag(const wxChar *tag, const wxChar **attrs) SetBandwidthSelectionFormatName(value); } // while + mViewInfo.UpdatePrefs(); + if (longVpos != 0) { // PRL: It seems this must happen after SetSnapTo mViewInfo.track = NULL; @@ -3861,6 +3884,11 @@ void AudacityProject::PushState(wxString desc, AutoSave(); } +void AudacityProject::RollbackState() +{ + SetStateTo(GetUndoManager()->GetCurrentState()); +} + void AudacityProject::ModifyState(bool bWantsAutoSave) { mUndoManager.ModifyState(mTracks, mViewInfo.selectedRegion); @@ -4353,7 +4381,7 @@ void AudacityProject::GetRegionsByLabel( Regions ®ions ) //If the function replaces the selection with audio of a different length, // bSyncLockedTracks should be set true to perform the same action on sync-lock selected // tracks. -void AudacityProject::EditByLabel( WaveTrack::EditFunction action, +void AudacityProject::EditByLabel( EditFunction action, bool bSyncLockedTracks ) { Regions regions; @@ -4402,7 +4430,7 @@ void AudacityProject::EditByLabel( WaveTrack::EditFunction action, //Functions copy the edited regions to clipboard, possibly in multiple tracks //This probably should not be called if *action() changes the timeline, because // the copy needs to happen by track, and the timeline change by group. -void AudacityProject::EditClipboardByLabel( WaveTrack::EditDestFunction action ) +void AudacityProject::EditClipboardByLabel( EditDestFunction action ) { Regions regions; diff --git a/src/Project.h b/src/Project.h index 98cc9ffac8d89719d366ff83c16b07039a39d6f5..2c6b034be42fcec888715a732821a652df187240 100644 --- a/src/Project.h +++ b/src/Project.h @@ -86,6 +86,9 @@ class MixerBoardFrame; struct AudioIOStartStreamOptions; +class WaveTrackArray; +class Regions; + AudacityProject *CreateNewAudacityProject(); AUDACITY_DLL_API AudacityProject *GetActiveProject(); void RedrawAllProjects(); @@ -179,7 +182,8 @@ class AUDACITY_DLL_API AudacityProject: public wxFrame, TrackFactory *GetTrackFactory(); AdornedRulerPanel *GetRulerPanel(); Tags *GetTags(); - int GetAudioIOToken(); + int GetAudioIOToken() const; + bool IsAudioActive() const; void SetAudioIOToken(int token); bool IsActive(); @@ -241,7 +245,7 @@ class AUDACITY_DLL_API AudacityProject: public wxFrame, TrackPanel * GetTrackPanel(){return mTrackPanel;} - bool GetIsEmpty() { return mTracks->IsEmpty(); } + bool GetIsEmpty(); bool GetTracksFitVerticallyZoomed() { return mTracksFitVerticallyZoomed; } //lda void SetTracksFitVerticallyZoomed(bool flag) { mTracksFitVerticallyZoomed = flag; } //lda @@ -321,8 +325,14 @@ class AUDACITY_DLL_API AudacityProject: public wxFrame, void ZoomBy(double multiplier); void Rewind(bool shift); void SkipEnd(bool shift); - void EditByLabel( WaveTrack::EditFunction action, bool bSyncLockedTracks ); - void EditClipboardByLabel( WaveTrack::EditDestFunction action ); + + + typedef bool (WaveTrack::* EditFunction)(double, double); + typedef bool (WaveTrack::* EditDestFunction)(double, double, Track**); + + void EditByLabel(EditFunction action, bool bSyncLockedTracks); + void EditClipboardByLabel(EditDestFunction action ); + bool IsSyncLocked(); void SetSyncLock(bool flag); @@ -468,6 +478,7 @@ class AUDACITY_DLL_API AudacityProject: public wxFrame, void PushState(wxString desc, wxString shortDesc, int flags = PUSH_AUTOSAVE); + void RollbackState(); private: diff --git a/src/Screenshot.cpp b/src/Screenshot.cpp index 94fc80c3396a097acb062dc9705f961b6449e1ff..af6513968b21f06fd5ed82b4f201681a052c193e 100644 --- a/src/Screenshot.cpp +++ b/src/Screenshot.cpp @@ -34,6 +34,8 @@ #include "Prefs.h" #include "toolbars/ToolManager.h" +#include "Track.h" + class CommandType; //////////////////////////////////////////////////////////////////////////////// diff --git a/src/Snap.cpp b/src/Snap.cpp index 951c8119784077cd7ee4d390c47b7f4fa0e6c3f5..f8c7a4dffe676efae1befbdc46e561dd3ed1996d 100644 --- a/src/Snap.cpp +++ b/src/Snap.cpp @@ -16,6 +16,7 @@ #include "LabelTrack.h" #include "Project.h" #include "TrackPanel.h" +#include "WaveTrack.h" #include "widgets/NumericTextCtrl.h" // Change this to "true" to snap to nearest and "false" to snap to previous @@ -81,7 +82,7 @@ SnapManager::SnapManager(TrackList *tracks, TrackClipArray *exclusions, WaveClip *clip = it->GetData(); if (exclusions) { bool skip = false; - for(int j=0; j<(int)exclusions->GetCount(); j++) { + for(int j=0; j<(int)exclusions->size(); j++) { if ((*exclusions)[j].track == waveTrack && (*exclusions)[j].clip == clip) skip = true; diff --git a/src/Snap.h b/src/Snap.h index a3e9fe82c1cbc9bd8431dbb85d7031ce11bb273f..478a49e0e46b03aacd19d07bae53040f849b8983 100644 --- a/src/Snap.h +++ b/src/Snap.h @@ -15,15 +15,27 @@ #ifndef __AUDACITY_SNAP__ #define __AUDACITY_SNAP__ +#include <vector> + #include <wx/defs.h> -#include <wx/dynarray.h> -#include "Track.h" #include "widgets/NumericTextCtrl.h" -class TrackClipArray; +class Track; +class WaveClip; +class TrackList; class ZoomInfo; +class TrackClip +{ +public: + TrackClip(Track *t, WaveClip *c) { track = t; clip = c; } + Track *track; + WaveClip *clip; +}; + +typedef std::vector<TrackClip> TrackClipArray; + enum { SNAP_OFF, diff --git a/src/SoundActivatedRecord.cpp b/src/SoundActivatedRecord.cpp index 671380b96efe09d7bd48416d1d2c5e9744104bbc..29f896e1721523941701f8c8c81006d853356576 100644 --- a/src/SoundActivatedRecord.cpp +++ b/src/SoundActivatedRecord.cpp @@ -19,14 +19,12 @@ *//********************************************************************/ #include "Audacity.h" +#include "SoundActivatedRecord.h" -#include <wx/dialog.h> - -#include "Envelope.h" #include "ShuttleGui.h" #include "ShuttlePrefs.h" #include "Prefs.h" -#include "SoundActivatedRecord.h" +#include "prefs/GUISettings.h" BEGIN_EVENT_TABLE(SoundActivatedRecord, wxDialog) EVT_BUTTON(wxID_OK, SoundActivatedRecord::OnOK) @@ -57,7 +55,7 @@ void SoundActivatedRecord::PopulateOrExchange(ShuttleGui & S) { S.StartMultiColumn(2, wxEXPAND); S.SetStretchyCol(1); - dBRange = gPrefs->Read(wxT("/GUI/EnvdBRange"), ENV_DB_RANGE); + dBRange = gPrefs->Read(ENV_DB_KEY, ENV_DB_RANGE); S.TieSlider(_("Activation level (dB):"), wxT("/AudioIO/SilenceLevel"), -50, 0, -dBRange); S.EndMultiColumn(); } diff --git a/src/SoundActivatedRecord.h b/src/SoundActivatedRecord.h index 71fef4d7516f621aba1ca864ac420e1bead192f0..a7397f3e0ca81bf3dd5cac8b4ddb051f6144e496 100644 --- a/src/SoundActivatedRecord.h +++ b/src/SoundActivatedRecord.h @@ -13,6 +13,13 @@ ********************************************************************/ +#ifndef __AUDACITY_SOUND_ACTIVATED_RECORD__ +#define __AUDACITY_SOUND_ACTIVATED_RECORD__ + +#include <wx/dialog.h> + +class ShuttleGui; + class SoundActivatedRecord : public wxDialog { public: @@ -27,3 +34,4 @@ private: DECLARE_EVENT_TABLE(); }; +#endif diff --git a/src/Spectrum.h b/src/Spectrum.h index 64e0e28cb473c7e6b86e174e1dfd2142d4c7fe77..f600a05b8644c0ed47453e0b33f8f885075163dd 100644 --- a/src/Spectrum.h +++ b/src/Spectrum.h @@ -11,7 +11,6 @@ #ifndef __AUDACITY_SPECTRUM__ #define __AUDACITY_SPECTRUM__ -#include "WaveTrack.h" #include "FFT.h" /* diff --git a/src/Theme.cpp b/src/Theme.cpp index 386d4b004fd26cff10a012e141b58b8b07665a16..88f2aabfd48a7091dcb0253cdb7c8461904e70d2 100644 --- a/src/Theme.cpp +++ b/src/Theme.cpp @@ -60,6 +60,7 @@ and use it for toolbar and window layouts too. #include <wx/file.h> #include <wx/ffile.h> #include <wx/mstream.h> +#include <wx/msgdlg.h> #include "Project.h" #include "toolbars/ToolBar.h" diff --git a/src/TimeTrack.cpp b/src/TimeTrack.cpp index ea121cf4aa1cfe913a9019dbb917f7173d3dc6ed..24464efd7db354d36319b8345c96ca8124410fd1 100644 --- a/src/TimeTrack.cpp +++ b/src/TimeTrack.cpp @@ -19,6 +19,7 @@ #include <wx/intl.h> #include "AColor.h" #include "widgets/Ruler.h" +#include "Envelope.h" #include "Prefs.h" #include "Internat.h" #include "Resample.h" diff --git a/src/TimerRecordDialog.cpp b/src/TimerRecordDialog.cpp index 1aa1954202cf333aa36f15733a40036fcc0dfa36..5295a861414571473586ea08810b442d55b9fa3c 100644 --- a/src/TimerRecordDialog.cpp +++ b/src/TimerRecordDialog.cpp @@ -29,6 +29,7 @@ #include <wx/string.h> #include <wx/timer.h> #include <wx/dynlib.h> //<! For windows.h +#include <wx/msgdlg.h> #include "ShuttleGui.h" #include "Project.h" diff --git a/src/Track.cpp b/src/Track.cpp index ae91bd2702b512be36fdae2ba817a01b197d15d0..07fc7a0aacaa1dfbca537c222895f68ebe1745fa 100644 --- a/src/Track.cpp +++ b/src/Track.cpp @@ -23,9 +23,7 @@ and TimeTrack. #include "Track.h" #include "WaveTrack.h" #include "NoteTrack.h" -#include "LabelTrack.h" #include "Project.h" -#include "TimeTrack.h" #include "DirManager.h" #ifdef _MSC_VER diff --git a/src/TrackArtist.cpp b/src/TrackArtist.cpp index 3c7624b2fb6cc2f358637661abf5402f2594daf6..c78d210b9d4fa17dd0d03c0ea5ddafff9f36c999 100644 --- a/src/TrackArtist.cpp +++ b/src/TrackArtist.cpp @@ -168,13 +168,14 @@ audio tracks. #include "AColor.h" #include "BlockFile.h" #include "Envelope.h" -#include "Track.h" +#include "NumberScale.h" #include "WaveTrack.h" #include "LabelTrack.h" #include "TimeTrack.h" #include "Prefs.h" -#include "prefs/SpectrumPrefs.h" -#include "Sequence.h" +#include "prefs/GUISettings.h" +#include "prefs/SpectrogramSettings.h" +#include "prefs/WaveformSettings.h" #include "Spectrum.h" #include "ViewInfo.h" #include "widgets/Ruler.h" @@ -459,19 +460,11 @@ void TrackArtist::DrawTrack(const Track * t, bool muted = (hasSolo || t->GetMute()) && !t->GetSolo(); switch (wt->GetDisplay()) { - case WaveTrack::WaveformDisplay: + case WaveTrack::Waveform: DrawWaveform(wt, dc, rect, selectedRegion, zoomInfo, - drawEnvelope, bigPoints, drawSliders, false, muted); + drawEnvelope, bigPoints, drawSliders, muted); break; - case WaveTrack::WaveformDBDisplay: - DrawWaveform(wt, dc, rect, selectedRegion, zoomInfo, - drawEnvelope, bigPoints, drawSliders, true, muted); - break; - case WaveTrack::SpectrumDisplay: - case WaveTrack::SpectrumLogDisplay: - case WaveTrack::SpectralSelectionDisplay: - case WaveTrack::SpectralSelectionLogDisplay: - case WaveTrack::PitchDisplay: + case WaveTrack::Spectrum: DrawSpectrum(wt, dc, rect, selectedRegion, zoomInfo); break; } @@ -548,11 +541,6 @@ void TrackArtist::DrawVRuler(Track *t, wxDC * dc, wxRect & rect) bev.width += 1; AColor::BevelTrackInfo(*dc, true, bev); - // Pitch doesn't have a ruler - if (((WaveTrack *)t)->GetDisplay() == WaveTrack::PitchDisplay) { - return; - } - // Right align the ruler wxRect rr = rect; rr.width--; @@ -695,182 +683,187 @@ 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; - int display = wt->GetDisplay(); + WaveTrack *wt = static_cast<WaveTrack*>(t); - if (display == WaveTrack::WaveformDisplay) { - // Waveform + const int display = wt->GetDisplay(); - float min, max; - wt->GetDisplayBounds(&min, &max); - if(wt->GetLastDisplay()==WaveTrack::WaveformDBDisplay) - { - // do a translation into the WaveTrack::WaveformDisplay space - wt->SetDisplay(WaveTrack::WaveformDisplay); // this makes the last display not WaveformDBDisplay - float sign = (min >= 0 ? 1 : -1); - if (min != 0.) { - min = pow(10., (fabs(min)*mdBrange - mdBrange)/20.0); - if (min < 0.0) - min = 0.0; - min *= sign; - } - sign = (max >= 0 ? 1 : -1); + if (display == WaveTrack::Waveform) { + WaveformSettings::ScaleType scaleType = + wt->GetWaveformSettings().scaleType; - if (max != 0.) { - max = pow(10., (fabs(max)*mdBrange - mdBrange)/20.0); - if (max < 0.0) - max = 0.0; - max *= sign; - } - wt->SetDisplayBounds(min, max); - } - - vruler->SetBounds(rect.x, rect.y+1, rect.x + rect.width, rect.y + rect.height-1); - vruler->SetOrientation(wxVERTICAL); - vruler->SetRange(max, min); - vruler->SetFormat(Ruler::RealFormat); - vruler->SetUnits(wxT("")); - vruler->SetLabelEdges(false); - vruler->SetLog(false); - } - else if (display == WaveTrack::WaveformDBDisplay) { - // Waveform (db) + if (scaleType == WaveformSettings::stLinear) { + // Waveform - vruler->SetUnits(wxT("")); - - float min, max; - wt->GetDisplayBounds(&min, &max); + float min, max; + wt->GetDisplayBounds(&min, &max); + if (wt->GetLastScaleType() != scaleType) + { + // do a translation into the linear space + wt->SetLastScaleType(scaleType); + float sign = (min >= 0 ? 1 : -1); + if (min != 0.) { + min = DB_TO_LINEAR(fabs(min)*mdBrange - mdBrange); + if (min < 0.0) + min = 0.0; + min *= sign; + } + sign = (max >= 0 ? 1 : -1); - if(wt->GetLastDisplay()==WaveTrack::WaveformDisplay) - { - // do a translation into the WaveTrack::WaveformDBDisplay space - wt->SetDisplay(WaveTrack::WaveformDBDisplay); // this makes the last display not WaveformDisplay - float sign = (min >= 0 ? 1 : -1); - if (min != 0.) { - min = (20.0 * log10(fabs(min)) + mdBrange) / mdBrange; - if (min < 0.0) - min = 0.0; - min *= sign; + if (max != 0.) { + max = DB_TO_LINEAR(fabs(max)*mdBrange - mdBrange); + if (max < 0.0) + max = 0.0; + max *= sign; + } + wt->SetDisplayBounds(min, max); } - sign = (max >= 0 ? 1 : -1); - if (max != 0.) { - max = (20.0 * log10(fabs(max)) + mdBrange) / mdBrange; - if (max < 0.0) - max = 0.0; - max *= sign; - } - wt->SetDisplayBounds(min, max); + vruler->SetBounds(rect.x, rect.y + 1, rect.x + rect.width, rect.y + rect.height - 1); + vruler->SetOrientation(wxVERTICAL); + vruler->SetRange(max, min); + vruler->SetFormat(Ruler::RealFormat); + vruler->SetUnits(wxT("")); + vruler->SetLabelEdges(false); + vruler->SetLog(false); } + else { + wxASSERT(scaleType == WaveformSettings::stLogarithmic); + scaleType = WaveformSettings::stLogarithmic; + + vruler->SetUnits(wxT("")); - if (max > 0) { - int top = 0; - float topval = 0; - int bot = rect.height; - float botval = -mdBrange; + float min, max; + wt->GetDisplayBounds(&min, &max); - if (min < 0) { - bot = top + (int)((max / (max-min))*(bot-top)); - min = 0; - } + if (wt->GetLastScaleType() != scaleType) + { + // do a translation into the dB space + wt->SetLastScaleType(scaleType); + float sign = (min >= 0 ? 1 : -1); + if (min != 0.) { + min = (LINEAR_TO_DB(fabs(min)) + mdBrange) / mdBrange; + if (min < 0.0) + min = 0.0; + min *= sign; + } + sign = (max >= 0 ? 1 : -1); - if (max > 1) { - top += (int)((max-1)/(max-min) * (bot-top)); - max = 1; + if (max != 0.) { + max = (LINEAR_TO_DB(fabs(max)) + mdBrange) / mdBrange; + if (max < 0.0) + max = 0.0; + max *= sign; + } + wt->SetDisplayBounds(min, max); } - if (max < 1 && max > 0) - topval = -((1-max)*mdBrange); + if (max > 0) { + int top = 0; + float topval = 0; + int bot = rect.height; + float botval = -mdBrange; - if (min > 0) { - botval = -((1-min)*mdBrange); - } + if (min < 0) { + bot = top + (int)((max / (max - min))*(bot - top)); + min = 0; + } - vruler->SetBounds(rect.x, rect.y+top+1, rect.x + rect.width, rect.y + bot-1); - vruler->SetOrientation(wxVERTICAL); - vruler->SetRange(topval, botval); - } - else - vruler->SetBounds(0.0, 0.0, 0.0, 0.0); // A.C.H I couldn't find a way to just disable it? - vruler->SetFormat(Ruler::RealLogFormat); - vruler->SetLabelEdges(true); - vruler->SetLog(false); - } - else if ( - (display == WaveTrack::SpectrumDisplay) || - (display == WaveTrack::SpectralSelectionDisplay) ) - { - // Spectrum + if (max > 1) { + top += (int)((max - 1) / (max - min) * (bot - top)); + max = 1; + } - if (rect.height < 60) - return; + if (max < 1 && max > 0) + topval = -((1 - max)*mdBrange); - double rate = wt->GetRate(); - int freq = lrint(rate/2.); + if (min > 0) { + botval = -((1 - min)*mdBrange); + } + + vruler->SetBounds(rect.x, rect.y + top + 1, rect.x + rect.width, rect.y + bot - 1); + vruler->SetOrientation(wxVERTICAL); + vruler->SetRange(topval, botval); + } + else + vruler->SetBounds(0.0, 0.0, 0.0, 0.0); // A.C.H I couldn't find a way to just disable it? + vruler->SetFormat(Ruler::RealLogFormat); + vruler->SetLabelEdges(true); + vruler->SetLog(false); + } + } + else { + wxASSERT(display == WaveTrack::Spectrum); + switch (wt->GetSpectrogramSettings().scaleType) { + default: + wxASSERT(false); + case SpectrogramSettings::stLinear: + { + // Spectrum - int maxFreq = GetSpectrumMaxFreq(freq); - if(maxFreq > freq) - maxFreq = freq; + if (rect.height < 60) + return; - 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 we will use Hz if maxFreq is < 2000, otherwise we represent kHz, and append to the numbers a "k" - */ - vruler->SetBounds(rect.x, rect.y+1, rect.x + rect.width, rect.y + rect.height-1); - vruler->SetOrientation(wxVERTICAL); - vruler->SetFormat(Ruler::RealFormat); - vruler->SetLabelEdges(true); - // use kHz in scale, if appropriate - if (maxFreq>=2000) { - vruler->SetRange((maxFreq/1000.), (minFreq/1000.)); - vruler->SetUnits(wxT("k")); - } else { - // use Hz - vruler->SetRange(int(maxFreq), int(minFreq)); - vruler->SetUnits(wxT("")); + */ + vruler->SetBounds(rect.x, rect.y + 1, rect.x + rect.width, rect.y + rect.height - 1); + vruler->SetOrientation(wxVERTICAL); + vruler->SetFormat(Ruler::RealFormat); + vruler->SetLabelEdges(true); + // use kHz in scale, if appropriate + if (maxFreq >= 2000) { + vruler->SetRange((maxFreq / 1000.), (minFreq / 1000.)); + vruler->SetUnits(wxT("k")); + } + else { + // use Hz + vruler->SetRange(int(maxFreq), int(minFreq)); + vruler->SetUnits(wxT("")); + } + vruler->SetLog(false); } - vruler->SetLog(false); - } - else if ( - (display == WaveTrack::SpectrumLogDisplay) || - (display == WaveTrack::SpectralSelectionLogDisplay) ) - { - // SpectrumLog - - if (rect.height < 10) - return; - - double rate = wt->GetRate(); - int freq = lrint(rate/2.); + break; + case SpectrogramSettings::stLogarithmic: + case SpectrogramSettings::stMel: + case SpectrogramSettings::stBark: + case SpectrogramSettings::stErb: + case SpectrogramSettings::stUndertone: + { + // SpectrumLog - int maxFreq = GetSpectrumLogMaxFreq(freq); - if(maxFreq > freq) - maxFreq = freq; + if (rect.height < 10) + return; - 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 we will use Hz if maxFreq is < 2000, otherwise we represent kHz, and append to the numbers a "k" - */ - vruler->SetBounds(rect.x, rect.y+1, rect.x + rect.width, rect.y + rect.height-1); - vruler->SetOrientation(wxVERTICAL); - vruler->SetFormat(Ruler::IntFormat); - vruler->SetLabelEdges(true); - vruler->SetRange(maxFreq, minFreq); - vruler->SetUnits(wxT("")); - vruler->SetLog(true); - } - else if (display == WaveTrack::PitchDisplay) { - // Pitch + */ + vruler->SetBounds(rect.x, rect.y + 1, rect.x + rect.width, rect.y + rect.height - 1); + vruler->SetOrientation(wxVERTICAL); + vruler->SetFormat(Ruler::IntFormat); + vruler->SetLabelEdges(true); + vruler->SetRange(maxFreq, minFreq); + vruler->SetUnits(wxT("")); + vruler->SetLog(true); + NumberScale scale + (wt->GetSpectrogramSettings().GetScale(wt->GetRate(), false).Reversal()); + vruler->SetNumberScale(&scale); + } + break; + } } } @@ -903,7 +896,7 @@ int GetWaveYPos(float value, float min, float max, float sign = (value >= 0 ? 1 : -1); if (value != 0.) { - float db = 20.0 * log10(fabs(value)); + float db = LINEAR_TO_DB(fabs(value)); value = (db + dBr) / dBr; if (!outer) { value -= 0.5; @@ -944,7 +937,7 @@ float FromDB(float value, double dBRange) return 0; double sign = (value >= 0 ? 1 : -1); - return pow(10.0, ((fabs(value) * dBRange) - dBRange) / 20.0)*sign; + return DB_TO_LINEAR((fabs(value) * dBRange) - dBRange) * sign; } float ValueOfPixel(int yy, int height, bool offset, @@ -995,11 +988,10 @@ void TrackArtist::DrawNegativeOffsetTrackArrows(wxDC &dc, const wxRect &rect) void TrackArtist::DrawWaveformBackground(wxDC &dc, int leftOffset, const wxRect &rect, const double env[], float zoomMin, float zoomMax, bool dB, - const SelectedRegion &selectedRegion, + double t0, double t1, const ZoomInfo &zoomInfo, bool drawEnvelope, bool bIsSyncLockSelected) { - const double t0 = selectedRegion.t0(), t1 = selectedRegion.t1(); // Visually (one vertical slice of the waveform background, on its side; // the "*" is the actual waveform background we're drawing @@ -1431,9 +1423,10 @@ void TrackArtist::DrawWaveform(WaveTrack *track, bool drawEnvelope, bool bigPoints, bool drawSliders, - bool dB, bool muted) { + const bool dB = !track->GetWaveformSettings().isLinear(); + DrawBackgroundWithSelection(&dc, rect, track, blankSelectedBrush, blankBrush, selectedRegion, zoomInfo); @@ -1451,7 +1444,7 @@ void TrackArtist::DrawWaveform(WaveTrack *track, if (xx >= 0 && xx < rect.width) { dc.SetPen(*wxGREY_PEN); AColor::Line(dc, (int) (rect.x + xx - 1), rect.y, (int) (rect.x + xx - 1), rect.y + rect.height); - if (loc.typ == WaveTrack::locationCutLine) { + if (loc.typ == WaveTrackLocation::locationCutLine) { dc.SetPen(*wxRED_PEN); } else { @@ -1637,11 +1630,17 @@ struct ClipParameters }; } +#ifdef __GNUC__ +#define CONST +#else +#define CONST const +#endif + namespace { struct WavePortion { wxRect rect; - /*const*/ double averageZoom; - /*const*/ bool inFisheye; + CONST double averageZoom; + CONST bool inFisheye; WavePortion(int x, int y, int w, int h, double zoom, bool i) : rect(x, y, w, h), averageZoom(zoom), inFisheye(i) {} @@ -1664,9 +1663,9 @@ void FindWavePortions for (int left = rect.x; left < rightmost;) { while (it != end && it->position <= left) prev = it++; - const int right = std::max(left, int( - it != end ? it->position : rightmost - )); + if (it == end) + break; + const int right = std::max(left, int(it->position)); const int width = right - left; if (width > 0) portions.push_back( @@ -1731,11 +1730,20 @@ void TrackArtist::DrawClipWaveform(WaveTrack *track, // Draw the background of the track, outlining the shape of // the envelope and using a colored pen for the selected // part of the waveform - DrawWaveformBackground(dc, leftOffset, mid, - env, - zoomMin, zoomMax, dB, - selectedRegion, zoomInfo, drawEnvelope, - !track->GetSelected()); + { + double t0, t1; + if (track->GetSelected() || track->IsSyncLockSelected()) { + t0 = track->LongSamplesToTime(track->TimeToLongSamples(selectedRegion.t0())), + t1 = track->LongSamplesToTime(track->TimeToLongSamples(selectedRegion.t1())); + } + else + t0 = t1 = 0.0; + DrawWaveformBackground(dc, leftOffset, mid, + env, + zoomMin, zoomMax, dB, + t0, t1, zoomInfo, drawEnvelope, + !track->GetSelected()); + } WaveDisplay display(hiddenMid.width); bool isLoadingOD = false;//true if loading on demand block in sequence. @@ -1957,6 +1965,8 @@ static inline float findValue bool autocorrelation, int gain, int range) { float value; + + #if 0 // Averaging method if (int(bin1) == int(bin0)) { @@ -1982,11 +1992,24 @@ static inline float findValue wxUnusedVar(half); // Maximum method, and no apportionment of any single bins over multiple pixel rows // See Bug971 - int bin = std::min(half - 1, int(floor(0.5 + bin0))); - const int limitBin = std::min(half, int(floor(0.5 + bin1))); - value = spectrum[bin]; - while (++bin < limitBin) - value = std::max(value, spectrum[bin]); + int index, limitIndex; + if (autocorrelation) { + // bin = 2 * half / (half - 1 - array_index); + // Solve for index + index = std::max(0.0f, std::min(float(half - 1), + (half - 1) - (2 * half) / (std::max(1.0f, bin0)) + )); + limitIndex = std::max(0.0f, std::min(float(half - 1), + (half - 1) - (2 * half) / (std::max(1.0f, bin1)) + )); + } + else { + index = std::min(half - 1, int(floor(0.5 + bin0))); + limitIndex = std::min(half, int(floor(0.5 + bin1))); + } + value = spectrum[index]; + while (++index < limitIndex) + value = std::max(value, spectrum[index]); #endif if (!autocorrelation) { // Last step converts dB to a 0.0-1.0 range @@ -2031,10 +2054,10 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &waveTrackCache, #endif const WaveTrack *const track = waveTrackCache.GetTrack(); - const int display = track->GetDisplay(); - const bool autocorrelation = (WaveTrack::PitchDisplay == display); - const bool logF = (WaveTrack::SpectrumLogDisplay == display - || WaveTrack::SpectralSelectionLogDisplay == display); + const SpectrogramSettings &settings = track->GetSpectrogramSettings(); + + const bool autocorrelation = (settings.algorithm == SpectrogramSettings::algPitchEAC); + enum { DASH_LENGTH = 10 /* pixels */ }; const ClipParameters params(true, track, clip, rect, selectedRegion, zoomInfo); @@ -2062,13 +2085,10 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &waveTrackCache, double freqLo = SelectedRegion::UndefinedFrequency; double freqHi = SelectedRegion::UndefinedFrequency; #ifdef EXPERIMENTAL_SPECTRAL_EDITING - if (!autocorrelation) { - freqLo = selectedRegion.f0(); - freqHi = selectedRegion.f1(); - } + freqLo = selectedRegion.f0(); + freqHi = selectedRegion.f1(); #endif - const SpectrogramSettings &settings = SpectrogramSettings::defaults(); const bool &isGrayscale = settings.isGrayscale; const int &range = settings.range; const int &gain = settings.gain; @@ -2093,7 +2113,7 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &waveTrackCache, return; unsigned char *data = image->GetData(); - const int half = GetSpectrumWindowSize(!autocorrelation) / 2; + const int half = settings.GetFFTLength() / 2; const double binUnit = rate / (2 * half); const float *freq = 0; const sampleCount *where = 0; @@ -2104,38 +2124,16 @@ 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; - } + // Legacy special-case treatment of log scale + const SpectrogramSettings::ScaleType scaleType = settings.scaleType; + const int minFreq = + scaleType == SpectrogramSettings::stLinear + ? settings.GetMinFreq(rate) : settings.GetLogMinFreq(rate); + const int maxFreq = + scaleType == SpectrogramSettings::stLinear + ? settings.GetMaxFreq(rate) : settings.GetLogMaxFreq(rate); - float minBin = ((double)minFreq / binUnit); - float maxBin = ((double)maxFreq / binUnit); - float binPerPx = float(maxBin - minBin) / float(mid.height); - - const float - // e=exp(1.0f), - lmin = logf(float(minFreq)), - lmax = logf(float(maxFreq)), - scale = lmax - lmin; + const NumberScale numberScale(settings.GetScale(rate, true)); #ifdef EXPERIMENTAL_FFT_Y_GRID const float @@ -2160,7 +2158,8 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &waveTrackCache, #endif //EXPERIMENTAL_FFT_Y_GRID if (!updated && clip->mSpecPxCache->valid && - (clip->mSpecPxCache->len == hiddenMid.height * hiddenMid.width) + (clip->mSpecPxCache->len == hiddenMid.height * hiddenMid.width) + && scaleType == clip->mSpecPxCache->scaleType && gain == clip->mSpecPxCache->gain && range == clip->mSpecPxCache->range && minFreq == clip->mSpecPxCache->minFreq @@ -2183,6 +2182,7 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &waveTrackCache, delete clip->mSpecPxCache; clip->mSpecPxCache = new SpecPxCache(hiddenMid.width * hiddenMid.height); clip->mSpecPxCache->valid = true; + clip->mSpecPxCache->scaleType = scaleType; clip->mSpecPxCache->gain = gain; clip->mSpecPxCache->range = range; clip->mSpecPxCache->minFreq = minFreq; @@ -2214,135 +2214,124 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &waveTrackCache, int *indexes = new int[maxTableSize]; #endif //EXPERIMENTAL_FIND_NOTES - for (int xx = 0; xx < hiddenMid.width; ++xx) - { - if (!logF) { - for (int yy = 0; yy < hiddenMid.height; ++yy) { - float bin0 = float(yy) * binPerPx + minBin; - float bin1 = float(yy + 1) * binPerPx + minBin; + for (int xx = 0; xx < hiddenMid.width; ++xx) { + NumberScale::Iterator it = numberScale.begin(mid.height); + float nextBin = std::max(0.0f, std::min(float(half - 1), *it)); + for (int yy = 0; yy < hiddenMid.height; ++yy) { + const float bin = nextBin; + nextBin = std::max(0.0f, std::min(float(half - 1), *++it)); + + if (settings.scaleType != SpectrogramSettings::stLogarithmic) { const float value = findValue - (freq + half * xx, bin0, bin1, half, autocorrelation, gain, range); + (freq + half * xx, bin, nextBin, half, autocorrelation, gain, range); clip->mSpecPxCache->values[xx * hiddenMid.height + yy] = value; } - } - else { + else { + // Do we need this legacy experiment still? #ifdef EXPERIMENTAL_FIND_NOTES - int maximas=0; - const int x0 = half * xx; - if (fftFindNotes) { - for (int i = maxTableSize-1; i >= 0; i--) - indexes[i]=-1; - - // Build a table of (most) values, put the index in it. - for (int i = int(i0); i < int(i1); i++) { - float freqi=freq[x0 + int(i)]; - int value=int((freqi+gain+range)/range*(maxTableSize-1)); - if (value < 0) - value=0; - if (value >= maxTableSize) - value=maxTableSize-1; - indexes[value]=i; - } - // Build from the indices an array of maxima. - for (int i = maxTableSize - 1; i >= 0; i--) { - int index = indexes[i]; - if (index >= 0) { - float freqi = freq[x0 + index]; - if (freqi < findNotesMinA) - break; - - bool ok = true; - for (int m = 0; m < maximas; m++) { - // Avoid to store very close maxima. - float maxm = maxima[m]; - if (maxm / index < minDistance && index / maxm < minDistance) { - ok = false; + int maximas = 0; + const int x0 = half * x; + if (fftFindNotes) { + for (int i = maxTableSize - 1; i >= 0; i--) + indexes[i] = -1; + + // Build a table of (most) values, put the index in it. + for (int i = int(i0); i < int(i1); i++) { + float freqi = freq[x0 + int(i)]; + int value = int((freqi + gain + range) / range*(maxTableSize - 1)); + if (value < 0) + value = 0; + if (value >= maxTableSize) + value = maxTableSize - 1; + indexes[value] = i; + } + // Build from the indices an array of maxima. + for (int i = maxTableSize - 1; i >= 0; i--) { + int index = indexes[i]; + if (index >= 0) { + float freqi = freq[x0 + index]; + if (freqi < findNotesMinA) break; + + bool ok = true; + for (int m = 0; m < maximas; m++) { + // Avoid to store very close maxima. + float maxm = maxima[m]; + if (maxm / index < minDistance && index / maxm < minDistance) { + ok = false; + break; + } + } + if (ok) { + maxima[maximas++] = index; + if (maximas >= numberOfMaxima) + break; } - } - if (ok) { - maxima[maximas++] = index; - if (maximas >= numberOfMaxima) - break; } } - } // The f2pix helper macro converts a frequency into a pixel coordinate. #define f2pix(f) (logf(f)-lmins)/(lmaxs-lmins)*hiddenMid.height - // Possibly quantize the maxima frequencies and create the pixel block limits. - for (int i=0; i < maximas; i++) { - int index=maxima[i]; - float f = float(index)*bin2f; - if (findNotesQuantize) - { f = expf(int(log(f/440)/log2*12-0.5)/12.0f*log2)*440; - maxima[i] = f*f2bin; + // Possibly quantize the maxima frequencies and create the pixel block limits. + for (int i = 0; i < maximas; i++) { + int index = maxima[i]; + float f = float(index)*bin2f; + if (findNotesQuantize) + { + f = expf(int(log(f / 440) / log2 * 12 - 0.5) / 12.0f*log2) * 440; + maxima[i] = f*f2bin; + } + float f0 = expf((log(f / 440) / log2 * 24 - 1) / 24.0f*log2) * 440; + maxima0[i] = f2pix(f0); + float f1 = expf((log(f / 440) / log2 * 24 + 1) / 24.0f*log2) * 440; + maxima1[i] = f2pix(f1); } - float f0 = expf((log(f/440)/log2*24-1)/24.0f*log2)*440; - maxima0[i] = f2pix(f0); - float f1 = expf((log(f/440)/log2*24+1)/24.0f*log2)*440; - maxima1[i] = f2pix(f1); } - } - int it=0; - int oldBin0=-1; - bool inMaximum = false; + int it = 0; + int oldBin0 = -1; + bool inMaximum = false; #endif //EXPERIMENTAL_FIND_NOTES - double yy2_base = exp(lmin) / binUnit; - float yy2 = yy2_base; - double exp_scale_per_height = exp(scale / hiddenMid.height); - for (int yy = 0; yy < hiddenMid.height; ++yy) { - if (int(yy2) >= half) - yy2=half-1; - if (yy2<0) - yy2=0; - float bin0 = float(yy2); - yy2_base *= exp_scale_per_height; - float yy3 = yy2_base; - if (int(yy3)>=half) - yy3=half-1; - if (yy3<0) - yy3=0; - float bin1 = float(yy3); float value; #ifdef EXPERIMENTAL_FIND_NOTES if (fftFindNotes) { if (it < maximas) { - float i0=maxima0[it]; + float i0 = maxima0[it]; if (yy >= i0) inMaximum = true; if (inMaximum) { - float i1=maxima1[it]; - if (yy+1 <= i1) { - value=findValue(freq + x0, bin0, bin1, half, autocorrelation, gain, range); + float i1 = maxima1[it]; + if (yy + 1 <= i1) { + value = findValue(freq + x0, bin, nextBin, half, autocorrelation, gain, range); if (value < findNotesMinA) value = minColor; - } else { + } + else { it++; inMaximum = false; value = minColor; } - } else { + } + else { value = minColor; } - } else + } + else value = minColor; - } else + } + else #endif //EXPERIMENTAL_FIND_NOTES { value = findValue - (freq + half * xx, bin0, bin1, half, autocorrelation, gain, range); + (freq + half * xx, bin, nextBin, half, autocorrelation, gain, range); } clip->mSpecPxCache->values[xx * hiddenMid.height + yy] = value; - yy2 = yy2_base; - } // each yy - } // is logF + } // logF + } // each yy } // each xx - } // updating cache float selBinLo = freqLo / binUnit; @@ -2354,6 +2343,7 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &waveTrackCache, (zoomInfo.PositionToTime(0, -leftOffset) - tOffset) ); + const bool isSpectral = settings.SpectralSelectionEnabled(); const bool hidden = (ZoomInfo::HIDDEN == zoomInfo.GetFisheyeState()); const int begin = hidden ? 0 @@ -2393,93 +2383,42 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &waveTrackCache, (zoomInfo.PositionToTime(xx + 1, -leftOffset) - tOffset) ); - // TODO: The logF and non-logF case are very similar. - // They should be merged and simplified. - if (!logF) - { - for (int yy = 0; yy < hiddenMid.height; ++yy) { - float bin0 = float(yy) * binPerPx + minBin; - float bin1 = float(yy + 1) * binPerPx + minBin; - - // For spectral selection, determine what colour - // set to use. We use a darker selection if - // in both spectral range and time range. - - AColor::ColorGradientChoice selected = - AColor::ColorGradientUnselected; - // If we are in the time selected range, then we may use a different color set. - if (ssel0 <= w0 && w1 < ssel1) - { - bool isSpectral = ((track->GetDisplay() == WaveTrack::SpectralSelectionDisplay) || - (track->GetDisplay() == WaveTrack::SpectralSelectionLogDisplay)); - selected = ChooseColorSet(bin0, bin1, selBinLo, selBinCenter, selBinHi, + NumberScale::Iterator it = numberScale.begin(mid.height); + float nextBin = std::max(0.0f, std::min(float(half - 1), *it)); + for (int yy = 0; yy < hiddenMid.height; ++yy) { + const float bin = nextBin; + nextBin = std::max(0.0f, std::min(float(half - 1), *++it)); + + // For spectral selection, determine what colour + // set to use. We use a darker selection if + // in both spectral range and time range. + + AColor::ColorGradientChoice selected = AColor::ColorGradientUnselected; + // If we are in the time selected range, then we may use a different color set. + if (ssel0 <= w0 && w1 < ssel1) + selected = + ChooseColorSet(bin, nextBin, selBinLo, selBinCenter, selBinHi, (xx + leftOffset - hiddenLeftOffset) / DASH_LENGTH, isSpectral); - } - - unsigned char rv, gv, bv; - const float value = uncached - ? findValue(uncached, bin0, bin1, half, autocorrelation, gain, range) - : clip->mSpecPxCache->values[correctedX * hiddenMid.height + yy]; - GetColorGradient(value, selected, isGrayscale, &rv, &gv, &bv); - int px = ((mid.height - 1 - yy) * mid.width + xx) * 3; - data[px++] = rv; - data[px++] = gv; - data[px] = bv; - } - } - else //logF - { - double yy2_base=exp(lmin)/binUnit; - float yy2 = yy2_base; - double exp_scale_per_height = exp(scale / hiddenMid.height); - for (int yy = 0; yy < hiddenMid.height; ++yy) { - if (int(yy2)>=half) - yy2=half-1; - if (yy2<0) - yy2=0; - float bin0 = float(yy2); - yy2_base *= exp_scale_per_height; - float yy3 = yy2_base; - if (int(yy3)>=half) - yy3=half-1; - if (yy3<0) - yy3=0; - float bin1 = float(yy3); - - AColor::ColorGradientChoice selected = AColor::ColorGradientUnselected; - // If we are in the time selected range, then we may use a different color set. - if (ssel0 <= w0 && w1 < ssel1) - { - bool isSpectral = ((track->GetDisplay() == WaveTrack::SpectralSelectionDisplay) || - (track->GetDisplay() == WaveTrack::SpectralSelectionLogDisplay)); - selected = ChooseColorSet( - bin0, bin1, selBinLo, selBinCenter, selBinHi, - (xx + leftOffset - hiddenLeftOffset) / DASH_LENGTH, isSpectral); - } - - unsigned char rv, gv, bv; - const float value = uncached - ? findValue(uncached, bin0, bin1, half, autocorrelation, gain, range) - : clip->mSpecPxCache->values[correctedX * hiddenMid.height + yy]; - GetColorGradient(value, selected, isGrayscale, &rv, &gv, &bv); + const float value = uncached + ? findValue(uncached, bin, nextBin, half, autocorrelation, gain, range) + : clip->mSpecPxCache->values[correctedX * hiddenMid.height + yy]; + unsigned char rv, gv, bv; + GetColorGradient(value, selected, isGrayscale, &rv, &gv, &bv); #ifdef EXPERIMENTAL_FFT_Y_GRID - if (fftYGrid && yGrid[yy]) { - rv /= 1.1f; - gv /= 1.1f; - bv /= 1.1f; - } + if (fftYGrid && yGrid[yy]) { + rv /= 1.1f; + gv /= 1.1f; + bv /= 1.1f; + } #endif //EXPERIMENTAL_FFT_Y_GRID - int px = ((mid.height - 1 - yy) * mid.width + xx) * 3; - data[px++] = rv; - data[px++] = gv; - data[px] = bv; - - yy2 = yy2_base; - } - } - } + int px = ((mid.height - 1 - yy) * mid.width + xx) * 3; + data[px++] = rv; + data[px++] = gv; + data[px] = bv; + } // each yy + } // each xx wxBitmap converted = wxBitmap(*image); @@ -2495,23 +2434,6 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &waveTrackCache, #endif //EXPERIMENTAL_FFT_Y_GRID } -void TrackArtist::InvalidateSpectrumCache(TrackList *tracks) -{ - TrackListOfKindIterator iter(Track::Wave, tracks); - for (Track *t = iter.First(); t; t = iter.Next()) { - InvalidateSpectrumCache((WaveTrack *)t); - } -} - -void TrackArtist::InvalidateSpectrumCache(WaveTrack *track) -{ - WaveClipList::compatibility_iterator it; - for (it = track->GetClipIterator(); it; it = it->GetNext()) { - it->GetData()->mSpecPxCache->valid = false; - } -} - - #ifdef USE_MIDI /* Note: recall that Allegro attributes end in a type identifying letter. @@ -3186,9 +3108,9 @@ void TrackArtist::DrawTimeTrack(TimeTrack *track, double lower = track->GetRangeLower(), upper = track->GetRangeUpper(); if(track->GetDisplayLog()) { // MB: silly way to undo the work of GetWaveYPos while still getting a logarithmic scale - double dBRange = gPrefs->Read(wxT("/GUI/EnvdBRange"), ENV_DB_RANGE); - lower = 20.0 * log10(std::max(1.0e-7, lower)) / dBRange + 1.0; - upper = 20.0 * log10(std::max(1.0e-7, upper)) / dBRange + 1.0; + double dBRange = gPrefs->Read(ENV_DB_KEY, ENV_DB_RANGE); + lower = LINEAR_TO_DB(std::max(1.0e-7, lower)) / dBRange + 1.0; + upper = LINEAR_TO_DB(std::max(1.0e-7, upper)) / dBRange + 1.0; } track->GetEnvelope()->DrawPoints(dc, envRect, zoomInfo, track->GetDisplayLog(), lower, upper); @@ -3196,72 +3118,12 @@ void TrackArtist::DrawTimeTrack(TimeTrack *track, void TrackArtist::UpdatePrefs() { - mdBrange = gPrefs->Read(wxT("/GUI/EnvdBRange"), mdBrange); + mdBrange = gPrefs->Read(ENV_DB_KEY, mdBrange); mShowClipping = gPrefs->Read(wxT("/GUI/ShowClipping"), mShowClipping); 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) -{ - wxUnusedVar(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 diff --git a/src/TrackArtist.h b/src/TrackArtist.h index 5c96ca38aba45c32662c3431eacd8813067e0ea6..b6876d9f6ddef05f2ed6751afd00dc3ab9d8e8c0 100644 --- a/src/TrackArtist.h +++ b/src/TrackArtist.h @@ -71,19 +71,6 @@ class AUDACITY_DLL_API TrackArtist { void UpdatePrefs(); - 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) { this->unselectedBrush = unselectedBrush; @@ -110,7 +97,7 @@ class AUDACITY_DLL_API TrackArtist { wxDC & dc, const wxRect & rect, const SelectedRegion &selectedRegion, const ZoomInfo &zoomInfo, bool drawEnvelope, bool bigPoints, bool drawSliders, - bool dB, bool muted); + bool muted); void DrawSpectrum(WaveTrack *track, wxDC & dc, const wxRect & rect, @@ -154,7 +141,7 @@ class AUDACITY_DLL_API TrackArtist { void DrawWaveformBackground(wxDC & dc, int leftOffset, const wxRect &rect, const double env[], float zoomMin, float zoomMax, bool dB, - const SelectedRegion &selectedRegion, const ZoomInfo &zoomInfo, + double t0, double t1, const ZoomInfo &zoomInfo, bool drawEnvelope, bool bIsSyncLockSelected); void DrawMinMaxRMS(wxDC &dc, const wxRect & rect, const double env[], float zoomMin, float zoomMax, bool dB, diff --git a/src/TrackPanel.cpp b/src/TrackPanel.cpp index 730e4db9ac0d26d5a43d955d223b479104d1b4e3..2c883f9d3a94b87942918a122ede53d132f175d5 100644 --- a/src/TrackPanel.cpp +++ b/src/TrackPanel.cpp @@ -196,18 +196,16 @@ is time to refresh some aspect of the screen. #include "float_cast.h" #include "Internat.h" #include "LabelTrack.h" -#include "Lyrics.h" -#include "LyricsWindow.h" #include "MixerBoard.h" #include "NoteTrack.h" +#include "NumberScale.h" #include "Prefs.h" #include "Project.h" #include "Snap.h" #include "ShuttleGui.h" #include "Theme.h" #include "TimeTrack.h" -#include "Track.h" #include "TrackArtist.h" #include "TrackPanelAx.h" #include "ViewInfo.h" @@ -217,7 +215,9 @@ is time to refresh some aspect of the screen. #include "ondemand/ODManager.h" +#include "prefs/PrefsDialog.h" #include "prefs/SpectrumPrefs.h" +#include "prefs/WaveformPrefs.h" #include "toolbars/ControlToolBar.h" #include "toolbars/ToolManager.h" @@ -228,16 +228,14 @@ is time to refresh some aspect of the screen. #include "widgets/Ruler.h" #include "widgets/NumericTextCtrl.h" -#include <wx/arrimpl.cpp> - -#define ZOOMLIMIT 0.001 - -WX_DEFINE_OBJARRAY(TrackClipArray); +#define ZOOMLIMIT 0.001f //This loads the appropriate set of cursors, depending on platform. #include "../images/Cursors.h" #include <iostream> +DEFINE_EVENT_TYPE(EVT_TRACK_PANEL_TIMER) + enum { kLeftInset = 4, kTopInset = 4, @@ -324,12 +322,8 @@ enum { OnFloatID, // <--- OnWaveformID, - OnWaveformDBID, OnSpectrumID, - OnSpectrumLogID, - OnSpectralSelID, - OnSpectralSelLogID, - OnPitchID, + OnViewSettingsID, OnSplitStereoID, OnSplitStereoMonoID, @@ -345,6 +339,18 @@ enum { OnTimeTrackLinID, OnTimeTrackLogID, OnTimeTrackLogIntID, + + // Reserve an ample block of ids for waveform scale types + OnFirstWaveformScaleID, + OnLastWaveformScaleID = OnFirstWaveformScaleID + 9, + + // Reserve an ample block of ids for spectrum scale types + OnFirstSpectrumScaleID, + OnLastSpectrumScaleID = OnFirstSpectrumScaleID + 19, + + OnZoomInVerticalID, + OnZoomOutVerticalID, + OnZoomFitVerticalID, }; BEGIN_EVENT_TABLE(TrackPanel, wxWindow) @@ -368,7 +374,8 @@ BEGIN_EVENT_TABLE(TrackPanel, wxWindow) EVT_MENU_RANGE(OnUpOctaveID, OnDownOctaveID, TrackPanel::OnChangeOctave) EVT_MENU_RANGE(OnChannelLeftID, OnChannelMonoID, TrackPanel::OnChannelChange) - EVT_MENU_RANGE(OnWaveformID, OnPitchID, TrackPanel::OnSetDisplay) + EVT_MENU_RANGE(OnWaveformID, OnSpectrumID, TrackPanel::OnSetDisplay) + EVT_MENU(OnViewSettingsID, TrackPanel::OnViewSettings) EVT_MENU_RANGE(OnRate8ID, OnRate384ID, TrackPanel::OnRateChange) EVT_MENU_RANGE(On16BitID, OnFloatID, TrackPanel::OnFormatChange) EVT_MENU(OnRateOtherID, TrackPanel::OnRateOther) @@ -385,10 +392,18 @@ BEGIN_EVENT_TABLE(TrackPanel, wxWindow) EVT_MENU(OnTimeTrackLinID, TrackPanel::OnTimeTrackLin) EVT_MENU(OnTimeTrackLogID, TrackPanel::OnTimeTrackLog) EVT_MENU(OnTimeTrackLogIntID, TrackPanel::OnTimeTrackLogInt) + + EVT_MENU_RANGE(OnFirstWaveformScaleID, OnLastWaveformScaleID, TrackPanel::OnWaveformScaleType) + EVT_MENU_RANGE(OnFirstSpectrumScaleID, OnLastSpectrumScaleID, TrackPanel::OnSpectrumScaleType) + + EVT_MENU(OnZoomInVerticalID, TrackPanel::OnZoomInVertical) + EVT_MENU(OnZoomOutVerticalID, TrackPanel::OnZoomOutVertical) + EVT_MENU(OnZoomFitVerticalID, TrackPanel::OnZoomFitVertical) END_EVENT_TABLE() /// Makes a cursor from an XPM, uses CursorId as a fallback. -static wxCursor * MakeCursor( int WXUNUSED(CursorId), const char * pXpm[36], int HotX, int HotY ) +/// TODO: Move this function to some other source file for reuse elsewhere. +wxCursor * MakeCursor( int WXUNUSED(CursorId), const char * pXpm[36], int HotX, int HotY ) { wxCursor * pCursor; @@ -552,6 +567,8 @@ TrackPanel::TrackPanel(wxWindow * parent, wxWindowID id, mLabelTrackInfoMenu = NULL; mTimeTrackMenu = NULL; + mRulerWaveformMenu = mRulerSpectrumMenu = NULL; + BuildMenus(); mTrackArtist = new TrackArtist(); @@ -584,8 +601,8 @@ TrackPanel::TrackPanel(wxWindow * parent, wxWindowID id, mSnapLeft = -1; mSnapRight = -1; - mLastCursor = -1; - mLastIndicator = -1; + mLastCursorX = -1; + mLastIndicatorX = -1; mOldQPIndicatorPos = -1; // Register for tracklist updates @@ -722,18 +739,11 @@ void TrackPanel::BuildMenus(void) /* build the pop-down menu used on wave (sampled audio) tracks */ mWaveTrackMenu = new wxMenu(); BuildCommonDropMenuItems(mWaveTrackMenu); // does name, up/down etc - mWaveTrackMenu->Append(OnWaveformID, _("Wa&veform")); - mWaveTrackMenu->Append(OnWaveformDBID, _("&Waveform (dB)")); - mWaveTrackMenu->Append(OnSpectrumID, _("&Spectrogram")); - /* i18n-hint: short form of 'logarithm'*/ - mWaveTrackMenu->Append(OnSpectrumLogID, _("Spectrogram l&og(f)")); - /* i18n-hint: Spectral Selection is spectrogram with ability to select frequencies too'*/ - mWaveTrackMenu->Append(OnSpectralSelID, _("S&pectral Selection")); - /* i18n-hint: short form of 'logarithm'*/ - mWaveTrackMenu->Append(OnSpectralSelLogID, _("Spectral Selection lo&g(f)")); - - mWaveTrackMenu->Append(OnPitchID, _("Pitc&h (EAC)")); + mWaveTrackMenu->AppendRadioItem(OnWaveformID, _("&Waveform")); + mWaveTrackMenu->AppendRadioItem(OnSpectrumID, _("&Spectrum")); + mWaveTrackMenu->Append(OnViewSettingsID, _("&View Settings...")); mWaveTrackMenu->AppendSeparator(); + mWaveTrackMenu->AppendRadioItem(OnChannelMonoID, _("&Mono")); mWaveTrackMenu->AppendRadioItem(OnChannelLeftID, _("&Left Channel")); mWaveTrackMenu->AppendRadioItem(OnChannelRightID, _("&Right Channel")); @@ -771,6 +781,16 @@ void TrackPanel::BuildMenus(void) mLabelTrackInfoMenu->Append(OnCopySelectedTextID, _("&Copy")); mLabelTrackInfoMenu->Append(OnPasteSelectedTextID, _("&Paste")); mLabelTrackInfoMenu->Append(OnDeleteSelectedLabelID, _("&Delete Label")); + + mRulerWaveformMenu = new wxMenu(); + BuildVRulerMenuItems + (mRulerWaveformMenu, OnFirstWaveformScaleID, + WaveformSettings::GetScaleNames()); + + mRulerSpectrumMenu = new wxMenu(); + BuildVRulerMenuItems + (mRulerSpectrumMenu, OnFirstSpectrumScaleID, + SpectrogramSettings::GetScaleNames()); } void TrackPanel::BuildCommonDropMenuItems(wxMenu * menu) @@ -785,6 +805,19 @@ void TrackPanel::BuildCommonDropMenuItems(wxMenu * menu) } +// static +void TrackPanel::BuildVRulerMenuItems +(wxMenu * menu, int firstId, const wxArrayString &names) +{ + int id = firstId; + for (int ii = 0, nn = names.size(); ii < nn; ++ii) + menu->AppendRadioItem(id++, names[ii]); + menu->AppendSeparator(); + menu->Append(OnZoomInVerticalID, _("Zoom In\tLeft-Click/Left-Drag")); + menu->Append(OnZoomOutVerticalID, _("Zoom Out\tShift-Left-Click")); + menu->Append(OnZoomFitVerticalID, _("Zoom to Fit\tShift-Right-Click")); +} + void TrackPanel::DeleteMenus(void) { // Note that the submenus (mRateMenu, ...) @@ -813,6 +846,9 @@ void TrackPanel::DeleteMenus(void) delete mTimeTrackMenu; mTimeTrackMenu = NULL; } + + delete mRulerWaveformMenu; + delete mRulerSpectrumMenu; } #ifdef EXPERIMENTAL_OUTPUT_DISPLAY @@ -847,7 +883,6 @@ void TrackPanel::UpdatePrefs() #ifdef EXPERIMENTAL_SCROLLING_LIMITS gPrefs->Read(wxT("/GUI/ScrollBeyondZero"), &mScrollBeyondZero, false); #endif - mdBr = gPrefs->Read(wxT("/GUI/EnvdBRange"), ENV_DB_RANGE); gPrefs->Read(wxT("/GUI/AutoScroll"), &mViewInfo->bUpdateTrackIndicator, true); gPrefs->Read(wxT("/GUI/AdjustSelectionEdges"), &mAdjustSelectionEdges, @@ -869,6 +904,8 @@ void TrackPanel::UpdatePrefs() UpdateVirtualStereoOrder(); #endif + mViewInfo->UpdatePrefs(); + if (mTrackArtist) { mTrackArtist->UpdatePrefs(); } @@ -1015,30 +1052,9 @@ void TrackPanel::OnTimer() wxCommandEvent dummyEvent; AudacityProject *p = GetProject(); - if ((p->GetAudioIOToken() > 0) && - gAudioIO->IsStreamActive(p->GetAudioIOToken())) { - // Update lyrics display. - LyricsWindow* pLyricsWindow = p->GetLyricsWindow(); - if (pLyricsWindow) - { - Lyrics* pLyricsPanel = pLyricsWindow->GetLyricsPanel(); - pLyricsPanel->Update(gAudioIO->GetStreamTime()); - } - } - - //v Vaughan, 2011-02-25: Moved this update back here from audacityAudioCallback. - // See note there. - // Vaughan, 2010-01-30: - // Since all we're doing here is updating the meters, I moved it to - // audacityAudioCallback where it calls gAudioIO->mOutputMeter->UpdateDisplay(). - MixerBoard* pMixerBoard = this->GetMixerBoard(); - if (pMixerBoard && - (p->GetAudioIOToken() > 0) && - gAudioIO->IsStreamActive(p->GetAudioIOToken())) - { - pMixerBoard->UpdateMeters(gAudioIO->GetStreamTime(), - (p->mLastPlayMode == loopedPlay)); + wxCommandEvent e(EVT_TRACK_PANEL_TIMER); + p->ProcessEvent(e); } #ifdef EXPERIMENTAL_SCRUBBING_BASIC @@ -1079,25 +1095,11 @@ void TrackPanel::OnTimer() #endif // Check whether we were playing or recording, but the stream has stopped. - if (p->GetAudioIOToken()>0 && - !gAudioIO->IsStreamActive(p->GetAudioIOToken())) + if (p->GetAudioIOToken()>0 && !IsAudioActive()) { //the stream may have been started up after this one finished (by some other project) //in that case reset the buttons don't stop the stream p->GetControlToolBar()->StopPlaying(!gAudioIO->IsStreamActive()); - - // Reset lyrics display. - LyricsWindow* pLyricsWindow = p->GetLyricsWindow(); - if (pLyricsWindow) - { - Lyrics* pLyricsPanel = pLyricsWindow->GetLyricsPanel(); - pLyricsPanel->Update(p->GetSel0()); - } - - // Vaughan, 2011-01-28: No longer doing this on timer. - // Now it's in AudioIO::SetMeters() and AudioIO::StopStream(), as with Meter Toolbar meters. - //if (pMixerBoard) - // pMixerBoard->ResetMeters(false); } // Next, check to see if we were playing or recording @@ -1119,8 +1121,8 @@ void TrackPanel::OnTimer() // that indicates where the current play/record position is. (This also // draws the moving vertical line.) - if (!gAudioIO->IsPaused() && - ( mIndicatorShowing || gAudioIO->IsStreamActive(p->GetAudioIOToken())) + if (!gAudioIO->IsPaused() && ( mIndicatorShowing || IsAudioActive()) + #ifdef EXPERIMENTAL_SCRUBBING_SMOOTH_SCROLL && !mSmoothScrollingScrub #endif @@ -1129,8 +1131,7 @@ void TrackPanel::OnTimer() DrawIndicator(); } - if(gAudioIO->IsStreamActive(p->GetAudioIOToken()) && - gAudioIO->GetNumCaptureChannels()) { + if(IsAudioActive() && gAudioIO->GetNumCaptureChannels()) { // Periodically update the display while recording @@ -1239,40 +1240,36 @@ void TrackPanel::DoDrawIndicator (wxDC & dc, bool repairOld /* = false */, double indicator /* = -1 */) { bool onScreen; - int x; double pos; if (!repairOld) { // Erase the old indicator. - if( mLastIndicator != -1 ) + if (mLastIndicatorX != -1) { - onScreen = between_inclusive( mViewInfo->h, - mLastIndicator, - mViewInfo->h + mViewInfo->screen ); - if( onScreen ) + onScreen = between_inclusive(GetLeftOffset(), + mLastIndicatorX, + GetLeftOffset() + mViewInfo->GetScreenWidth()); + if (onScreen) { - x = mViewInfo->TimeToPosition(mLastIndicator, GetLeftOffset()); - // LL: Keep from trying to blit outsize of the source DC. This results in a crash on // OSX due to allocating memory using negative sizes and can be caused by resizing // the project window while recording or playing. int w = dc.GetSize().GetWidth(); - if (x >= w) { - x = w - 1; + if (mLastIndicatorX >= w) { + mLastIndicatorX = w - 1; } - dc.Blit( x, 0, 1, mBacking->GetHeight(), &mBackingDC, x, 0 ); + + dc.Blit(mLastIndicatorX, 0, 1, mBacking->GetHeight(), &mBackingDC, mLastIndicatorX, 0); } // Nothing's ever perfect... // // Redraw the cursor since we may have just wiped it out - if( mLastCursor == mLastIndicator ) + if (mLastCursorX == mLastIndicatorX) { DoDrawCursor( dc ); } - - mLastIndicator = -1; } pos = indicator; @@ -1281,7 +1278,7 @@ void TrackPanel::DoDrawIndicator pos = gAudioIO->GetStreamTime(); AudacityProject *p = GetProject(); - bool audioActive = ( gAudioIO->IsStreamActive( p->GetAudioIOToken() ) != 0 ); + bool audioActive = IsAudioActive(); onScreen = between_inclusive( mViewInfo->h, pos, mViewInfo->h + mViewInfo->screen ); @@ -1309,19 +1306,16 @@ void TrackPanel::DoDrawIndicator mIndicatorShowing = ( onScreen && audioActive ); - // Remember it - mLastIndicator = pos; - } else { - pos = mLastIndicator; + // Calculate the horizontal position of the indicator + mLastIndicatorX = mViewInfo->TimeToPosition(pos, GetLeftOffset()); } + else + pos = mViewInfo->PositionToTime(mLastIndicatorX, GetLeftOffset()); // Set play/record color bool rec = (gAudioIO->GetNumCaptureChannels() > 0); AColor::IndicatorColor( &dc, !rec); - // Calculate the horizontal position of the indicator - x = mViewInfo->TimeToPosition(pos, GetLeftOffset()); - mRuler->DrawIndicator( pos, rec ); // Ensure that we don't draw through the TrackInfo or vertical ruler. @@ -1329,7 +1323,7 @@ void TrackPanel::DoDrawIndicator int leftCutoff = clip.x + GetLabelWidth(); int rightInset = kLeftInset + 2; // See the call to SetInset int rightCutoff = clip.x + clip.width - rightInset; - if (!between_inclusive(leftCutoff, x, rightCutoff)) + if (!between_inclusive(leftCutoff, mLastIndicatorX, rightCutoff)) { return; } @@ -1349,9 +1343,9 @@ void TrackPanel::DoDrawIndicator // Draw the new indicator in its new location AColor::Line(dc, - x, + mLastIndicatorX, y + kTopInset + 1, - x, + mLastIndicatorX, y + t->GetHeight() - 3 ); } } @@ -1370,38 +1364,28 @@ void TrackPanel::DrawCursor() void TrackPanel::DoDrawCursor(wxDC & dc) { bool onScreen; - int x; - if( mLastCursor != -1 ) + if( mLastCursorX != -1 ) { - onScreen = between_inclusive( mViewInfo->h, - mLastCursor, - mViewInfo->h + mViewInfo->screen ); + onScreen = between_inclusive(GetLeftOffset(), + mLastCursorX, + GetLeftOffset() + mViewInfo->GetScreenWidth()); if( onScreen ) - { - x = mViewInfo->TimeToPosition(mLastCursor, GetLeftOffset()); - - dc.Blit( x, 0, 1, mBacking->GetHeight(), &mBackingDC, x, 0 ); - } - - mLastCursor = -1; + dc.Blit(mLastCursorX, 0, 1, mBacking->GetHeight(), &mBackingDC, mLastCursorX, 0); } - mLastCursor = mViewInfo->selectedRegion.t0(); + const double time = mViewInfo->selectedRegion.t0(); + mLastCursorX = mViewInfo->TimeToPosition(time, GetLeftOffset()); onScreen = between_inclusive( mViewInfo->h, - mLastCursor, + time, mViewInfo->h + mViewInfo->screen ); if( !onScreen ) - { return; - } AColor::CursorColor( &dc ); - x = mViewInfo->TimeToPosition(mLastCursor, GetLeftOffset()); - // Draw cursor in all selected tracks VisibleTrackIterator iter( GetProject() ); for( Track *t = iter.First(); t; t = iter.Next() ) @@ -1413,14 +1397,14 @@ void TrackPanel::DoDrawCursor(wxDC & dc) wxCoord bottom = y + t->GetHeight() - kTopInset; // MB: warp() is not needed here as far as I know, in fact it creates a bug. Removing it fixes that. - AColor::Line( dc, x, top, x, bottom ); // <-- The whole point of this routine. + AColor::Line(dc, mLastCursorX, top, mLastCursorX, bottom); // <-- The whole point of this routine. #ifdef EXPERIMENTAL_OUTPUT_DISPLAY if(MONO_WAVE_PAN(t)){ y = t->GetY(true) - mViewInfo->vpos + 1; top = y + kTopInset; bottom = y + t->GetHeight(true) - kTopInset; - AColor::Line( dc, x, top, x, bottom ); + AColor::Line( dc, mLastCursorX, top, mLastCursorX, bottom ); } #endif @@ -1428,7 +1412,7 @@ void TrackPanel::DoDrawCursor(wxDC & dc) } // AS: Ah, no, this is where we draw the blinky thing in the ruler. - mRuler->DrawCursor( mLastCursor ); + mRuler->DrawCursor( time ); DisplaySelection(); } @@ -1494,8 +1478,7 @@ void TrackPanel::OnPaint(wxPaintEvent & /* event */) mRefreshBacking = false; #ifdef EXPERIMENTAL_SCRUBBING_SMOOTH_SCROLL - if (mSmoothScrollingScrub && - gAudioIO->IsStreamActive(GetProject()->GetAudioIOToken())) { + if (mSmoothScrollingScrub && IsAudioActive()) { // Pan the view, so that we center the play indicator. // By the time DoDrawIndicator() is reached, gAudioIO->GetStreamTime() // may be a little different. @@ -1530,9 +1513,7 @@ void TrackPanel::OnPaint(wxPaintEvent & /* event */) // Update the indicator in case it was damaged if this project is playing - AudacityProject* p = GetProject(); - if (!gAudioIO->IsPaused() && - (mIndicatorShowing || gAudioIO->IsStreamActive(p->GetAudioIOToken()))) + if (!gAudioIO->IsPaused() && (mIndicatorShowing || IsAudioActive())) { // If not smooth scrolling, then // we just want to repair, not update the old, so set the second param to true. @@ -1622,7 +1603,6 @@ void TrackPanel::HandleEscapeKey(bool down) break; default: return; - ; } // Common part in all cases that do anything @@ -1678,11 +1658,14 @@ MixerBoard* TrackPanel::GetMixerBoard() /// edits at the moment. /// @return true if audio is being recorded or is playing. bool TrackPanel::IsUnsafe() +{ + return IsAudioActive(); +} + +bool TrackPanel::IsAudioActive() { AudacityProject *p = GetProject(); - bool bUnsafe = (p->GetAudioIOToken()>0 && - gAudioIO->IsStreamActive(p->GetAudioIOToken())); - return bUnsafe; + return p->IsAudioActive(); } @@ -1714,43 +1697,48 @@ bool TrackPanel::SetCursorByActivity( ) SetCursor( unsafe ? *mDisabledCursor : *mStretchCursor); return true; #endif - case IsOverCutLine: - SetCursor( unsafe ? *mDisabledCursor : *mArrowCursor); - // what, no return true here? -- PRL default: break; } return false; } +bool TrackPanel::SetCursorForCutline(WaveTrack * track, wxRect &rect, wxMouseEvent &event) +{ + if (IsOverCutline(track, rect, event)) { + bool unsafe = IsUnsafe(); + SetCursor(unsafe ? *mDisabledCursor : *mArrowCursor); + return true; + // No tip string? + } + return false; +} + /// When in the "label" (TrackInfo or vertical ruler), we can either vertical zoom or re-order tracks. /// Dont't change cursor/tip to zoom if display is not waveform (either linear of dB) or Spectrum void TrackPanel::SetCursorAndTipWhenInLabel( Track * t, - wxMouseEvent &event, const wxChar ** ppTip ) + wxMouseEvent &event, wxString &tip ) { - if (event.m_x >= GetVRulerOffset() && - (t->GetKind() == Track::Wave) && - ( ((WaveTrack *) t)->GetDisplay() != WaveTrack::PitchDisplay) ) + if (event.m_x >= GetVRulerOffset() && (t->GetKind() == Track::Wave) ) { - *ppTip = _("Click to vertically zoom in. Shift-click to zoom out. Drag to specify a zoom region."); + tip = _("Click to vertically zoom in. Shift-click to zoom out. Drag to specify a zoom region."); SetCursor(event.ShiftDown()? *mZoomOutCursor : *mZoomInCursor); } #ifdef USE_MIDI else if (event.m_x >= GetVRulerOffset() && t->GetKind() == Track::Note) { - *ppTip = _("Click to verticaly zoom in, Shift-click to zoom out, Drag to create a particular zoom region."); + tip = _("Click to verticaly zoom in, Shift-click to zoom out, Drag to create a particular zoom region."); SetCursor(event.ShiftDown() ? *mZoomOutCursor : *mZoomInCursor); } #endif else { // Set a status message if over TrackInfo. - *ppTip = _("Drag the track vertically to change the order of the tracks."); + tip = _("Drag the track vertically to change the order of the tracks."); SetCursor(*mArrowCursor); } } /// When in the resize area we can adjust size or relative size. -void TrackPanel::SetCursorAndTipWhenInVResizeArea( Track * label, - bool bLinked, const wxChar ** ppTip ) +void TrackPanel::SetCursorAndTipWhenInVResizeArea( bool bLinked, wxString &tip ) { // Check to see whether it is the first channel of a stereo track if (bLinked) { @@ -1758,15 +1746,10 @@ void TrackPanel::SetCursorAndTipWhenInVResizeArea( Track * label, // not actually in the resize area at all. (The resize area // is shorter when it is between stereo tracks). - // IF we are in the label THEN return. - // Subsequently called methods can detect that a tip and - // cursor are still needed. - if (label) - return; - *ppTip = _("Click and drag to adjust relative size of stereo tracks."); + tip = _("Click and drag to adjust relative size of stereo tracks."); SetCursor(*mResizeCursor); } else { - *ppTip = _("Click and drag to resize the track."); + tip = _("Click and drag to resize the track."); SetCursor(*mResizeCursor); } } @@ -1774,7 +1757,7 @@ void TrackPanel::SetCursorAndTipWhenInVResizeArea( Track * label, /// When in a label track, find out if we've hit anything that /// would cause a cursor change. void TrackPanel::SetCursorAndTipWhenInLabelTrack( LabelTrack * pLT, - wxMouseEvent & event, const wxChar ** ppTip ) + wxMouseEvent & event, wxString &tip ) { int edge=pLT->OverGlyph(event.m_x, event.m_y); if(edge !=0) @@ -1795,7 +1778,7 @@ void TrackPanel::SetCursorAndTipWhenInLabelTrack( LabelTrack * pLT, // signal this by setting the tip. if( edge != 0 ) { - *ppTip = + tip = (pLT->mbHitCenter ) ? _("Drag one or more label boundaries.") : _("Drag label boundary."); @@ -1805,20 +1788,15 @@ void TrackPanel::SetCursorAndTipWhenInLabelTrack( LabelTrack * pLT, namespace { // This returns true if we're a spectral editing track. -inline bool isSpectrogramTrack(const Track *pTrack, bool *pLogf = NULL) { +inline bool isSpectralSelectionTrack(const Track *pTrack) { if (pTrack && pTrack->GetKind() == Track::Wave) { - const int display = - static_cast<const WaveTrack*>(pTrack)->GetDisplay(); - const bool logF = (display == WaveTrack::SpectrumLogDisplay) || - (display == WaveTrack::SpectralSelectionLogDisplay); - if (pLogf) - *pLogf = logF; - return (display == WaveTrack::SpectralSelectionLogDisplay) || (display == WaveTrack::SpectralSelectionDisplay); + const WaveTrack *const wt = static_cast<const WaveTrack*>(pTrack); + const SpectrogramSettings &settings = wt->GetSpectrogramSettings(); + const int display = wt->GetDisplay(); + return (display == WaveTrack::Spectrum) && settings.SpectralSelectionEnabled(); } else { - if (pLogf) - *pLogf = false; return false; } } @@ -1826,7 +1804,7 @@ inline bool isSpectrogramTrack(const Track *pTrack, bool *pLogf = NULL) { } // namespace // If we're in OnDemand mode, we may change the tip. -void TrackPanel::MaySetOnDemandTip( Track * t, const wxChar ** ppTip ) +void TrackPanel::MaySetOnDemandTip( Track * t, wxString &tip ) { wxASSERT( t ); //For OD regions, we need to override and display the percent complete for this task. @@ -1836,17 +1814,17 @@ void TrackPanel::MaySetOnDemandTip( Track * t, const wxChar ** ppTip ) //see if the wavetrack exists in the ODManager (if the ODManager exists) if(!ODManager::IsInstanceCreated()) return; - //ask the wavetrack for the corresponding tip - it may not change **pptip, but that's fine. - ODManager::Instance()->FillTipForWaveTrack((WaveTrack*)t,ppTip); + //ask the wavetrack for the corresponding tip - it may not change tip, but that's fine. + ODManager::Instance()->FillTipForWaveTrack(static_cast<WaveTrack*>(t), tip); return; } #ifdef EXPERIMENTAL_SPECTRAL_EDITING void TrackPanel::HandleCenterFrequencyCursor -(bool shiftDown, const wxChar ** ppTip, const wxCursor ** ppCursor) +(bool shiftDown, wxString &tip, const wxCursor ** ppCursor) { #ifndef SPECTRAL_EDITING_ESC_KEY - *ppTip = + tip = shiftDown ? _("Click and drag to move center selection frequency.") : _("Click and drag to move center selection frequency to a spectral peak."); @@ -1854,7 +1832,7 @@ void TrackPanel::HandleCenterFrequencyCursor #else shiftDown; - *ppTip = + tip = _("Click and drag to move center selection frequency."); #endif @@ -1891,7 +1869,7 @@ void TrackPanel::HandleCenterFrequencyClick // Determine and set the cursor and tip accordingly. void TrackPanel::SetCursorAndTipWhenSelectTool( Track * t, wxMouseEvent & event, wxRect &r, bool bMultiToolMode, - const wxChar ** ppTip, const wxCursor ** ppCursor ) + wxString &tip, const wxCursor ** ppCursor ) { // Do not set the default cursor here and re-set later, that causes // flashing. @@ -1909,13 +1887,10 @@ void TrackPanel::SetCursorAndTipWhenSelectTool( Track * t, keyStr = _("Edit, Preferences..."); else keyStr = KeyStringDisplay(keyStr); - // Must compose a string that survives the function call, hence static. - static wxString result; /* i18n-hint: %s is usually replaced by "Ctrl+P" for Windows/Linux, "Command+," for Mac */ - result = wxString::Format( + tip = wxString::Format( _("Multi-Tool Mode: %s for Mouse and Keyboard Preferences."), keyStr.c_str()); - *ppTip = result; // Later in this function we may point to some other string instead. } @@ -1928,7 +1903,7 @@ void TrackPanel::SetCursorAndTipWhenSelectTool( Track * t, // the preferences... if ( !t->GetSelected() || !mAdjustSelectionEdges) { - MaySetOnDemandTip( t, ppTip ); + MaySetOnDemandTip( t, tip ); return; } @@ -1942,11 +1917,10 @@ void TrackPanel::SetCursorAndTipWhenSelectTool( Track * t, const bool bShiftDown = event.ShiftDown(); #ifdef EXPERIMENTAL_SPECTRAL_EDITING - bool logF; if ( (mFreqSelMode == FREQ_SEL_SNAPPING_CENTER) && - isSpectrogramTrack(t, &logF) ) { + isSpectralSelectionTrack(t)) { // Not shift-down, but center frequency snapping toggle is on - *ppTip = _("Click and drag to set frequency bandwidth."); + tip = _("Click and drag to set frequency bandwidth."); *ppCursor = mEnvelopeCursor; return; } @@ -1972,7 +1946,7 @@ void TrackPanel::SetCursorAndTipWhenSelectTool( Track * t, case SBLeft: case SBRight: if ( HitTestStretch(t, r, event)) { - *ppTip = _("Click and drag to stretch within selected region."); + tip = _("Click and drag to stretch within selected region."); *ppCursor = mStretchCursor; return; } @@ -1987,33 +1961,33 @@ void TrackPanel::SetCursorAndTipWhenSelectTool( Track * t, if( bShiftDown ){ // wxASSERT( false ); // Same message is used for moving left right top or bottom edge. - *ppTip = _("Click to move selection boundary to cursor."); + tip = _("Click to move selection boundary to cursor."); // No cursor change. return; } break; case SBLeft: - *ppTip = _("Click and drag to move left selection boundary."); + tip = _("Click and drag to move left selection boundary."); *ppCursor = mAdjustLeftSelectionCursor; return; case SBRight: - *ppTip = _("Click and drag to move right selection boundary."); + tip = _("Click and drag to move right selection boundary."); *ppCursor = mAdjustRightSelectionCursor; return; #ifdef EXPERIMENTAL_SPECTRAL_EDITING case SBBottom: - *ppTip = _("Click and drag to move bottom selection frequency."); + tip = _("Click and drag to move bottom selection frequency."); *ppCursor = mBottomFrequencyCursor; return; case SBTop: - *ppTip = _("Click and drag to move top selection frequency."); + tip = _("Click and drag to move top selection frequency."); *ppCursor = mTopFrequencyCursor; return; case SBCenter: - HandleCenterFrequencyCursor(bShiftDown, ppTip, ppCursor); + HandleCenterFrequencyCursor(bShiftDown, tip, ppCursor); return; case SBWidth: - *ppTip = _("Click and drag to adjust frequency bandwidth."); + tip = _("Click and drag to adjust frequency bandwidth."); *ppCursor = mBandWidthCursor; return; #endif @@ -2022,13 +1996,13 @@ void TrackPanel::SetCursorAndTipWhenSelectTool( Track * t, } // switch // Falls through the switch if there was no boundary found. - MaySetOnDemandTip( t, ppTip ); + MaySetOnDemandTip( t, tip ); } /// In this method we know what tool we are using, /// so set the cursor accordingly. void TrackPanel::SetCursorAndTipByTool( int tool, - wxMouseEvent & event, const wxChar ** /*ppTip*/ ) + wxMouseEvent & event, wxString& ) { bool unsafe = IsUnsafe(); @@ -2071,12 +2045,12 @@ void TrackPanel::HandleCursor(wxMouseEvent & event) // (2) If we are not over a track at all, set the cursor to Arrow and // clear the StatusBar, - wxRect r; - Track *label = FindTrack(event.m_x, event.m_y, true, true, &r); - Track *nonlabel = FindTrack(event.m_x, event.m_y, false, false, &r); - Track *t = label ? label : nonlabel; + wxRect labelRect, trackRect; + Track *const label = FindTrack(event.m_x, event.m_y, true, true, &labelRect); + Track *const nonlabel = FindTrack(event.m_x, event.m_y, false, false, &trackRect); + Track *const track = label ? label : nonlabel; - if (!t) { + if (!track) { SetCursor(*mArrowCursor); mListener->TP_DisplayStatusMessage(wxT("")); return; @@ -2089,30 +2063,39 @@ void TrackPanel::HandleCursor(wxMouseEvent & event) // Strategy here is to set the tip when we have determined and // set the correct cursor. We stop doing tests for what we've // hit once the tip is not NULL. - const wxChar *tip = NULL; - if (label) { - SetCursorAndTipWhenInLabel( label, event, &tip ); - } + wxString tip; // Are we within the vertical resize area? - if ((tip == NULL ) && within(event.m_y, r.y + r.height, TRACK_RESIZE_REGION)) + if (nonlabel + ? within(event.m_y, trackRect.y + trackRect.height, TRACK_RESIZE_REGION) + : within(event.m_y, labelRect.y + labelRect.height, TRACK_RESIZE_REGION)) { - SetCursorAndTipWhenInVResizeArea( label, t->GetLinked(), &tip ); + SetCursorAndTipWhenInVResizeArea(nonlabel && track->GetLinked(), tip); // tip may still be NULL at this point, in which case we go on looking. } + if ((tip == wxString()) && label) { + SetCursorAndTipWhenInLabel( label, event, tip ); + } + // Otherwise, we must be over a track of some kind // Is it a label track? - if ((tip==NULL) && (t->GetKind() == Track::Label)) + if ((tip == wxString()) && (track->GetKind() == Track::Label)) { // We are over a label track - SetCursorAndTipWhenInLabelTrack( (LabelTrack*)t, event, &tip ); + SetCursorAndTipWhenInLabelTrack( static_cast<LabelTrack*>(track), event, tip ); // ..and if we haven't yet determined the cursor, // we go on to do all the standard track hit tests. } - if( tip==NULL ) + if ((tip == wxString()) && + nonlabel && + nonlabel->GetKind() == Track::Wave && + SetCursorForCutline(static_cast<WaveTrack*>(nonlabel), trackRect, event)) + return; + + if( tip == wxString() ) { ToolsToolBar * ttb = mListener->TP_GetToolsToolBar(); if( ttb == NULL ) @@ -2131,21 +2114,21 @@ void TrackPanel::HandleCursor(wxMouseEvent & event) // the other tool cases. if( tool != selectTool ) { - SetCursorAndTipByTool( tool, event, &tip); + SetCursorAndTipByTool( tool, event, tip); } else { bool bMultiToolMode = ttb->IsDown(multiTool); const wxCursor *pSelection = 0; SetCursorAndTipWhenSelectTool - ( t, event, r, bMultiToolMode, &tip, &pSelection ); + ( track, event, trackRect, bMultiToolMode, tip, &pSelection ); if (pSelection) // Set cursor once only here, to avoid flashing during drags SetCursor(*pSelection); } } - if (tip) + if (tip != wxString()) mListener->TP_DisplayStatusMessage(tip); } @@ -2161,7 +2144,7 @@ void TrackPanel::HandleSelect(wxMouseEvent & event) // AS: Ok, did the user just click the mouse, release the mouse, // or drag? if (event.LeftDown() || - (event.LeftDClick() && event.CmdDown())) { + (event.LeftDClick() && event.CmdDown())) { // AS: Now, did they click in a track somewhere? If so, we want // to extend the current selection or start a new selection, // depending on the shift key. If not, cancel all selections. @@ -2220,7 +2203,7 @@ void TrackPanel::HandleSelect(wxMouseEvent & event) selectedClip->GetOffset(), selectedClip->GetEndTime()); } //Also, capture this track for dragging until we up-click. - mCapturedClipArray.Add(TrackClip(w, selectedClip)); + mCapturedClipArray.push_back(TrackClip(w, selectedClip)); mMouseCapture = IsSliding; @@ -2243,15 +2226,6 @@ void TrackPanel::HandleSelect(wxMouseEvent & event) #endif done: SelectionHandleDrag(event, t); - - // Update lyrics display for new selection. - AudacityProject* pProj = GetActiveProject(); - LyricsWindow* pLyricsWindow = pProj->GetLyricsWindow(); - if (pLyricsWindow && pLyricsWindow->IsShown()) - { - Lyrics* pLyricsPanel = pLyricsWindow->GetLyricsPanel(); - pLyricsPanel->Update(pProj->GetSel0()); - } } @@ -2533,8 +2507,6 @@ void TrackPanel::SelectionHandleClick(wxMouseEvent & event, mCapturedTrack = pTrack; mCapturedRect = r; - mMouseClickX = event.m_x; - mMouseClickY = event.m_y; mMouseCapture=IsSelecting; mInitialSelection = mViewInfo->selectedRegion; @@ -2680,9 +2652,8 @@ void TrackPanel::SelectionHandleClick(wxMouseEvent & event, // preferences now if (mAdjustSelectionEdges) { #ifdef EXPERIMENTAL_SPECTRAL_EDITING - bool logF; if (mFreqSelMode == FREQ_SEL_SNAPPING_CENTER && - isSpectrogramTrack(pTrack, &logF)) { + isSpectralSelectionTrack(pTrack)) { // Ignore whether we are inside the time selection. // Exit center-snapping, start dragging the width. mFreqSelMode = FREQ_SEL_PINNED_CENTER; @@ -2990,10 +2961,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(); const double rate = pTrack->GetRate(); const double nyq = rate / 2.0; const double binFrequency = rate / windowSize; @@ -3030,7 +3001,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; @@ -3055,12 +3026,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(); 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); @@ -3072,10 +3044,9 @@ void TrackPanel::MoveSnappingFreqSelection (int mouseYCoordinate, int trackTopEdge, int trackHeight, Track *pTrack) { - bool logF; if (pTrack && pTrack->GetSelected() && - isSpectrogramTrack(pTrack, &logF)) { + isSpectralSelectionTrack(pTrack)) { WaveTrack *const wt = static_cast<WaveTrack*>(pTrack); // PRL: // What happens if center snapping selection began in one spectrogram track, @@ -3085,8 +3056,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); const double snappedFrequency = mFrequencySnapper->FindPeak(frequency, NULL); const double maxRatio = findMaxRatio(snappedFrequency, rate); @@ -3118,17 +3089,14 @@ void TrackPanel::StartFreqSelection (int mouseYCoordinate, int trackTopEdge, mFreqSelMode = FREQ_SEL_INVALID; mFreqSelPin = SelectedRegion::UndefinedFrequency; - bool logF; - if (isSpectrogramTrack(pTrack, &logF)) { + if (isSpectralSelectionTrack(pTrack)) { 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); + mViewInfo->selectedRegion.setFrequencies(mFreqSelPin, mFreqSelPin); } - - mViewInfo->selectedRegion.setFrequencies(mFreqSelPin, mFreqSelPin); } void TrackPanel::ExtendFreqSelection(int mouseYCoordinate, int trackTopEdge, @@ -3145,14 +3113,10 @@ void TrackPanel::ExtendFreqSelection(int mouseYCoordinate, int trackTopEdge, // started, and that is of a spectrogram display type. const WaveTrack* wt = mFreqSelTrack; - const int display = wt->GetDisplay(); - const bool logF = (display == WaveTrack::SpectrumLogDisplay) || - (display == WaveTrack::SpectralSelectionLogDisplay) - ; const double rate = wt->GetRate(); const double frequency = - PositionToFrequency(true, mouseYCoordinate, - trackTopEdge, trackHeight, rate, logF); + PositionToFrequency(wt, true, mouseYCoordinate, + trackTopEdge, trackHeight); // Dragging center? if (mFreqSelMode == FREQ_SEL_DRAG_CENTER) { @@ -3415,12 +3379,7 @@ void TrackPanel::Stretch(int mouseXCoordinate, int trackLeftEdge, void TrackPanel::SelectionHandleDrag(wxMouseEvent & event, Track *clickedTrack) { #ifdef EXPERIMENTAL_SCRUBBING_BASIC - if (IsScrubbing()) { - // May need a screen update. - if (mAutoScrolling) - UpdateSelectionDisplay(); - } - else if (mScrubStartPosition >= 0) { + if (mScrubStartPosition >= 0) { MaybeStartScrubbing(event); // Do nothing more, don't change selection return; @@ -3527,13 +3486,14 @@ 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 + int trackHeight) const { + const double rate = wt->GetRate(); + // Handle snapping if (maySnap && mouseYCoordinate - trackTopEdge < FREQ_SNAP_DISTANCE) @@ -3542,62 +3502,23 @@ double TrackPanel::PositionToFrequency(bool maySnap, trackTopEdge + trackHeight - mouseYCoordinate < FREQ_SNAP_DISTANCE) return -1; + const SpectrogramSettings &settings = wt->GetSpectrogramSettings(); + const NumberScale numberScale(settings.GetScale(rate, false)); 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)); - 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)); - return p * minFreq + (1.0 - p) * maxFreq; - } + return numberScale.PositionToValue(1.0 - p); } /// 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 + int trackHeight) const { - const int freq = lrint(rate/2.); - double p = 0; - - if (logF) - { - const double maxFreq = - std::min(freq, mTrackArtist->GetSpectrumLogMaxFreq(freq)); - const double minFreq = - std::max(1, mTrackArtist->GetSpectrumLogMinFreq(1)); - if (maxFreq > minFreq) - { - const double - logFrequency = log(frequency < 1.0 ? 1.0 : frequency), - logMinFreq = log(minFreq), - logMaxFreq = log(maxFreq); - p = (logFrequency - logMinFreq) / (logMaxFreq - logMinFreq); - } - } - else - { - const double maxFreq = - std::min(freq, mTrackArtist->GetSpectrumMaxFreq(freq)); - const double minFreq = - std::max(0, mTrackArtist->GetSpectrumMinFreq(0)); - if (maxFreq > minFreq) - p = (frequency - minFreq) / (maxFreq - minFreq); - } + const double rate = wt->GetRate(); + const SpectrogramSettings &settings = wt->GetSpectrogramSettings(); + const NumberScale numberScale(settings.GetScale(rate, false)); + const float p = numberScale.ValueToPosition(frequency); return trackTopEdge + wxInt64((1.0 - p) * trackHeight); } #endif @@ -3678,20 +3599,17 @@ bool mayDragWidth, bool onlyWithinSnapDistance, bool chooseTime = true; bool chooseBottom = true; bool chooseCenter = false; - bool logF; // Consider adjustment of frequencies only if mouse is // within the time boundaries if (!mViewInfo->selectedRegion.isPoint() && t0 <= selend && selend < t1 && - isSpectrogramTrack(pTrack, &logF)) { + isSpectralSelectionTrack(pTrack)) { 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) : 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) : rect.y; wxInt64 signedBottomDist = int(event.m_y - bottomSel); wxInt64 verticalDist = abs(signedBottomDist); @@ -3709,8 +3627,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); const wxInt64 centerDist = abs(int(event.m_y - centerSel)); if (centerDist < verticalDist) chooseCenter = true, verticalDist = centerDist, @@ -3761,11 +3678,13 @@ void TrackPanel::HandleEnvelope(wxMouseEvent & event) { if (event.LeftDown()) { wxRect r; - mCapturedTrack = FindTrack(event.m_x, event.m_y, false, false, &r); + Track *pTrack = FindTrack(event.m_x, event.m_y, false, false, &r); - if (!mCapturedTrack) + if (!pTrack) return; + SetCapturedTrack(pTrack, IsEnveloping); + if (mCapturedTrack->GetKind() == Track::Wave) { mCapturedEnvelope = @@ -3807,9 +3726,9 @@ void TrackPanel::ForwardEventToTimeTrackEnvelope(wxMouseEvent & event) double lower = ptimetrack->GetRangeLower(), upper = ptimetrack->GetRangeUpper(); if(ptimetrack->GetDisplayLog()) { // MB: silly way to undo the work of GetWaveYPos while still getting a logarithmic scale - double dBRange = gPrefs->Read(wxT("/GUI/EnvdBRange"), ENV_DB_RANGE); - lower = 20.0 * log10(std::max(1.0e-7, lower)) / dBRange + 1.0; - upper = 20.0 * log10(std::max(1.0e-7, upper)) / dBRange + 1.0; + double dBRange = mViewInfo->dBr; + lower = LINEAR_TO_DB(std::max(1.0e-7, lower)) / dBRange + 1.0; + upper = LINEAR_TO_DB(std::max(1.0e-7, upper)) / dBRange + 1.0; } bool needUpdate = pspeedenvelope->MouseEvent( @@ -3837,10 +3756,8 @@ void TrackPanel::ForwardEventToWaveTrackEnvelope(wxMouseEvent & event) // This asks which one is in use. (ie, Wave, Spectrum, etc) int display = pwavetrack->GetDisplay(); - // AS: If we're using the right type of display for envelope operations - // ie one of the Wave displays - const bool dB = (display == WaveTrack::WaveformDBDisplay); - if (dB || (display == WaveTrack::WaveformDisplay)) { + if (display == WaveTrack::Waveform) { + const bool dB = !pwavetrack->GetWaveformSettings().isLinear(); bool needUpdate; // AS: Then forward our mouse event to the envelope. @@ -3931,7 +3848,7 @@ void TrackPanel::HandleSlide(wxMouseEvent & event) if (mDidSlideVertically && mCapturedTrack) // Now that user has dropped the clip into a different track, // make sure the sample rate matches the destination track (mCapturedTrack). - for (size_t i = 0; i < mCapturedClipArray.GetCount(); i++) + for (size_t i = 0; i < mCapturedClipArray.size(); i++) if (mCapturedTrack->GetKind() == Track::Wave) // Should always be true here, but make sure. { WaveClip* pWaveClip = mCapturedClipArray[i].clip; @@ -4019,7 +3936,7 @@ void TrackPanel::StartSlide(wxMouseEvent & event) // The captured clip is the focus, but we need to create a list // of all clips that have to move, also... - mCapturedClipArray.Clear(); + mCapturedClipArray.clear(); double clickTime = mViewInfo->PositionToTime(event.m_x, GetLeftOffset()); @@ -4042,7 +3959,7 @@ void TrackPanel::StartSlide(wxMouseEvent & event) } else { mCapturedClipIsSelection = false; - mCapturedClipArray.Add(TrackClip(vt, mCapturedClip)); + mCapturedClipArray.push_back(TrackClip(vt, mCapturedClip)); // Check for stereo partner Track *partner = mTracks->GetLink(vt); @@ -4056,7 +3973,7 @@ void TrackPanel::StartSlide(wxMouseEvent & event) if (s0 >= 0) { WaveClip *clip = ((WaveTrack *)partner)->GetClipAtSample(s0); if (clip) { - mCapturedClipArray.Add(TrackClip(partner, clip)); + mCapturedClipArray.push_back(TrackClip(partner, clip)); } } } @@ -4069,7 +3986,7 @@ void TrackPanel::StartSlide(wxMouseEvent & event) // clips are considered (the effect is like recursion and terminates // because AddClipsToCaptured doesn't add duplicate clips); to remove // this behavior just store the array size beforehand. - for (unsigned int i = 0; i < mCapturedClipArray.GetCount(); ++i) { + for (unsigned int i = 0; i < mCapturedClipArray.size(); ++i) { // Capture based on tracks that have clips -- that means we // don't capture based on links to label tracks for now (until // we can treat individual labels as clips) @@ -4101,7 +4018,7 @@ void TrackPanel::StartSlide(wxMouseEvent & event) } else { mCapturedClip = NULL; - mCapturedClipArray.Clear(); + mCapturedClipArray.clear(); } mSlideUpDownOnly = event.CmdDown() && !multiToolModeActive; @@ -4160,7 +4077,7 @@ void TrackPanel::AddClipsToCaptured(Track *t, double t0, double t1) { // Avoid getting clips that were already captured bool newClip = true; - for (unsigned int i = 0; i < mCapturedClipArray.GetCount(); ++i) { + for (unsigned int i = 0; i < mCapturedClipArray.size(); ++i) { if (mCapturedClipArray[i].clip == clip) { newClip = false; break; @@ -4168,7 +4085,7 @@ void TrackPanel::AddClipsToCaptured(Track *t, double t0, double t1) } if (newClip) - mCapturedClipArray.Add(TrackClip(t, clip)); + mCapturedClipArray.push_back(TrackClip(t, clip)); } it = it->GetNext(); } @@ -4180,7 +4097,7 @@ void TrackPanel::AddClipsToCaptured(Track *t, double t0, double t1) // Avoid adding a track twice bool newClip = true; - for (unsigned int i = 0; i < mCapturedClipArray.GetCount(); ++i) { + for (unsigned int i = 0; i < mCapturedClipArray.size(); ++i) { if (mCapturedClipArray[i].track == t) { newClip = false; break; @@ -4195,7 +4112,7 @@ void TrackPanel::AddClipsToCaptured(Track *t, double t0, double t1) return; } #endif - mCapturedClipArray.Add(TrackClip(t, NULL)); + mCapturedClipArray.push_back(TrackClip(t, NULL)); } } } @@ -4227,11 +4144,11 @@ void TrackPanel::DoSlide(wxMouseEvent & event) // happens relative to the original horizontal position of // each clip... #ifdef USE_MIDI - if (mCapturedClipArray.GetCount()) { + if (mCapturedClipArray.size()) { #else if (mCapturedClip) { #endif - for(i=0; i<mCapturedClipArray.GetCount(); i++) { + for(i=0; i<mCapturedClipArray.size(); i++) { if (mCapturedClipArray[i].clip) mCapturedClipArray[i].clip->Offset(-mHSlideAmount); else @@ -4261,7 +4178,7 @@ void TrackPanel::DoSlide(wxMouseEvent & event) mtw->GetRate(); // set it to a sample point } // Adjust desiredSlideAmount using SnapManager - if (mSnapManager && mCapturedClipArray.GetCount()) { + if (mSnapManager && mCapturedClipArray.size()) { double clipLeft; double clipRight; if (mCapturedClip) { @@ -4335,7 +4252,7 @@ void TrackPanel::DoSlide(wxMouseEvent & event) // Temporary apply the offset because we want to see if the // track fits with the desired offset - for(i=0; i<mCapturedClipArray.GetCount(); i++) + for(i=0; i<mCapturedClipArray.size(); i++) if (mCapturedClipArray[i].clip) mCapturedClipArray[i].clip->Offset(desiredSlideAmount); // See if it can be moved @@ -4356,7 +4273,7 @@ void TrackPanel::DoSlide(wxMouseEvent & event) } else { // Undo the offset - for(i=0; i<mCapturedClipArray.GetCount(); i++) + for(i=0; i<mCapturedClipArray.size(); i++) if (mCapturedClipArray[i].clip) mCapturedClipArray[i].clip->Offset(-desiredSlideAmount); } @@ -4377,7 +4294,7 @@ void TrackPanel::DoSlide(wxMouseEvent & event) } #ifdef USE_MIDI - if (mCapturedClipArray.GetCount()) { + if (mCapturedClipArray.size()) { #else if (mCapturedClip) { #endif @@ -4390,7 +4307,7 @@ void TrackPanel::DoSlide(wxMouseEvent & event) initialAllowed = mHSlideAmount; unsigned int i, j; - for(i=0; i<mCapturedClipArray.GetCount(); i++) { + for(i=0; i<mCapturedClipArray.size(); i++) { WaveTrack *track = (WaveTrack *)mCapturedClipArray[i].track; WaveClip *clip = mCapturedClipArray[i].clip; @@ -4399,7 +4316,7 @@ void TrackPanel::DoSlide(wxMouseEvent & event) // temporarily because they're all moving together and // we want to find out if OTHER clips are in the way, // not one of the moving ones - for(j=0; j<mCapturedClipArray.GetCount(); j++) { + for(j=0; j<mCapturedClipArray.size(); j++) { WaveClip *clip2 = mCapturedClipArray[j].clip; if (clip2 && clip2 != clip) clip2->Offset(-safeBigDistance); @@ -4411,7 +4328,7 @@ void TrackPanel::DoSlide(wxMouseEvent & event) else mHSlideAmount = 0.0; - for(j=0; j<mCapturedClipArray.GetCount(); j++) { + for(j=0; j<mCapturedClipArray.size(); j++) { WaveClip *clip2 = mCapturedClipArray[j].clip; if (clip2 && clip2 != clip) clip2->Offset(safeBigDistance); @@ -4422,7 +4339,7 @@ void TrackPanel::DoSlide(wxMouseEvent & event) if (mHSlideAmount != 0.0) { // finally, here is where clips are moved unsigned int i; - for(i=0; i<mCapturedClipArray.GetCount(); i++) { + for(i=0; i<mCapturedClipArray.size(); i++) { Track *track = mCapturedClipArray[i].track; WaveClip *clip = mCapturedClipArray[i].clip; if (clip) @@ -4609,9 +4526,7 @@ void TrackPanel::HandleVZoomClick( wxMouseEvent & event ) if (!mCapturedTrack) return; - // don't do anything if track is not wave or Spectrum/log Spectrum - if (((mCapturedTrack->GetKind() == Track::Wave) && - (((WaveTrack*)mCapturedTrack)->GetDisplay() != WaveTrack::PitchDisplay)) + if (mCapturedTrack->GetKind() == Track::Wave #ifdef USE_MIDI || mCapturedTrack->GetKind() == Track::Note #endif @@ -4651,7 +4566,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; @@ -4678,11 +4592,25 @@ void TrackPanel::HandleVZoomButtonUp( wxMouseEvent & event ) } #endif + // 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); + + if (event.RightUp() && + !(event.ShiftDown() || event.CmdDown())) { + OnVRulerMenu(mCapturedTrack, &event); + return; + } + + HandleWaveTrackVZoom(static_cast<WaveTrack*>(mCapturedTrack), + event.ShiftDown(), event.RightUp()); + mCapturedTrack = NULL; +} + +void TrackPanel::HandleWaveTrackVZoom(WaveTrack *track, bool shiftDown, bool rightUp) +{ + WaveTrack *partner = static_cast<WaveTrack *>(mTracks->GetLink(track)); int height = track->GetHeight(); int ypos = mCapturedRect.y; @@ -4693,225 +4621,174 @@ void TrackPanel::HandleVZoomButtonUp( wxMouseEvent & event ) mZoomStart = temp; } - 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) - ; - 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 + 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)); + const bool spectral = (track->GetDisplay() == WaveTrack::Spectrum); + const bool spectrumLinear = spectral && + (track->GetSpectrogramSettings().scaleType == SpectrogramSettings::stLinear); + + 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(); + 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 - 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 - } - else - track->GetDisplayBounds(&min, &max); + track->GetDisplayBounds(&min, &max); + if (IsDragZooming()) { // Drag Zoom - float p1, p2, tmin, tmax; - 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=wxMax(1.0, pow(10, xmin*d+lmin)); - max=wxMin(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; - } + const float tmin = min, tmax = max; + + 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(spectrum) { - 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()) { + else if (shiftDown || 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(spectrum) { - if (event.ShiftDown() && event.RightUp()) { + if (spectral) { + if (shiftDown && 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 = wxMin( rate/2., 2. * max); - } - else { - min = wxMax( 0.0, c - 2*l); - max = wxMin( 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 = wxMax(1,pow(10, xmin*d+lmin)); - max = wxMin(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 (shiftDown && 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 = wxMin(maxRange - ZOOMLIMIT, wxMax(minRange, c - 2*l)); - max = wxMax(minRange + ZOOMLIMIT, wxMin(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(spectrum) { - c = 0.5*(min+max); - // Enforce maximum vertical zoom - l = wxMax( 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); + if (spectral) { + // Center the zoom-in at the click + const float middle = 1.0f - (mZoomStart - ypos) / (float)height; + const float middleValue = scale.PositionToValue(middle); + + 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 = wxMax(1,pow(10, xmin*d+lmin)); - max = wxMin(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 = wxMax( 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; - } + 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; } } } - if(spectrum) { - mTrackArtist->SetSpectrumMaxFreq(max); - mTrackArtist->SetSpectrumMinFreq(min); - mTrackArtist->InvalidateSpectrumCache(mTracks); - } - else if(spectrumLog) { - mTrackArtist->SetSpectrumLogMaxFreq(max); - mTrackArtist->SetSpectrumLogMinFreq(min); - mTrackArtist->InvalidateSpectrumCache(mTracks); + 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 { + 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 { track->SetDisplayBounds(min, max); @@ -4920,9 +4797,8 @@ void TrackPanel::HandleVZoomButtonUp( wxMouseEvent & event ) } mZoomEnd = mZoomStart = 0; - UpdateVRuler(mCapturedTrack); + UpdateVRuler(track); Refresh(false); - mCapturedTrack = NULL; MakeParentModifyState(true); } @@ -4964,20 +4840,12 @@ bool TrackPanel::IsSampleEditingPossible( wxMouseEvent &event, Track * t ) //If we aren't displaying the waveform, Display a message dialog WaveTrack *const wt = static_cast<WaveTrack*>(t); const int display = wt->GetDisplay(); -#if 1 - if (!(WaveTrack::WaveformDisplay == display || - WaveTrack::WaveformDBDisplay == display)) - { - wxMessageBox(_("To use Draw, choose 'Waveform' or 'Waveform dB' in the Track Drop-down Menu."), wxT("Draw Tool")); - return false; - } -#else - if(WaveTrack::WaveformDisplay != display) + + if (WaveTrack::Waveform != display) { wxMessageBox(_("To use Draw, choose 'Waveform' in the Track Drop-down Menu."), wxT("Draw Tool")); return false; } -#endif bool showPoints; { @@ -4992,16 +4860,7 @@ bool TrackPanel::IsSampleEditingPossible( wxMouseEvent &event, Track * t ) //If we aren't zoomed in far enough, show a message dialog. if(!showPoints) { - // Release capture so user will be able to click OK on Linux - bool hadCapture = HasCapture(); - if (hadCapture) - ReleaseMouse(); - wxMessageBox(_("To use Draw, zoom in further until you can see the individual samples."), wxT("Draw Tool")); - - // Re-aquire capture - if (hadCapture) - CaptureMouse(); return false; } return true; @@ -5015,8 +4874,9 @@ float TrackPanel::FindSampleEditingLevel(wxMouseEvent &event, double t0) const int y = event.m_y - mDrawingTrackTop; const int height = mDrawingTrack->GetHeight(); - const bool dB = (WaveTrack::WaveformDBDisplay == mDrawingTrack->GetDisplay()); - float newLevel = ::ValueOfPixel(y, height, false, dB, mdBr, zoomMin, zoomMax); + const bool dB = !mDrawingTrack->GetWaveformSettings().isLinear(); + float newLevel = + ::ValueOfPixel(y, height, false, dB, mViewInfo->dBr, zoomMin, zoomMax); //Take the envelope into account Envelope *const env = mDrawingTrack->GetEnvelopeAtX(event.m_x); @@ -5050,11 +4910,7 @@ void TrackPanel::HandleSampleEditingClick( wxMouseEvent & event ) return; if( !IsSampleEditingPossible( event, t ) ) - { - if( HasCapture() ) - ReleaseMouse(); return; - } /// \todo Should mCapturedTrack take the place of mDrawingTrack?? mDrawingTrack = static_cast<WaveTrack*>(t); @@ -5278,8 +5134,6 @@ void TrackPanel::HandleSampleEditing(wxMouseEvent & event) // This is for when a given track gets the x. void TrackPanel::HandleClosing(wxMouseEvent & event) { - AudacityProject *p = GetProject(); //lda - Track *t = mCapturedTrack; wxRect r = mCapturedRect; @@ -5293,7 +5147,7 @@ void TrackPanel::HandleClosing(wxMouseEvent & event) else if (event.LeftUp()) { mTrackInfo.DrawCloseBox(&dc, r, false); if (closeRect.Contains(event.m_x, event.m_y)) { - if (!gAudioIO->IsStreamActive(p->GetAudioIOToken())) + if (!IsUnsafe()) RemoveTrack(t); } SetCapturedTrack( NULL ); @@ -5601,9 +5455,7 @@ void TrackPanel::HandleLabelClick(wxMouseEvent & event) // if they see anything other than a left click. bool isleft = event.Button(wxMOUSE_BTN_LEFT); - AudacityProject *p = GetProject(); - bool unsafe = (p->GetAudioIOToken()>0 && - gAudioIO->IsStreamActive(p->GetAudioIOToken())); + bool unsafe = IsUnsafe(); wxRect r; @@ -5734,6 +5586,11 @@ void TrackPanel::HandleRearrange(wxMouseEvent & event) return; } + // probably harmless during play? However, we do disallow the click, so check this too. + bool unsafe = IsUnsafe(); + if (unsafe) + return; + MixerBoard* pMixerBoard = this->GetMixerBoard(); // Update mixer board, too. wxString dir; if (event.m_y < mMoveUpThreshold || event.m_y < 0) { @@ -5918,26 +5775,25 @@ bool TrackPanel::PopupFunc(Track * t, wxRect r, int x, int y) /// update the track size. void TrackPanel::HandleResizeClick( wxMouseEvent & event ) { - wxRect r; + wxRect rTrack; wxRect rLabel; // DM: Figure out what track is about to be resized - Track *t = FindTrack(event.m_x, event.m_y, false, false, &r); - Track *label = FindTrack(event.m_x, event.m_y, true, true, &rLabel); - - // If the click is at the bottom of a non-linked track label, we - // treat it as a normal resize. If the label is of a linked track, - // we ignore the click. + Track *track = FindTrack(event.m_x, event.m_y, false, false, &rTrack); - if (label && !label->GetLinked()) { - t = label; + if (!track) { + // This will only return unlinked tracks or left channels of stereo tracks + // or NULL: + track = FindTrack(event.m_x, event.m_y, true, true, &rLabel); + // If stereo, get the right channel. + if (track && track->GetLinked()) + track = track->GetLink(); } - if (!t) { + if (!track) { return; } - mMouseClickX = event.m_x; mMouseClickY = event.m_y; #ifdef EXPERIMENTAL_OUTPUT_DISPLAY @@ -5983,34 +5839,34 @@ void TrackPanel::HandleResizeClick( wxMouseEvent & event ) } } #else // EXPERIMENTAL_OUTPUT_DISPLAY - Track *prev = mTracks->GetPrev(t); - Track *next = mTracks->GetNext(t); + Track *prev = mTracks->GetPrev(track); + Track *next = mTracks->GetNext(track); //STM: Determine whether we should rescale one or two tracks - if (prev && prev->GetLink() == t) { + if (prev && prev->GetLink() == track) { // mCapturedTrack is the lower track - mInitialTrackHeight = t->GetHeight(); - mInitialActualHeight = t->GetActualHeight(); - mInitialMinimized = t->GetMinimized(); + mInitialTrackHeight = track->GetHeight(); + mInitialActualHeight = track->GetActualHeight(); + mInitialMinimized = track->GetMinimized(); mInitialUpperTrackHeight = prev->GetHeight(); mInitialUpperActualHeight = prev->GetActualHeight(); - SetCapturedTrack(t, IsResizingBelowLinkedTracks); + SetCapturedTrack(track, IsResizingBelowLinkedTracks); } - else if (next && t->GetLink() == next) { + else if (next && track->GetLink() == next) { // mCapturedTrack is the upper track mInitialTrackHeight = next->GetHeight(); mInitialActualHeight = next->GetActualHeight(); mInitialMinimized = next->GetMinimized(); - mInitialUpperTrackHeight = t->GetHeight(); - mInitialUpperActualHeight = t->GetActualHeight(); - SetCapturedTrack(t, IsResizingBetweenLinkedTracks); + mInitialUpperTrackHeight = track->GetHeight(); + mInitialUpperActualHeight = track->GetActualHeight(); + SetCapturedTrack(track, IsResizingBetweenLinkedTracks); } else { // DM: Save the initial mouse location and the initial height - mInitialTrackHeight = t->GetHeight(); - mInitialActualHeight = t->GetActualHeight(); - mInitialMinimized = t->GetMinimized(); - SetCapturedTrack(t, IsResizing); + mInitialTrackHeight = track->GetHeight(); + mInitialActualHeight = track->GetActualHeight(); + mInitialMinimized = track->GetMinimized(); + SetCapturedTrack(track, IsResizing); } #endif // EXPERIMENTAL_OUTPUT_DISPLAY } @@ -6491,10 +6347,8 @@ void TrackPanel::OnMouseEvent(wxMouseEvent & event) if (event.ButtonDown()) { SetFocus(); - if (!HasCapture()) - CaptureMouse(); } - else if (event.ButtonUp()) { + if (event.ButtonUp()) { if (HasCapture()) ReleaseMouse(); } @@ -6555,10 +6409,16 @@ void TrackPanel::OnMouseEvent(wxMouseEvent & event) HandleLabelTrackMouseEvent((LabelTrack *)mCapturedTrack, mCapturedRect, event); break; default: //includes case of IsUncaptured + // This is where most button-downs are detected HandleTrackSpecificMouseEvent(event); break; } + if (event.ButtonDown() && IsMouseCaptured()) { + if (!HasCapture()) + CaptureMouse(); + } + //EnsureVisible should be called after the up-click. if (event.ButtonUp()) { wxRect r; @@ -6569,27 +6429,26 @@ void TrackPanel::OnMouseEvent(wxMouseEvent & event) } } -bool TrackPanel::HandleTrackLocationMouseEvent(WaveTrack * track, wxRect &r, wxMouseEvent &event) +bool TrackPanel::HandleTrackLocationMouseEvent(WaveTrack * track, wxRect &rect, wxMouseEvent &event) { // FIXME: Disable this and return true when CutLines aren't showing? // (Don't use gPrefs-> for the fix as registry access is slow). if (mMouseCapture == WasOverCutLine) { - // Needed to avoid select events right after IsOverCutLine event on button up if (event.ButtonUp()) { mMouseCapture = IsUncaptured; return false; } - return true; + else + // Needed to avoid select events after button down + return true; } - - if (mMouseCapture == IsOverCutLine) + else if (!IsUnsafe() && IsOverCutline(track, rect, event)) { if (!mCapturedTrackLocationRect.Contains(event.m_x, event.m_y)) { SetCapturedTrack( NULL ); - SetCursorByActivity(); return false; } @@ -6597,15 +6456,11 @@ bool TrackPanel::HandleTrackLocationMouseEvent(WaveTrack * track, wxRect &r, wxM if (event.LeftDown()) { - if (mCapturedTrackLocation.typ == WaveTrack::locationCutLine) + if (mCapturedTrackLocation.typ == WaveTrackLocation::locationCutLine) { // When user presses left button on cut line, expand the line again double cutlineStart = 0, cutlineEnd = 0; - // Release capture so user will be able to click OK on Linux - if (HasCapture()) - ReleaseMouse(); - if (track->ExpandCutLine(mCapturedTrackLocation.pos, &cutlineStart, &cutlineEnd)) { WaveTrack* linked = (WaveTrack*)mTracks->GetLink(track); @@ -6618,8 +6473,8 @@ bool TrackPanel::HandleTrackLocationMouseEvent(WaveTrack * track, wxRect &r, wxM MakeParentPushState(_("Expanded Cut Line"), _("Expand")); handled = true; } - } else if (mCapturedTrackLocation.typ == WaveTrack::locationMergePoint) - { + } + else if (mCapturedTrackLocation.typ == WaveTrackLocation::locationMergePoint) { if (!track->MergeClips(mCapturedTrackLocation.clipidx1, mCapturedTrackLocation.clipidx2)) return false; @@ -6646,6 +6501,8 @@ bool TrackPanel::HandleTrackLocationMouseEvent(WaveTrack * track, wxRect &r, wxM if (handled) { SetCapturedTrack( NULL ); + // Effect happened at button-down, but treat like a dragging mode until + // button-up. mMouseCapture = WasOverCutLine; RefreshTrack(track); return true; @@ -6654,24 +6511,27 @@ bool TrackPanel::HandleTrackLocationMouseEvent(WaveTrack * track, wxRect &r, wxM return true; } + return false; +} + +bool TrackPanel::IsOverCutline(WaveTrack * track, wxRect &rect, wxMouseEvent &event) +{ for (int i=0; i<track->GetNumCachedLocations(); i++) { WaveTrack::Location loc = track->GetCachedLocation(i); const double x = mViewInfo->TimeToPosition(loc.pos); - if (x >= 0 && x < r.width) + if (x >= 0 && x < rect.width) { wxRect locRect; - locRect.x = int( r.x + x ) - 5; + locRect.x = int(rect.x + x) - 5; locRect.width = 11; - locRect.y = r.y; - locRect.height = r.height; + locRect.y = rect.y; + locRect.height = rect.height; if (locRect.Contains(event.m_x, event.m_y)) { - SetCapturedTrack(track, IsOverCutLine); mCapturedTrackLocation = loc; mCapturedTrackLocationRect = locRect; - SetCursorByActivity(); return true; } } @@ -6808,19 +6668,17 @@ bool TrackPanel::HandleLabelTrackMouseEvent(LabelTrack * lTrack, wxRect &r, wxMo void TrackPanel::HandleTrackSpecificMouseEvent(wxMouseEvent & event) { Track * pTrack; - wxRect r; + wxRect rTrack; wxRect rLabel; - AudacityProject *p = GetProject(); - bool unsafe = (p->GetAudioIOToken()>0 && - gAudioIO->IsStreamActive(p->GetAudioIOToken())); + bool unsafe = IsUnsafe(); FindTrack(event.m_x, event.m_y, true, true, &rLabel); - pTrack = FindTrack(event.m_x, event.m_y, false, false, &r); + pTrack = FindTrack(event.m_x, event.m_y, false, false, &rTrack); //call HandleResize if I'm over the border area if (event.LeftDown() && - (within(event.m_y, r.y + r.height, TRACK_RESIZE_REGION) + (within(event.m_y, rTrack.y + rTrack.height, TRACK_RESIZE_REGION) || within(event.m_y, rLabel.y + rLabel.height, TRACK_RESIZE_REGION))) { HandleResize(event); @@ -6846,7 +6704,7 @@ void TrackPanel::HandleTrackSpecificMouseEvent(wxMouseEvent & event) //If so, use MouseDown handler for the label track. if (pTrack && (pTrack->GetKind() == Track::Label)) { - if(HandleLabelTrackMouseEvent( (LabelTrack *) pTrack, r, event )) + if (HandleLabelTrackMouseEvent((LabelTrack *)pTrack, rTrack, event)) return; } @@ -6863,18 +6721,14 @@ void TrackPanel::HandleTrackSpecificMouseEvent(wxMouseEvent & event) } #endif + bool handled = false; + if (pTrack && (pTrack->GetKind() == Track::Wave) && - (mMouseCapture == IsUncaptured || mMouseCapture == IsOverCutLine || - mMouseCapture == WasOverCutLine)) - { - if (HandleTrackLocationMouseEvent( (WaveTrack *) pTrack, r, event )) - return; - } + (mMouseCapture == IsUncaptured || mMouseCapture == WasOverCutLine)) + handled = HandleTrackLocationMouseEvent((WaveTrack *)pTrack, rTrack, event); ToolsToolBar * pTtb = mListener->TP_GetToolsToolBar(); - if( pTtb == NULL ) - return; - + if( !handled && pTtb != NULL ) { int toolToUse = DetermineToolToUse(pTtb, event); @@ -6986,7 +6840,7 @@ bool TrackPanel::HitTestStretch(Track *track, wxRect &r, wxMouseEvent & event) // selected when the cursor is near the center of the track and // within the selection if (!track || !track->GetSelected() || track->GetKind() != Track::Note || - gAudioIO->IsStreamActive( GetProject()->GetAudioIOToken())) { + IsUnsafe()) { return false; } int center = r.y + r.height / 2; @@ -7015,16 +6869,14 @@ bool TrackPanel::HitTestEnvelope(Track *track, wxRect &r, wxMouseEvent & event) if (!envelope) return false; - int displayType = wavetrack->GetDisplay(); + const int displayType = wavetrack->GetDisplay(); // Not an envelope hit, unless we're using a type of wavetrack display // suitable for envelopes operations, ie one of the Wave displays. - const bool dB = (displayType == WaveTrack::WaveformDBDisplay); - if (! - (dB || (displayType == WaveTrack::WaveformDisplay)) - ) + if ( displayType != WaveTrack::Waveform) return false; // No envelope, not a hit, so return. // Get envelope point, range 0.0 to 1.0 + const bool dB = !wavetrack->GetWaveformSettings().isLinear(); // Convert x to time. const double envValue = envelope->GetValue(mViewInfo->PositionToTime(event.m_x, r.x)); @@ -7034,12 +6886,12 @@ bool TrackPanel::HitTestEnvelope(Track *track, wxRect &r, wxMouseEvent & event) // Get y position of envelope point. int yValue = GetWaveYPos( envValue, zoomMin, zoomMax, - r.height, dB, true, mdBr, false ) + r.y; + r.height, dB, true, mViewInfo->dBr, false) + r.y; // Get y position of center line int ctr = GetWaveYPos( 0.0, zoomMin, zoomMax, - r.height, dB, true, mdBr, false ) + r.y; + r.height, dB, true, mViewInfo->dBr, false) + r.y; // Get y distance of mouse from center line (in pixels). int yMouse = abs(ctr - event.m_y); @@ -7082,10 +6934,10 @@ bool TrackPanel::HitTestSamples(Track *track, wxRect &r, wxMouseEvent & event) //Get rate in order to calculate the critical zoom threshold double rate = wavetrack->GetRate(); - int displayType = wavetrack->GetDisplay(); - bool dB = (WaveTrack::WaveformDBDisplay == displayType); - if (!(WaveTrack::WaveformDisplay == displayType || dB)) + const int displayType = wavetrack->GetDisplay(); + if (WaveTrack::Waveform != displayType) return false; // Not a wave, so return. + const bool dB = !wavetrack->GetWaveformSettings().isLinear(); const double tt = mViewInfo->PositionToTime(event.m_x, r.x); if (!SampleResolutionTest(*mViewInfo, wavetrack, tt, rate)) @@ -7108,7 +6960,7 @@ bool TrackPanel::HitTestSamples(Track *track, wxRect &r, wxMouseEvent & event) int yValue = GetWaveYPos( oneSample * envValue, zoomMin, zoomMax, - r.height, dB, true, mdBr, false) + r.y; + r.height, dB, true, mViewInfo->dBr, false) + r.y; // Get y position of mouse (in pixels) int yMouse = event.m_y; @@ -8067,8 +7919,7 @@ void TrackPanel::SeekLeftOrRight { if (keyup) { - int token = GetProject()->GetAudioIOToken(); - if (token > 0 && gAudioIO->IsStreamActive(token)) + if (IsAudioActive()) { return; } @@ -8089,8 +7940,6 @@ void TrackPanel::SeekLeftOrRight if (leftward) multiplier = -multiplier; - int token = GetProject()->GetAudioIOToken(); - if (shift && ctrl) { mLastSelectionAdjustment = curtime; @@ -8129,7 +7978,7 @@ void TrackPanel::SeekLeftOrRight } Refresh(false); } - else if (token > 0 && gAudioIO->IsStreamActive(token)) { + else if (IsAudioActive()) { #ifdef EXPERIMENTAL_IMPROVED_SEEKING if (gAudioIO->GetLastPlaybackTime() < mLastSelectionAdjustment) { // Allow time for the last seek to output a buffer before @@ -8282,8 +8131,7 @@ void TrackPanel::OnBoundaryMove(bool left, bool boundaryContract) } mLastSelectionAdjustment = curtime; - int token = GetProject()->GetAudioIOToken(); - if( token > 0 && gAudioIO->IsStreamActive( token ) ) + if (IsAudioActive()) { double indicator = gAudioIO->GetStreamTime(); if (left) { @@ -8558,16 +8406,11 @@ void TrackPanel::OnTrackMenu(Track *t) theMenu->Enable(OnChannelLeftID, !t->GetLinked()); theMenu->Enable(OnChannelRightID, !t->GetLinked()); - int display = ((WaveTrack *) t)->GetDisplay(); - - theMenu->Enable(OnWaveformID, display != WaveTrack::WaveformDisplay); - theMenu->Enable(OnWaveformDBID, - display != WaveTrack::WaveformDBDisplay); - theMenu->Enable(OnSpectrumID, display != WaveTrack::SpectrumDisplay); - theMenu->Enable(OnSpectrumLogID, display != WaveTrack::SpectrumLogDisplay); - theMenu->Enable(OnSpectralSelID, display != WaveTrack::SpectralSelectionDisplay); - theMenu->Enable(OnSpectralSelLogID, display != WaveTrack::SpectralSelectionLogDisplay); - theMenu->Enable(OnPitchID, display != WaveTrack::PitchDisplay); + const int display = static_cast<WaveTrack *>(t)->GetDisplay(); + theMenu->Check( + (display == WaveTrack::Waveform) ? OnWaveformID : OnSpectrumID, + true + ); WaveTrack * track = (WaveTrack *)t; SetMenuCheck(*mRateMenu, IdOfRate((int) track->GetRate())); @@ -8610,6 +8453,55 @@ void TrackPanel::OnTrackMenu(Track *t) Refresh(false); } +void TrackPanel::OnVRulerMenu(Track *t, wxMouseEvent *pEvent) +{ + if (!t) { + t = GetFocusedTrack(); + if (!t) + return; + } + + if (t->GetKind() != Track::Wave) + return; + + WaveTrack *const wt = static_cast<WaveTrack*>(t); + + const int display = wt->GetDisplay(); + wxMenu *theMenu; + if (display == WaveTrack::Waveform) { + theMenu = mRulerWaveformMenu; + const int id = + OnFirstWaveformScaleID + int(wt->GetWaveformSettings().scaleType); + theMenu->Check(id, true); + } + else { + theMenu = mRulerSpectrumMenu; + const int id = + OnFirstSpectrumScaleID + int(wt->GetSpectrogramSettings().scaleType); + theMenu->Check(id, true); + } + + int x, y; + if (pEvent) + x = pEvent->m_x, y = pEvent->m_y; + else { + // If no event given, pop up the menu at the same height + // as for the track control menu + const wxRect r = FindTrackRect(wt, true); + wxRect titleRect; + mTrackInfo.GetTitleBarRect(r, titleRect); + x = GetVRulerOffset(), y = titleRect.y + titleRect.height + 1; + } + + // So that IsDragZooming() returns false, and if we zoom in, we do so + // centered where the mouse is now: + mZoomStart = mZoomEnd = pEvent->m_y; + + mPopupMenuTarget = wt; + PopupMenu(theMenu, x, y); + mPopupMenuTarget = NULL; +} + void TrackPanel::OnTrackMute(bool shiftDown, Track *t) { if (!t) { @@ -8659,7 +8551,7 @@ void TrackPanel::OnTrackClose() Track *t = GetFocusedTrack(); if(!t) return; - if( gAudioIO->IsStreamActive( GetProject()->GetAudioIOToken() ) ) + if (IsUnsafe()) { mListener->TP_DisplayStatusMessage( _( "Can't delete track with active audio" ) ); wxBell(); @@ -9029,6 +8921,51 @@ void TrackPanel::OnMergeStereo(wxCommandEvent & WXUNUSED(event)) Refresh(false); } +class ViewSettingsDialog : public PrefsDialog +{ +public: + ViewSettingsDialog + (wxWindow *parent, const wxString &title, PrefsDialog::Factories &factories, + int page) + : PrefsDialog(parent, title, factories) + , mPage(page) + { + } + + virtual long GetPreferredPage() + { + return mPage; + } + + virtual void SavePreferredPage() + { + } + +private: + const int mPage; +}; + +void TrackPanel::OnViewSettings(wxCommandEvent &) +{ + WaveTrack *const wt = static_cast<WaveTrack*>(mPopupMenuTarget); + WaveformPrefsFactory waveformFactory(wt); + SpectrumPrefsFactory spectrumFactory(wt); + + // Put Waveform page first + PrefsDialog::Factories factories; + factories.push_back(&waveformFactory); + factories.push_back(&spectrumFactory); + const int page = (wt->GetDisplay() == WaveTrack::Spectrum) + ? 1 : 0; + + wxString title(wt->GetName() + wxT(": ")); + ViewSettingsDialog dialog(this, title, factories, page); + + if (0 != dialog.ShowModal()) + // Redraw + Refresh(false); +} + /// Set the Display mode based on the menu choice in the Track Menu. /// Note that gModes MUST BE IN THE SAME ORDER AS THE MENU CHOICES!! /// const wxChar *gModes[] = { wxT("waveform"), wxT("waveformDB"), @@ -9036,7 +8973,7 @@ void TrackPanel::OnMergeStereo(wxCommandEvent & WXUNUSED(event)) void TrackPanel::OnSetDisplay(wxCommandEvent & event) { int idInt = event.GetId(); - wxASSERT(idInt >= OnWaveformID && idInt <= OnPitchID); + wxASSERT(idInt >= OnWaveformID && idInt <= OnSpectrumID); wxASSERT(mPopupMenuTarget && mPopupMenuTarget->GetKind() == Track::Wave); @@ -9044,30 +8981,17 @@ void TrackPanel::OnSetDisplay(wxCommandEvent & event) switch (idInt) { default: case OnWaveformID: - id = WaveTrack::WaveformDisplay; break; - case OnWaveformDBID: - id = WaveTrack::WaveformDBDisplay; break; + id = WaveTrack::Waveform; break; case OnSpectrumID: - id = WaveTrack::SpectralSelectionDisplay; break; - case OnSpectrumLogID: - id = WaveTrack::SpectralSelectionLogDisplay; break; - case OnSpectralSelID: - id = WaveTrack::SpectralSelectionDisplay; break; - case OnSpectralSelLogID: - id = WaveTrack::SpectralSelectionLogDisplay; break; - case OnPitchID: - id = WaveTrack::PitchDisplay; break; + id = WaveTrack::Spectrum; break; } WaveTrack *wt = (WaveTrack *) mPopupMenuTarget; if (wt->GetDisplay() != id) { wt->SetDisplay(WaveTrack::WaveTrackDisplay(id)); - mTrackArtist->InvalidateSpectrumCache(wt); - WaveTrack *l = (WaveTrack *) wt->GetLink(); - if (l) { + WaveTrack *l = static_cast<WaveTrack *>(wt->GetLink()); + if (l) l->SetDisplay(WaveTrack::WaveTrackDisplay(id)); - mTrackArtist->InvalidateSpectrumCache(l); - } #ifdef EXPERIMENTAL_OUTPUT_DISPLAY if (wt->GetDisplay() == WaveTrack::WaveformDisplay) { wt->SetVirtualState(false); @@ -9076,9 +9000,10 @@ void TrackPanel::OnSetDisplay(wxCommandEvent & event) } #endif UpdateVRuler(wt); + + MakeParentModifyState(true); + Refresh(false); } - MakeParentModifyState(true); - Refresh(false); } /// Sets the sample rate for a track, and if it is linked to @@ -9361,6 +9286,55 @@ void TrackPanel::OnTimeTrackLogInt(wxCommandEvent & /*event*/) Refresh(false); } +void TrackPanel::OnWaveformScaleType(wxCommandEvent &evt) +{ + WaveTrack *const wt = static_cast<WaveTrack *>(mPopupMenuTarget); + const WaveformSettings::ScaleType newScaleType = + WaveformSettings::ScaleType( + std::max(0, + std::min(int(WaveformSettings::stNumScaleTypes) - 1, + evt.GetId() - OnFirstWaveformScaleID + ))); + if (wt->GetWaveformSettings().scaleType != newScaleType) { + wt->GetIndependentWaveformSettings().scaleType = newScaleType; + UpdateVRuler(wt); // Is this really needed? + MakeParentModifyState(true); + Refresh(false); + } +} + +void TrackPanel::OnSpectrumScaleType(wxCommandEvent &evt) +{ + WaveTrack *const wt = static_cast<WaveTrack *>(mPopupMenuTarget); + const SpectrogramSettings::ScaleType newScaleType = + SpectrogramSettings::ScaleType( + std::max(0, + std::min(int(SpectrogramSettings::stNumScaleTypes) - 1, + evt.GetId() - OnFirstSpectrumScaleID + ))); + if (wt->GetSpectrogramSettings().scaleType != newScaleType) { + wt->GetIndependentSpectrogramSettings().scaleType = newScaleType; + UpdateVRuler(wt); // Is this really needed? + MakeParentModifyState(true); + Refresh(false); + } +} + +void TrackPanel::OnZoomInVertical(wxCommandEvent &) +{ + HandleWaveTrackVZoom(static_cast<WaveTrack*>(mPopupMenuTarget), false, false); +} + +void TrackPanel::OnZoomOutVertical(wxCommandEvent &) +{ + HandleWaveTrackVZoom(static_cast<WaveTrack*>(mPopupMenuTarget), true, false); +} + +void TrackPanel::OnZoomFitVertical(wxCommandEvent &) +{ + HandleWaveTrackVZoom(static_cast<WaveTrack*>(mPopupMenuTarget), true, true); +} + /// Move a track up, down, to top or to bottom. void TrackPanel::OnMoveTrack(wxCommandEvent &event) @@ -9759,7 +9733,7 @@ bool TrackPanel::MoveClipToTrack(WaveClip *clip, WaveTrack* dst) if (dst->GetKind() != Track::Wave) return false; #endif - for (i = 0; i < mCapturedClipArray.GetCount(); i++) { + for (i = 0; i < mCapturedClipArray.size(); i++) { if (clip == mCapturedClipArray[i].clip) { src = (WaveTrack*)mCapturedClipArray[i].track; break; @@ -9777,7 +9751,7 @@ bool TrackPanel::MoveClipToTrack(WaveClip *clip, WaveTrack* dst) // find the first track by getting the linked track from src // assumes that mCapturedArray[i].clip and .track is not NULL. - for (i = 0; i < mCapturedClipArray.GetCount(); i++) { + for (i = 0; i < mCapturedClipArray.size(); i++) { if (mTracks->GetLink(src) == mCapturedClipArray[i].track) { clip = mCapturedClipArray[i].clip; break; @@ -9793,7 +9767,7 @@ bool TrackPanel::MoveClipToTrack(WaveClip *clip, WaveTrack* dst) src2 = (WaveTrack*)mTracks->GetLink(src); dst2 = (WaveTrack*)mTracks->GetLink(dst); - for (i = 0; i < mCapturedClipArray.GetCount(); i++) { + for (i = 0; i < mCapturedClipArray.size(); i++) { if (mCapturedClipArray[i].track == src2) { clip2 = mCapturedClipArray[i].clip; break; @@ -9829,7 +9803,7 @@ bool TrackPanel::MoveClipToTrack(WaveClip *clip, WaveTrack* dst) src2->MoveClipToTrack(clip2, dst2); // update the captured clip array. - for (i = 0; i < mCapturedClipArray.GetCount(); i++) { + for (i = 0; i < mCapturedClipArray.size(); i++) { if (clip && mCapturedClipArray[i].clip == clip) { mCapturedClipArray[i].track = dst; } else if (clip2 && mCapturedClipArray[i].clip == clip2) { diff --git a/src/TrackPanel.h b/src/TrackPanel.h index 6dddc2ce00357750e5709f24dbd027863d91d74a..5cc2950b0b076c9efc768493f8f4c07d9ff6ad3f 100644 --- a/src/TrackPanel.h +++ b/src/TrackPanel.h @@ -15,18 +15,19 @@ #include <vector> #include <wx/dcmemory.h> -#include <wx/dynarray.h> #include <wx/panel.h> #include <wx/timer.h> #include <wx/window.h> #include "Experimental.h" -#include "Sequence.h" //Stm: included for the sampleCount declaration -#include "WaveClip.h" -#include "WaveTrack.h" +#include "audacity/Types.h" #include "UndoManager.h" //JKC: Included for PUSH_XXX definitions. #include "widgets/NumericTextCtrl.h" +#include "WaveTrackLocation.h" + +#include "Snap.h" + class wxMenu; class wxRect; @@ -47,24 +48,16 @@ class TrackPanelAx; class ViewInfo; -WX_DEFINE_ARRAY(LWSlider *, LWSliderArray); - -class AUDACITY_DLL_API TrackClip -{ - public: - TrackClip(Track *t, WaveClip *c) { track = t; clip = c; } - Track *track; - WaveClip *clip; -}; - -WX_DECLARE_OBJARRAY(TrackClip, TrackClipArray); +class WaveTrack; +class WaveClip; +class Envelope; // Declared elsewhere, to reduce compilation dependencies class TrackPanelListener; // JKC Nov 2011: Disabled warning C4251 which is to do with DLL linkage // and only a worry when there are DLLs using the structures. -// LWSliderArray and TrackClipArray are private in TrackInfo, so we will not +// Array classes are private in TrackInfo, so we will not // access them directly from the DLL. // TrackClipArray in TrackPanel needs to be handled with care in the derived // class, but the C4251 warning is no worry in core Audacity. @@ -75,6 +68,8 @@ class TrackPanelListener; #pragma warning( disable: 4251 ) #endif +DECLARE_EXPORTED_EVENT_TYPE(AUDACITY_DLL_API, EVT_TRACK_PANEL_TIMER, -1); + class AUDACITY_DLL_API TrackInfo { public: @@ -210,6 +205,7 @@ class AUDACITY_DLL_API TrackPanel:public wxPanel { virtual void OnTrackGainDec(); virtual void OnTrackGainInc(); virtual void OnTrackMenu(Track *t = NULL); + virtual void OnVRulerMenu(Track *t, wxMouseEvent *pEvent = NULL); virtual void OnTrackMute(bool shiftdown, Track *t = NULL); virtual void OnTrackSolo(bool shiftdown, Track *t = NULL); virtual void OnTrackClose(); @@ -244,9 +240,12 @@ class AUDACITY_DLL_API TrackPanel:public wxPanel { * @param menu the menu to add the commands to. */ virtual void BuildCommonDropMenuItems(wxMenu * menu); + static void BuildVRulerMenuItems(wxMenu * menu, int firstId, const wxArrayString &names); + virtual bool IsAudioActive(); virtual bool IsUnsafe(); virtual bool HandleLabelTrackMouseEvent(LabelTrack * lTrack, wxRect &r, wxMouseEvent & event); - virtual bool HandleTrackLocationMouseEvent(WaveTrack * track, wxRect &r, wxMouseEvent &event); + virtual bool HandleTrackLocationMouseEvent(WaveTrack * track, wxRect &rect, wxMouseEvent &event); + virtual bool IsOverCutline(WaveTrack * track, wxRect &rect, wxMouseEvent &event); virtual void HandleTrackSpecificMouseEvent(wxMouseEvent & event); virtual void DrawIndicator(); /// draws the green line on the tracks to show playback position @@ -337,9 +336,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); @@ -359,14 +358,15 @@ protected: // AS: Cursor handling virtual bool SetCursorByActivity( ); - virtual void SetCursorAndTipWhenInLabel( Track * t, wxMouseEvent &event, const wxChar ** ppTip ); - virtual void SetCursorAndTipWhenInVResizeArea( Track * label, bool blinked, const wxChar ** ppTip ); - virtual void SetCursorAndTipWhenInLabelTrack( LabelTrack * pLT, wxMouseEvent & event, const wxChar ** ppTip ); + virtual bool SetCursorForCutline(WaveTrack * track, wxRect &rect, wxMouseEvent &event); + virtual void SetCursorAndTipWhenInLabel( Track * t, wxMouseEvent &event, wxString &tip ); + virtual void SetCursorAndTipWhenInVResizeArea( bool blinked, wxString &tip ); + virtual void SetCursorAndTipWhenInLabelTrack( LabelTrack * pLT, wxMouseEvent & event, wxString &tip ); virtual void SetCursorAndTipWhenSelectTool - ( Track * t, wxMouseEvent & event, wxRect &r, bool bMultiToolMode, const wxChar ** ppTip, const wxCursor ** ppCursor ); - virtual void SetCursorAndTipByTool( int tool, wxMouseEvent & event, const wxChar **ppTip ); + ( Track * t, wxMouseEvent & event, wxRect &r, bool bMultiToolMode, wxString &tip, const wxCursor ** ppCursor ); + virtual void SetCursorAndTipByTool( int tool, wxMouseEvent & event, wxString &tip ); virtual void HandleCursor(wxMouseEvent & event); - virtual void MaySetOnDemandTip( Track * t, const wxChar ** ppTip ); + virtual void MaySetOnDemandTip( Track * t, wxString &tip ); // AS: Envelope editing handlers virtual void HandleEnvelope(wxMouseEvent & event); @@ -395,6 +395,7 @@ protected: virtual void HandleVZoomClick(wxMouseEvent & event); virtual void HandleVZoomDrag(wxMouseEvent & event); virtual void HandleVZoomButtonUp(wxMouseEvent & event); + virtual void HandleWaveTrackVZoom(WaveTrack *track, bool shiftDown, bool rightUp); // Handle sample editing using the 'draw' tool. virtual bool IsSampleEditingPossible( wxMouseEvent & event, Track * t ); @@ -459,12 +460,20 @@ protected: virtual void MoveTrack(Track* target, int eventId); virtual void OnChangeOctave (wxCommandEvent &event); virtual void OnChannelChange(wxCommandEvent &event); + virtual void OnViewSettings(wxCommandEvent &event); virtual void OnSetDisplay (wxCommandEvent &event); virtual void OnSetTimeTrackRange (wxCommandEvent &event); virtual void OnTimeTrackLin(wxCommandEvent &event); virtual void OnTimeTrackLog(wxCommandEvent &event); virtual void OnTimeTrackLogInt(wxCommandEvent &event); + virtual void OnWaveformScaleType(wxCommandEvent &event); + virtual void OnSpectrumScaleType(wxCommandEvent &event); + + virtual void OnZoomInVertical(wxCommandEvent &event); + virtual void OnZoomOutVertical(wxCommandEvent &event); + virtual void OnZoomFitVertical(wxCommandEvent &event); + virtual void SetMenuCheck( wxMenu & menu, int newId ); virtual void SetRate(Track *pTrack, double rate); virtual void OnRateChange(wxCommandEvent &event); @@ -494,9 +503,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. @@ -572,8 +581,8 @@ protected: // This stores the parts of the screen that get overwritten by the indicator // and cursor - double mLastIndicator; - double mLastCursor; + int mLastIndicatorX; + int mLastCursorX; // Quick-Play indicator postion double mOldQPIndicatorPos; @@ -632,7 +641,7 @@ protected: WaveClip *mCapturedClip; TrackClipArray mCapturedClipArray; bool mCapturedClipIsSelection; - WaveTrack::Location mCapturedTrackLocation; + WaveTrackLocation mCapturedTrackLocation; wxRect mCapturedTrackLocationRect; wxRect mCapturedRect; @@ -688,22 +697,20 @@ protected: #ifdef EXPERIMENTAL_SPECTRAL_EDITING void HandleCenterFrequencyCursor - (bool shiftDown, const wxChar ** ppTip, const wxCursor ** ppCursor); + (bool shiftDown, wxString &tip, const wxCursor ** ppCursor); 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, + int trackHeight) const; + wxInt64 FrequencyToPosition(const WaveTrack *wt, + double frequency, wxInt64 trackTopEdge, - int trackHeight, - double rate, - bool logF) const; + int trackHeight) const; #endif enum SelectionBoundary { @@ -749,7 +756,6 @@ protected: IsGainSliding, IsPanSliding, IsMinimizing, - IsOverCutLine, WasOverCutLine, IsPopping, #ifdef USE_MIDI @@ -766,7 +772,6 @@ protected: bool mAdjustSelectionEdges; bool mSlideUpDownOnly; bool mCircularTrackNavigation; - float mdBr; // JH: if the user is dragging a track, at what y // coordinate should the dragging track move up or down? @@ -826,6 +831,9 @@ protected: wxMenu *mFormatMenu; wxMenu *mLabelTrackInfoMenu; + wxMenu *mRulerWaveformMenu; + wxMenu *mRulerSpectrumMenu; + Track *mPopupMenuTarget; friend class TrackPanelAx; diff --git a/src/TrackPanelAx.cpp b/src/TrackPanelAx.cpp index f87bbb5912c9d8d7a9324cd64184aecbb87ed7d7..1ef9a29f7b38157f0fce59d85d5e2037cf0b0075 100644 --- a/src/TrackPanelAx.cpp +++ b/src/TrackPanelAx.cpp @@ -14,6 +14,9 @@ *//*******************************************************************/ +#include "Audacity.h" +#include "TrackPanelAx.h" + // For compilers that support precompilation, includes "wx/wx.h". #include <wx/wxprec.h> @@ -23,11 +26,10 @@ #endif -#include "Audacity.h" -#include "TrackPanelAx.h" - #include <wx/intl.h> +#include "Track.h" + TrackPanelAx::TrackPanelAx( wxWindow *window ) #if wxUSE_ACCESSIBILITY :wxWindowAccessible( window ) diff --git a/src/UndoManager.cpp b/src/UndoManager.cpp index 0c9ecfd9c89d5eda3ecbde30db127804b2a2cf4e..ba8ecbef92adf63648427001f82a380d35de59a3 100644 --- a/src/UndoManager.cpp +++ b/src/UndoManager.cpp @@ -28,7 +28,6 @@ UndoManager #include "Diags.h" #include "Internat.h" #include "Sequence.h" -#include "Track.h" #include "WaveTrack.h" // temp #include "NoteTrack.h" // for Sonify* function declarations #include "Diags.h" diff --git a/src/ViewInfo.cpp b/src/ViewInfo.cpp index f0f439a4287f6094c51c765ef08fa26f7c7a9a22..7746b297b59f65ccffa9127e0a52003215273c7e 100644 --- a/src/ViewInfo.cpp +++ b/src/ViewInfo.cpp @@ -13,6 +13,8 @@ Paul Licameli #include <algorithm> #include "Internat.h" +#include "prefs/GUISettings.h" +#include "Prefs.h" #include "xml/XMLWriter.h" namespace { @@ -26,12 +28,18 @@ ZoomInfo::ZoomInfo(double start, double screenDuration, double pixelsPerSecond) , screen(screenDuration) , zoom(pixelsPerSecond) { + UpdatePrefs(); } ZoomInfo::~ZoomInfo() { } +void ZoomInfo::UpdatePrefs() +{ + dBr = gPrefs->Read(ENV_DB_KEY, ENV_DB_RANGE); +} + /// Converts a position (mouse X coordinate) to /// project time, in seconds. Needs the left edge of /// the track as an additional parameter. diff --git a/src/ViewInfo.h b/src/ViewInfo.h index 23f3445ab108b03294257d00a18af64753369629..836ef04f9a1f76f0a58e541fd63f355bda034639 100644 --- a/src/ViewInfo.h +++ b/src/ViewInfo.h @@ -17,6 +17,11 @@ class Track; +#ifdef __GNUC__ +#define CONST +#else +#define CONST const +#endif // The subset of ViewInfo information (other than selection) // that is sufficient for purposes of TrackArtist, @@ -27,6 +32,8 @@ public: ZoomInfo(double start, double duration, double pixelsPerSecond); ~ZoomInfo(); + void UpdatePrefs(); + int vpos; // vertical scroll pos double h; // h pos in secs @@ -37,6 +44,7 @@ protected: double zoom; // pixels per second public: + float dBr; // decibel scale range // do NOT use this once to convert a pixel width to a duration! // Instead, call twice to convert start and end times, @@ -85,7 +93,7 @@ public: void ZoomBy(double multiplier); struct Interval { - /* const */ wxInt64 position; /* const */ double averageZoom; /* const */ bool inFisheye; + CONST wxInt64 position; CONST double averageZoom; CONST bool inFisheye; Interval(wxInt64 p, double z, bool i) : position(p), averageZoom(z), inFisheye(i) {} }; diff --git a/src/VoiceKey.cpp b/src/VoiceKey.cpp index e138d013a97752922b6e93e11b4c6c61cfc5eac3..d22cb9768558768970e3821f2b2e70627e9acb09 100644 --- a/src/VoiceKey.cpp +++ b/src/VoiceKey.cpp @@ -32,6 +32,8 @@ or "OFF" point #include <wx/intl.h> #include <iostream> +#include "WaveTrack.h" + using std::cout; using std::endl; diff --git a/src/VoiceKey.h b/src/VoiceKey.h index 3cdb859398c474c403ea55bd1e1d23e72f2bafa4..926548ed9791971e135380e301415ea064e07ea5 100644 --- a/src/VoiceKey.h +++ b/src/VoiceKey.h @@ -11,13 +11,15 @@ #ifndef __AUDACITY_VOICEKEY__ #define __AUDACITY_VOICEKEY__ -#include "WaveTrack.h" - #ifndef M_PI #define M_PI 3.14159265358979323846 /* pi */ #endif +#include "audacity/Types.h" + +class WaveTrack; + enum VoiceKeyTypes { VKT_NONE = 0, @@ -91,10 +93,10 @@ class VoiceKey { }; -inline int sgn(int number){ return (number<0) ? -1: 1;}; +inline int sgn(int number){ return (number<0) ? -1: 1;} //This returns a logistic density based on a z-score // a logistic distn has variance (pi*s)^2/3 -//inline float inline float logistic(float z){ return fexp(-1 * z/(pi / sqrt(3)) / (1 + pow(fexp(-1 * z(pi / sqrt(3))),2)));}; +//inline float inline float logistic(float z){ return fexp(-1 * z/(pi / sqrt(3)) / (1 + pow(fexp(-1 * z(pi / sqrt(3))),2)));} #endif diff --git a/src/WaveClip.cpp b/src/WaveClip.cpp index 762683782058bc4bd07610ba0120df6ed4d256a4..572bf676c50dbb194d785a206e12fc65a273963c 100644 --- a/src/WaveClip.cpp +++ b/src/WaveClip.cpp @@ -27,13 +27,15 @@ #include <vector> #include <wx/log.h> +#include "Sequence.h" #include "Spectrum.h" #include "Prefs.h" #include "Envelope.h" #include "Resample.h" #include "Project.h" +#include "WaveTrack.h" -#include "prefs/SpectrumPrefs.h" +#include "prefs/SpectrogramSettings.h" #include <wx/listimpl.cpp> WX_DEFINE_LIST(WaveClipList); @@ -367,6 +369,11 @@ bool WaveClip::SetSamples(samplePtr buffer, sampleFormat format, return bResult; } +BlockArray* WaveClip::GetSequenceBlockArray() +{ + return mSequence->GetBlockArray(); +} + double WaveClip::GetStartTime() const { // JS: mOffset is the minimum value and it is returned; no clipping to 0 @@ -394,6 +401,11 @@ sampleCount WaveClip::GetEndSample() const return GetStartSample() + mSequence->GetNumSamples(); } +sampleCount WaveClip::GetNumSamples() const +{ + return mSequence->GetNumSamples(); +} + bool WaveClip::WithinClip(double t) const { sampleCount ts = (sampleCount)floor(t * mRate + 0.5); @@ -846,7 +858,8 @@ void SpecCache::CalculateOneSpectrum rate, results, autocorrelation, settings.windowType); #endif // EXPERIMENTAL_USE_REALFFTF - if (!gainFactors.empty()) { + if (!autocorrelation && + !gainFactors.empty()) { // Apply a frequency-dependant gain factor for (int ii = 0; ii < half; ++ii) results[ii] += gainFactors[ii]; @@ -902,8 +915,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; diff --git a/src/WaveClip.h b/src/WaveClip.h index 07bd5230bdaf123ae0a43501296e9797e4d69b63..0beddc6ddc74757590c851772d6cc51bd4274f73 100644 --- a/src/WaveClip.h +++ b/src/WaveClip.h @@ -14,7 +14,6 @@ #include "Audacity.h" #include "SampleFormat.h" -#include "Sequence.h" #include "widgets/ProgressDialog.h" #include "ondemand/ODTaskThread.h" #include "xml/XMLTagHandler.h" @@ -31,7 +30,10 @@ #include <vector> +class BlockArray; +class DirManager; class Envelope; +class Sequence; class SpectrogramSettings; class WaveCache; class WaveTrackCache; @@ -127,6 +129,7 @@ public: len = cacheLen; values = new float[len]; valid = false; + scaleType = 0; range = gain = -1; minFreq = maxFreq = -1; } @@ -140,6 +143,7 @@ public: float *values; bool valid; + int scaleType; int range; int gain; int minFreq; @@ -247,7 +251,7 @@ public: double GetEndTime() const; sampleCount GetStartSample() const; sampleCount GetEndSample() const; - sampleCount GetNumSamples() const { return mSequence->GetNumSamples(); } + sampleCount GetNumSamples() const; // One and only one of the following is true for a given t (unless the clip // has zero length -- then BeforeClip() and AfterClip() can both be true). @@ -262,7 +266,7 @@ public: sampleCount start, sampleCount len); Envelope* GetEnvelope() { return mEnvelope; } - BlockArray* GetSequenceBlockArray() { return mSequence->GetBlockArray(); } + BlockArray* GetSequenceBlockArray(); // Get low-level access to the sequence. Whenever possible, don't use this, // but use more high-level functions inside WaveClip (or add them if you diff --git a/src/WaveTrack.cpp b/src/WaveTrack.cpp index 02f2c183fa22053fb270bf5617c99f97191de1b6..394ed1c5e9a9783c1bfff0966acd16e239c7fcbd 100644 --- a/src/WaveTrack.cpp +++ b/src/WaveTrack.cpp @@ -39,8 +39,6 @@ Track classes. #include "float_cast.h" -#include "LabelTrack.h" - #include "Envelope.h" #include "Sequence.h" #include "Spectrum.h" @@ -54,6 +52,8 @@ Track classes. #include "ondemand/ODManager.h" #include "effects/TimeWarper.h" +#include "prefs/SpectrumPrefs.h" +#include "prefs/WaveformPrefs.h" using std::max; @@ -72,8 +72,10 @@ WaveTrack *TrackFactory::NewWaveTrack(sampleFormat format, double rate) return new WaveTrack(mDirManager, format, rate); } -WaveTrack::WaveTrack(DirManager *projDirManager, sampleFormat format, double rate): +WaveTrack::WaveTrack(DirManager *projDirManager, sampleFormat format, double rate) : Track(projDirManager) + , mpSpectrumSettings(0) + , mpWaveformSettings(0) { if (format == (sampleFormat)0) { @@ -99,15 +101,20 @@ WaveTrack::WaveTrack(DirManager *projDirManager, sampleFormat format, double rat mDisplayNumLocations = 0; mDisplayLocations = NULL; mDisplayNumLocationsAllocated = 0; - mLastDisplay = -1; + mLastScaleType = -1; mAutoSaveIdent = 0; } WaveTrack::WaveTrack(WaveTrack &orig): Track(orig) + , mpSpectrumSettings(orig.mpSpectrumSettings + ? new SpectrogramSettings(*orig.mpSpectrumSettings) : 0 + ) + , mpWaveformSettings(orig.mpWaveformSettings + ? new WaveformSettings(*orig.mpWaveformSettings) : 0) { mDisplay = FindDefaultViewMode(); - mLastDisplay = -1; + mLastScaleType = -1; mLegacyProjectFileOffset = 0; @@ -139,9 +146,14 @@ 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); + SetWaveformSettings + (wt.mpWaveformSettings ? new WaveformSettings(*wt.mpWaveformSettings) : 0); } Track::Merge(orig); } @@ -159,6 +171,8 @@ WaveTrack::~WaveTrack() if (mDisplayLocations) delete [] mDisplayLocations; + delete mpSpectrumSettings; + delete mpWaveformSettings; } double WaveTrack::GetOffset() const @@ -195,7 +209,7 @@ WaveTrack::WaveTrackDisplay WaveTrack::FindDefaultViewMode() if (viewMode < 0) { int oldMode; gPrefs->Read(wxT("/GUI/DefaultViewMode"), &oldMode, - int(WaveTrack::WaveformDisplay)); + int(WaveTrack::Waveform)); viewMode = WaveTrack::ConvertLegacyDisplayValue(oldMode); } @@ -222,15 +236,22 @@ WaveTrack::ConvertLegacyDisplayValue(int oldValue) switch (oldValue) { default: case Waveform: - newValue = WaveTrack::WaveformDisplay; break; + case WaveformDB: + newValue = WaveTrack::Waveform; break; + /* case WaveformDB: newValue = WaveTrack::WaveformDBDisplay; break; + */ case Spectrogram: - newValue = WaveTrack::SpectrumDisplay; break; + case SpectrogramLogF: + case Pitch: + newValue = WaveTrack::Spectrum; break; + /* case SpectrogramLogF: newValue = WaveTrack::SpectrumLogDisplay; break; case Pitch: newValue = WaveTrack::PitchDisplay; break; + */ } return newValue; } @@ -239,11 +260,26 @@ WaveTrack::ConvertLegacyDisplayValue(int oldValue) WaveTrack::WaveTrackDisplay WaveTrack::ValidateWaveTrackDisplay(WaveTrackDisplay display) { - // To do, in future: detect obsolete values between min and max - if (display >= int(MinDisplay) && display <= int(MaxDisplay)) + switch (display) { + // non-obsolete codes + case Waveform: + case Spectrum: return display; - else + + // obsolete codes + case obsolete1: // was SpectrumLogDisplay + case obsolete2: // was SpectralSelectionDisplay + case obsolete3: // was SpectralSelectionLogDisplay + case obsolete4: // was PitchDisplay + return Spectrum; + + case obsolete5: // was WaveformDBDisplay + return Waveform; + + // codes out of bounds (from future prefs files?) + default: return MinDisplay; + } } void WaveTrack::GetDisplayBounds(float *min, float *max) @@ -624,6 +660,69 @@ 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; + } +} + +const WaveformSettings &WaveTrack::GetWaveformSettings() const +{ + if (mpWaveformSettings) + return *mpWaveformSettings; + else + return WaveformSettings::defaults(); +} + +WaveformSettings &WaveTrack::GetWaveformSettings() +{ + if (mpWaveformSettings) + return *mpWaveformSettings; + else + return WaveformSettings::defaults(); +} + +WaveformSettings &WaveTrack::GetIndependentWaveformSettings() +{ + if (!mpWaveformSettings) + mpWaveformSettings = new WaveformSettings(WaveformSettings::defaults()); + return *mpWaveformSettings; +} + +void WaveTrack::SetWaveformSettings(WaveformSettings *pSettings) +{ + if (mpWaveformSettings != pSettings) { + delete mpWaveformSettings; + mpWaveformSettings = pSettings; + } +} + // // ClearAndPaste() is a specialized version of HandleClear() // followed by Paste() and is used mostly by effects that @@ -2306,7 +2405,7 @@ void WaveTrack::UpdateLocationsCache() it = it->GetNext()) { // Add cut line expander point - mDisplayLocations[curpos].typ = locationCutLine; + mDisplayLocations[curpos].typ = WaveTrackLocation::locationCutLine; mDisplayLocations[curpos].pos = clip->GetOffset() + it->GetData()->GetOffset(); curpos++; @@ -2320,7 +2419,7 @@ void WaveTrack::UpdateLocationsCache() < WAVETRACK_MERGE_POINT_TOLERANCE) { // Add merge point - mDisplayLocations[curpos].typ = locationMergePoint; + mDisplayLocations[curpos].typ = WaveTrackLocation::locationMergePoint; mDisplayLocations[curpos].pos = clips.Item(i-1)->GetEndTime(); mDisplayLocations[curpos].clipidx1 = mClips.IndexOf(previousClip); mDisplayLocations[curpos].clipidx2 = mClips.IndexOf(clip); diff --git a/src/WaveTrack.h b/src/WaveTrack.h index 065f649483b3e80c99bd8c791b19f3becae3b8f5..61c063e36a8bf5be7daf31275a803151b357e8be 100644 --- a/src/WaveTrack.h +++ b/src/WaveTrack.h @@ -13,7 +13,6 @@ #include "Track.h" #include "SampleFormat.h" -#include "Sequence.h" #include "WaveClip.h" #include "Experimental.h" #include "widgets/ProgressDialog.h" @@ -22,6 +21,10 @@ #include <wx/longlong.h> #include <wx/thread.h> +#include "WaveTrackLocation.h" + +class SpectrogramSettings; +class WaveformSettings; class TimeWarper; // @@ -51,7 +54,7 @@ WX_DEFINE_ARRAY( Region*, Regions ); class Envelope; -class AUDACITY_DLL_API WaveTrack: public Track { +class AUDACITY_DLL_API WaveTrack : public Track { private: @@ -77,22 +80,8 @@ class AUDACITY_DLL_API WaveTrack: public Track { #ifdef EXPERIMENTAL_OUTPUT_DISPLAY static bool mMonoAsVirtualStereo; #endif - enum LocationType { - locationCutLine = 1, - locationMergePoint - }; - struct Location { - // Position of track location - double pos; - - // Type of track location - LocationType typ; - - // Only for typ==locationMergePoint - int clipidx1; // first clip (left one) - int clipidx2; // second clip (right one) - }; + typedef WaveTrackLocation Location; virtual ~WaveTrack(); virtual double GetOffset() const; @@ -145,6 +134,16 @@ 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); + + const WaveformSettings &GetWaveformSettings() const; + WaveformSettings &GetWaveformSettings(); + WaveformSettings &GetIndependentWaveformSettings(); + void SetWaveformSettings(WaveformSettings *pSettings); + // // High-level editing // @@ -172,9 +171,6 @@ class AUDACITY_DLL_API WaveTrack: public Track { virtual bool Join (double t0, double t1); virtual bool Disjoin (double t0, double t1); - typedef bool ( WaveTrack::* EditFunction )( double, double ); - typedef bool ( WaveTrack::* EditDestFunction )( double, double, Track** ); - virtual bool Trim (double t0, double t1); bool HandleClear(double t0, double t1, bool addCutLines, bool split); @@ -408,19 +404,21 @@ class AUDACITY_DLL_API WaveTrack: public Track { // DO NOT REORDER OLD VALUES! Replace obsoletes with placeholders. - WaveformDisplay = 0, - MinDisplay = WaveformDisplay, + Waveform = 0, + MinDisplay = Waveform, + + obsolete5, // was WaveformDBDisplay + + Spectrum, - WaveformDBDisplay, - SpectrumDisplay, - SpectrumLogDisplay, - SpectralSelectionDisplay, - SpectralSelectionLogDisplay, - PitchDisplay, + obsolete1, // was SpectrumLogDisplay + obsolete2, // was SpectralSelectionDisplay + obsolete3, // was SpectralSelectionLogDisplay + obsolete4, // was PitchDisplay // Add values here, and update MaxDisplay. - MaxDisplay = PitchDisplay, + MaxDisplay = Spectrum, NoDisplay, // Preview track has no display }; @@ -434,18 +432,15 @@ class AUDACITY_DLL_API WaveTrack: public Track { // Handle restriction of range of values of the enum from future versions static WaveTrackDisplay ValidateWaveTrackDisplay(WaveTrackDisplay display); - void SetDisplay(WaveTrackDisplay display) { - if(mDisplay < 2) - // remember last display mode for wave and wavedb so they can remap the vertical ruler - mLastDisplay = mDisplay; - mDisplay = display; - if( mDisplay == SpectralSelectionDisplay ){ - } - if( mDisplay == SpectralSelectionLogDisplay ){ - } + int GetLastScaleType() { return mLastScaleType; } + void SetLastScaleType(int scaleType) + { + // remember last display mode for wave and wavedb so vertical ruler can remap + mLastScaleType = scaleType; } + WaveTrackDisplay GetDisplay() const { return mDisplay; } - int GetLastDisplay() {return mLastDisplay;} + void SetDisplay(WaveTrackDisplay display) { mDisplay = display; } void GetDisplayBounds(float *min, float *max); void SetDisplayBounds(float min, float max); @@ -471,7 +466,7 @@ class AUDACITY_DLL_API WaveTrack: public Track { float mDisplayMin; float mDisplayMax; WaveTrackDisplay mDisplay; - int mLastDisplay; // last display mode + int mLastScaleType; // last scale type choice int mDisplayNumLocations; int mDisplayNumLocationsAllocated; Location* mDisplayLocations; @@ -490,6 +485,9 @@ class AUDACITY_DLL_API WaveTrack: public Track { wxCriticalSection mAppendCriticalSection; double mLegacyProjectFileOffset; int mAutoSaveIdent; + + SpectrogramSettings *mpSpectrumSettings; + WaveformSettings *mpWaveformSettings; }; // This is meant to be a short-lived object, during whose lifetime, diff --git a/src/WaveTrackLocation.h b/src/WaveTrackLocation.h new file mode 100644 index 0000000000000000000000000000000000000000..ddb9b2477f97be71dba037323eee43e40dd574e1 --- /dev/null +++ b/src/WaveTrackLocation.h @@ -0,0 +1,32 @@ +/********************************************************************** + +Audacity: A Digital Audio Editor + +WaveTrackLocation.h + +Paul Licameli -- split from WaveTrack.h + +**********************************************************************/ + +#ifndef __AUDACITY_WAVE_TRACK_LOCATION__ +#define __AUDACITY_WAVE_TRACK_LOCATION__ + +struct WaveTrackLocation { + + enum LocationType { + locationCutLine = 1, + locationMergePoint + }; + + // Position of track location + double pos; + + // Type of track location + LocationType typ; + + // Only for typ==locationMergePoint + int clipidx1; // first clip (left one) + int clipidx2; // second clip (right one) +}; + +#endif diff --git a/src/commands/CompareAudioCommand.cpp b/src/commands/CompareAudioCommand.cpp index 6957116b5109b169c953da898b1498eb068b460b..35833b9d5cf6a1bae2f6aeebbf2ac6eaaeb1d091 100644 --- a/src/commands/CompareAudioCommand.cpp +++ b/src/commands/CompareAudioCommand.cpp @@ -20,6 +20,7 @@ threshold of difference in two selected tracks #include "CompareAudioCommand.h" #include "../Project.h" #include "Command.h" +#include "../WaveTrack.h" wxString CompareAudioCommandType::BuildName() { diff --git a/src/commands/GetProjectInfoCommand.cpp b/src/commands/GetProjectInfoCommand.cpp index 46fb010afebe8b45da46c3f56bfc3fdb67358f5c..cc43d26cc20f8f3e6134a55a7d7b2a8dd53a41e8 100644 --- a/src/commands/GetProjectInfoCommand.cpp +++ b/src/commands/GetProjectInfoCommand.cpp @@ -20,7 +20,6 @@ #include "../TrackPanel.h" #include "../Project.h" #include "../Track.h" -#include "../WaveTrack.h" wxString GetProjectInfoCommandType::BuildName() { @@ -149,3 +148,23 @@ void GetProjectInfoCommand::SendTracksInfo(TrackList *projTracks, } Status(boolValueStr); } + +bool GetProjectInfoCommand::testSelected(Track * track) const +{ + return track->GetSelected(); +} + +bool GetProjectInfoCommand::testLinked(Track * track) const +{ + return track->GetLinked(); +} + +bool GetProjectInfoCommand::testSolo(Track * track) const +{ + return track->GetSolo(); +} + +bool GetProjectInfoCommand::testMute(Track * track) const +{ + return track->GetMute(); +} diff --git a/src/commands/GetProjectInfoCommand.h b/src/commands/GetProjectInfoCommand.h index 6f9942c159bb3ebbb094a243ea1dc6b793a3c21c..329f619d28b3a01e77612d50a6eecc6898f61067 100644 --- a/src/commands/GetProjectInfoCommand.h +++ b/src/commands/GetProjectInfoCommand.h @@ -18,7 +18,6 @@ #include "Command.h" #include "CommandType.h" -#include "../Track.h" class GetProjectInfoCommandType : public CommandType { @@ -51,10 +50,10 @@ private: void SendTracksInfo(TrackList *projTracks, Getter); // Functions pointed to for getting track parameters - bool testSelected(Track * track) const {return track->GetSelected();} - bool testLinked( Track * track) const {return track->GetLinked();} - bool testSolo( Track * track) const {return track->GetSolo();} - bool testMute( Track * track) const {return track->GetMute();} + bool testSelected(Track * track) const; + bool testLinked(Track * track) const; + bool testSolo(Track * track) const; + bool testMute(Track * track) const; }; diff --git a/src/commands/GetTrackInfoCommand.cpp b/src/commands/GetTrackInfoCommand.cpp index 7c3e9f786fe1d608f1d9e30f1bf6750a4963b8f2..daf44c0c47be9b36d7f4594faf510beea1dfa887 100644 --- a/src/commands/GetTrackInfoCommand.cpp +++ b/src/commands/GetTrackInfoCommand.cpp @@ -19,7 +19,6 @@ #include "GetTrackInfoCommand.h" #include "../TrackPanel.h" #include "../Project.h" -#include "../Track.h" #include "../WaveTrack.h" wxString GetTrackInfoCommandType::BuildName() diff --git a/src/commands/ImportExportCommands.cpp b/src/commands/ImportExportCommands.cpp index 548af3ebee905a17f7da85a015936e8ffe639be3..4a6b6885a7ad7361c288b18c1d2d1bc305456c40 100644 --- a/src/commands/ImportExportCommands.cpp +++ b/src/commands/ImportExportCommands.cpp @@ -15,6 +15,7 @@ #include "ImportExportCommands.h" #include "../Project.h" +#include "../Track.h" #include "../export/Export.h" // Import diff --git a/src/commands/ScreenshotCommand.cpp b/src/commands/ScreenshotCommand.cpp index 30dd1e43347d6b5840c8cc16d48d881634017ebc..5410c003fbdd1f6ac9f765cbdb42943712d1f5d8 100644 --- a/src/commands/ScreenshotCommand.cpp +++ b/src/commands/ScreenshotCommand.cpp @@ -25,6 +25,7 @@ project window. #include <wx/settings.h> #include <wx/bitmap.h> +#include "../Track.h" #include "../TrackPanel.h" #include "../toolbars/ToolManager.h" #include "../toolbars/ToolBar.h" diff --git a/src/commands/SelectCommand.cpp b/src/commands/SelectCommand.cpp index 087ad6cc40b71dfb6b34028d865ef3a19ddeb0dd..f689135e333df9555741940598f335a341f44152 100644 --- a/src/commands/SelectCommand.cpp +++ b/src/commands/SelectCommand.cpp @@ -19,6 +19,7 @@ #include "SelectCommand.h" #include <wx/string.h> #include "../Project.h" +#include "../Track.h" wxString SelectCommandType::BuildName() { diff --git a/src/commands/SetProjectInfoCommand.cpp b/src/commands/SetProjectInfoCommand.cpp index d96b60fa4240cdc4e974281e1efc726f0a9e6107..1724cacba279b4752d5074aceb6f49d70bf95754 100644 --- a/src/commands/SetProjectInfoCommand.cpp +++ b/src/commands/SetProjectInfoCommand.cpp @@ -19,7 +19,6 @@ #include "SetProjectInfoCommand.h" #include "../Project.h" #include "../Track.h" -#include "../WaveTrack.h" // The following parameters have a boolean string, indicated by the kSetOfTracksStr #define kSetOfTracksStr "TrackSet" diff --git a/src/effects/Amplify.cpp b/src/effects/Amplify.cpp index ce9dea8801222b07ea92c57b49c1e684878c4d67..dc2e73d73f3ec2ae83d0d2276ea58d8a9a40f9a2 100644 --- a/src/effects/Amplify.cpp +++ b/src/effects/Amplify.cpp @@ -65,7 +65,7 @@ END_EVENT_TABLE() EffectAmplify::EffectAmplify() { mAmp = DEF_Amp; - mRatio = pow(10.0, mAmp / 20.0); + mRatio = DB_TO_LINEAR(mAmp); mRatioClip = 0.0; mCanClip = false; mPeak = 0.0; @@ -211,10 +211,11 @@ void EffectAmplify::PopulateOrExchange(ShuttleGui & S) S.StartVerticalLay(0); { + int precission = 3; // allow (a generous) 3 decimal places for Amplification (dB) // Amplitude S.StartMultiColumn(2, wxCENTER); { - FloatingPointValidator<double> vldAmp(2, &mAmp); + FloatingPointValidator<double> vldAmp(precission, &mAmp, NUM_VAL_ONE_TRAILING_ZERO); vldAmp.SetRange(MIN_Amp, MAX_Amp); mAmpT = S.Id(ID_Amp).AddTextBox(_("Amplification (dB):"), wxT(""), 12); mAmpT->SetValidator(vldAmp); @@ -233,10 +234,10 @@ void EffectAmplify::PopulateOrExchange(ShuttleGui & S) // Peak S.StartMultiColumn(2, wxCENTER); { - int precission = 2; - FloatingPointValidator<double> vldNewPeak(precission, &mNewPeak); - double minAmp = MIN_Amp + (20.0 * log10(mPeak)); - double maxAmp = MAX_Amp + (20.0 * log10(mPeak)); + // One extra decimal place so that rounding is visible to user (see: bug 958) + FloatingPointValidator<double> vldNewPeak(precission + 1, &mNewPeak, NUM_VAL_ONE_TRAILING_ZERO); + double minAmp = MIN_Amp + LINEAR_TO_DB(mPeak); + double maxAmp = MAX_Amp + LINEAR_TO_DB(mPeak); // min and max need same precision as what we're validating (bug 963) minAmp = Internat::CompatibleToDouble(Internat::ToString(minAmp, precission)); @@ -268,17 +269,17 @@ void EffectAmplify::PopulateOrExchange(ShuttleGui & S) bool EffectAmplify::TransferDataToWindow() { // limit range of gain - double dBInit = 20.0*log10(mRatio); + double dBInit = LINEAR_TO_DB(mRatio); double dB = TrapDouble(dBInit, MIN_Amp, MAX_Amp); if (dB != dBInit) - mRatio = pow(10.0, dB / 20.0); + mRatio = DB_TO_LINEAR(dB); - mAmp = 20.0 * log10(mRatio); + mAmp = LINEAR_TO_DB(mRatio); mAmpT->GetValidator()->TransferToWindow(); mAmpS->SetValue((int) (mAmp * SCL_Amp + 0.5f)); - mNewPeak = 20.0 * log10(mRatio * mPeak); + mNewPeak = LINEAR_TO_DB(mRatio * mPeak); mNewPeakT->GetValidator()->TransferToWindow(); mClip->SetValue(mCanClip); @@ -295,7 +296,7 @@ bool EffectAmplify::TransferDataFromWindow() return false; } - mRatio = pow(10.0, TrapDouble(mAmp * SCL_Amp, MIN_Amp * SCL_Amp, MAX_Amp * SCL_Amp) / (20.0 * SCL_Amp)); + mRatio = DB_TO_LINEAR(TrapDouble(mAmp * SCL_Amp, MIN_Amp * SCL_Amp, MAX_Amp * SCL_Amp) / SCL_Amp); mCanClip = mClip->GetValue(); @@ -322,11 +323,11 @@ void EffectAmplify::OnAmpText(wxCommandEvent & WXUNUSED(evt)) return; } - mRatio = pow(10.0, TrapDouble(mAmp * SCL_Amp, MIN_Amp * SCL_Amp, MAX_Amp * SCL_Amp) / (20.0 * SCL_Amp)); + mRatio = DB_TO_LINEAR(TrapDouble(mAmp * SCL_Amp, MIN_Amp * SCL_Amp, MAX_Amp * SCL_Amp) / SCL_Amp); - mAmpS->SetValue((int) (20.0 * log10(mRatio) * SCL_Amp + 0.5)); + mAmpS->SetValue((int) (LINEAR_TO_DB(mRatio) * SCL_Amp + 0.5)); - mNewPeak = 20.0 * log10(mRatio * mPeak); + mNewPeak = LINEAR_TO_DB(mRatio * mPeak); mNewPeakT->GetValidator()->TransferToWindow(); CheckClip(); @@ -343,12 +344,12 @@ void EffectAmplify::OnPeakText(wxCommandEvent & WXUNUSED(evt)) if (mNewPeak == 0.0) mRatio = mRatioClip; else - mRatio = pow(10.0, mNewPeak / 20.0) / mPeak; + mRatio = DB_TO_LINEAR(mNewPeak) / mPeak; - double ampInit = 20.0 * log10(mRatio); + double ampInit = LINEAR_TO_DB(mRatio); mAmp = TrapDouble(ampInit, MIN_Amp, MAX_Amp); if (mAmp != ampInit) - mRatio = pow(10.0, mAmp / 20.0); + mRatio = DB_TO_LINEAR(mAmp); mAmpT->GetValidator()->TransferToWindow(); @@ -360,20 +361,20 @@ void EffectAmplify::OnPeakText(wxCommandEvent & WXUNUSED(evt)) void EffectAmplify::OnAmpSlider(wxCommandEvent & evt) { double dB = evt.GetInt() / SCL_Amp; - mRatio = pow(10.0, TrapDouble(dB, MIN_Amp, MAX_Amp) / 20.0); + mRatio = DB_TO_LINEAR(TrapDouble(dB, MIN_Amp, MAX_Amp)); double dB2 = (evt.GetInt() - 1) / SCL_Amp; - double ratio2 = pow(10.0, TrapDouble(dB2, MIN_Amp, MAX_Amp) / 20.0); + double ratio2 = DB_TO_LINEAR(TrapDouble(dB2, MIN_Amp, MAX_Amp)); if (!mClip->GetValue() && mRatio * mPeak > 1.0 && ratio2 * mPeak < 1.0) { mRatio = 1.0 / mPeak; } - mAmp = 20.0 * log10(mRatio); + mAmp = LINEAR_TO_DB(mRatio); mAmpT->GetValidator()->TransferToWindow(); - mNewPeak = 20.0 * log10(mRatio * mPeak); + mNewPeak = LINEAR_TO_DB(mRatio * mPeak); mNewPeakT->GetValidator()->TransferToWindow(); CheckClip(); diff --git a/src/effects/AutoDuck.cpp b/src/effects/AutoDuck.cpp index a582c38005f17c503454c97c01518d3ae9eb46d7..5f3db54ffd5235862b60b73e2ad24a1680577154 100644 --- a/src/effects/AutoDuck.cpp +++ b/src/effects/AutoDuck.cpp @@ -33,6 +33,8 @@ #include "../Theme.h" #include "../widgets/valnum.h" +#include "../WaveTrack.h" + // Define keys, defaults, minimums, and maximums for the effect parameters // // Name Type Key Def Min Max Scale @@ -278,7 +280,7 @@ bool EffectAutoDuck::Process() sampleCount minSamplesPause = mControlTrack->TimeToLongSamples(maxPause); - double threshold = pow(10.0, mThresholdDb/20); + double threshold = DB_TO_LINEAR(mThresholdDb); // adjust the threshold so we can compare it to the rmsSum value threshold = threshold * threshold * kRMSWindowSize; @@ -553,7 +555,7 @@ bool EffectAutoDuck::ApplyDuckFade(int trackNumber, WaveTrack* t, if (gain < mDuckAmountDb) gain = mDuckAmountDb; - buf[i - pos] *= pow(10.0, gain / 20.0); + buf[i - pos] *= DB_TO_LINEAR(gain); } t->Set((samplePtr)buf, floatSample, pos, len); diff --git a/src/effects/AutoDuck.h b/src/effects/AutoDuck.h index 45a8878d177cd6023b3bc9c7929012302b406ef8..ede5f31bc5211672e67e5141d96b9a1271cb6d57 100644 --- a/src/effects/AutoDuck.h +++ b/src/effects/AutoDuck.h @@ -19,8 +19,6 @@ #include <wx/textctrl.h> #include <wx/window.h> -#include "../WaveTrack.h" - #include "Effect.h" class EffectAutoDuckPanel; diff --git a/src/effects/BassTreble.cpp b/src/effects/BassTreble.cpp index 131cc153cbcf2d8e48dd89b593a021644c8a1b58..e524e7f9004321549da9514fc9de2a5bc5bee553 100644 --- a/src/effects/BassTreble.cpp +++ b/src/effects/BassTreble.cpp @@ -44,8 +44,8 @@ enum // Define keys, defaults, minimums, and maximums for the effect parameters // // Name Type Key Def Min Max Scale -Param( Bass, double, XO("Bass"), 0.0, -15.0, 15.0, 1 ); -Param( Treble, double, XO("Treble"), 0.0, -15.0, 15.0, 1 ); +Param( Bass, double, XO("Bass"), 0.0, -30.0, 30.0, 1 ); +Param( Treble, double, XO("Treble"), 0.0, -30.0, 30.0, 1 ); Param( Level, double, XO("Level"), -1.0, -30.0, 0.0, 1 ); Param( Normalize, bool, XO("Normalize"), true, false, true, 1 ); @@ -155,7 +155,7 @@ sampleCount EffectBassTreble::ProcessBlock(float **inBlock, float **outBlock, sa } else { - float gain = (pow(10.0, dB_level / 20.0f)) / mMax; + float gain = DB_TO_LINEAR(dB_level) / mMax; for (sampleCount i = 0; i < blockLen; i++) { // Normalize to specified level diff --git a/src/effects/ChangeSpeed.cpp b/src/effects/ChangeSpeed.cpp index a7245b876341122d78612d800d60c786a8e58c3f..705df25bd9084690fb55b005105011f9aac34436 100644 --- a/src/effects/ChangeSpeed.cpp +++ b/src/effects/ChangeSpeed.cpp @@ -14,12 +14,12 @@ *//*******************************************************************/ #include "../Audacity.h" +#include "ChangeSpeed.h" #include <math.h> #include <wx/intl.h> -#include "../Envelope.h" #include "../LabelTrack.h" #include "../Prefs.h" #include "../Project.h" @@ -27,9 +27,8 @@ #include "../ShuttleGui.h" #include "../widgets/valnum.h" -#include "ChangeSpeed.h" - #include "TimeWarper.h" +#include "../WaveTrack.h" enum { diff --git a/src/effects/ChangeSpeed.h b/src/effects/ChangeSpeed.h index 67a6c912b6e3367839a51b1ee4d210a33a9d348c..7df4ef8d4c36bb30e0f06a5f747d3585f169a2ba 100644 --- a/src/effects/ChangeSpeed.h +++ b/src/effects/ChangeSpeed.h @@ -19,8 +19,6 @@ #include <wx/string.h> #include <wx/textctrl.h> -#include "../Track.h" -#include "../WaveTrack.h" #include "../widgets/NumericTextCtrl.h" #include "Effect.h" diff --git a/src/effects/ClickRemoval.cpp b/src/effects/ClickRemoval.cpp index 81e616f65cb34790854b4619f58d4991785390cc..73943daef0b663fa3174092354792fd3f164cd9b 100644 --- a/src/effects/ClickRemoval.cpp +++ b/src/effects/ClickRemoval.cpp @@ -37,6 +37,8 @@ #include "../ShuttleGui.h" #include "../widgets/valnum.h" +#include "../WaveTrack.h" + enum { ID_Thresh = 10000, diff --git a/src/effects/ClickRemoval.h b/src/effects/ClickRemoval.h index 5723f09d5a4a29c62aaaceec376e2944c31ed337..723fd9e59bd5b079a1d8b0bcb23133de343a87c5 100644 --- a/src/effects/ClickRemoval.h +++ b/src/effects/ClickRemoval.h @@ -21,11 +21,9 @@ #include <wx/string.h> #include <wx/textctrl.h> -#include "../Envelope.h" -#include "../WaveTrack.h" - #include "Effect.h" +class Envelope; class ShuttleGui; #define CLICKREMOVAL_PLUGIN_SYMBOL XO("Click Removal") diff --git a/src/effects/Compressor.cpp b/src/effects/Compressor.cpp index 0d8e8752e417832dda4a542c1f90de0b8f9b99a3..ca506eb77a7abed3e51145f6d21dcf46f95b0295 100644 --- a/src/effects/Compressor.cpp +++ b/src/effects/Compressor.cpp @@ -41,6 +41,8 @@ #include "../float_cast.h" #include "../widgets/Ruler.h" +#include "../WaveTrack.h" + enum { ID_Threshold = 10000, @@ -328,8 +330,8 @@ bool EffectCompressor::TransferDataFromWindow() bool EffectCompressor::NewTrackPass1() { - mThreshold = pow(10.0, mThresholdDB/20); // factor of 20 because it's power - mNoiseFloor = pow(10.0, mNoiseFloorDB/20); + mThreshold = DB_TO_LINEAR(mThresholdDB); + mNoiseFloor = DB_TO_LINEAR(mNoiseFloorDB); mNoiseCounter = 100; mAttackInverseFactor = exp(log(mThreshold) / (mCurRate * mAttackTime + 0.5)); diff --git a/src/effects/Contrast.cpp b/src/effects/Contrast.cpp index 0ca8cb3db7447131bd22b39b49cdd710019df815..d5576531cb6a4ef9d9ac99bf4e758553e189ad52 100644 --- a/src/effects/Contrast.cpp +++ b/src/effects/Contrast.cpp @@ -14,7 +14,6 @@ #include "../AudacityApp.h" -#include "../Envelope.h" #include "../FFT.h" #include "../WaveTrack.h" #include "../Prefs.h" @@ -112,7 +111,7 @@ float ContrastDialog::GetDB() { if( rms < 1.0E-30 ) return -60.0; - return 20.0*log10(rms); + return LINEAR_TO_DB(rms); } else { diff --git a/src/effects/Effect.cpp b/src/effects/Effect.cpp index 22cd355e876517464dd1d354c8ec4d1a3d184f9d..57b3bf830d3caa23a12e0986fc90ea4426a47c21 100644 --- a/src/effects/Effect.cpp +++ b/src/effects/Effect.cpp @@ -2060,6 +2060,11 @@ TimeWarper *Effect::GetTimeWarper() // Use these two methods to copy the input tracks to mOutputTracks, if // doing the processing on them, and replacing the originals only on success (and not cancel). // Copy the group tracks that have tracks selected +void Effect::CopyInputTracks() +{ + CopyInputTracks(Track::Wave); +} + void Effect::CopyInputTracks(int trackType) { // Reset map diff --git a/src/effects/Effect.h b/src/effects/Effect.h index 973e3d33efb6d8c98a8e7c20087349d393fb519c..1cf24f6b1003e612f1d37c0d6e285256d4a22bb5 100644 --- a/src/effects/Effect.h +++ b/src/effects/Effect.h @@ -30,7 +30,6 @@ class wxWindow; #include "audacity/EffectInterface.h" #include "../Experimental.h" -#include "../WaveTrack.h" #include "../SelectedRegion.h" #include "../Shuttle.h" #include "../Internat.h" @@ -40,9 +39,14 @@ class ShuttleGui; #define BUILTIN_EFFECT_PREFIX wxT("Built-in Effect: ") +class AudacityProject; class SelectedRegion; class TimeWarper; class EffectUIHost; +class Track; +class TrackList; +class TrackFactory; +class WaveTrack; // TODO: Apr-06-2015 // TODO: Much more cleanup of old methods and variables is needed, but @@ -337,7 +341,8 @@ protected: // Use these two methods to copy the input tracks to mOutputTracks, if // doing the processing on them, and replacing the originals only on success (and not cancel). - void CopyInputTracks(int trackType = Track::Wave); + void CopyInputTracks(); // trackType = Track::Wave + void CopyInputTracks(int trackType); // If bGoodResult, replace mWaveTracks tracks in mTracks with successfully processed // mOutputTracks copies, get rid of old mWaveTracks, and set mWaveTracks to mOutputTracks. diff --git a/src/effects/Equalization.cpp b/src/effects/Equalization.cpp index ac81f46eaa2a470f1e8248611c55e2b869c7067f..fab552507d342ecd7259844856e20360a86204c7 100644 --- a/src/effects/Equalization.cpp +++ b/src/effects/Equalization.cpp @@ -53,6 +53,7 @@ #include "../Audacity.h" +#include "Equalization.h" #include <math.h> #include <vector> @@ -95,13 +96,10 @@ #include "../xml/XMLFileReader.h" #include "../Theme.h" #include "../AllThemeResources.h" -#include "../WaveTrack.h" #include "../float_cast.h" #include "FileDialog.h" -#include "Equalization.h" - #ifdef EXPERIMENTAL_EQ_SSE_THREADED #include "Equalization48x.h" #endif @@ -1182,13 +1180,13 @@ bool EffectEqualization::CalcFilter() } mFilterFuncR[mWindowSize/2] = val1; - mFilterFuncR[0] = (float)(pow(10., mFilterFuncR[0]/20.)); + mFilterFuncR[0] = DB_TO_LINEAR(mFilterFuncR[0]); for(i=1;i<mWindowSize/2;i++) { - mFilterFuncR[i] = (float)(pow(10., mFilterFuncR[i]/20.)); + mFilterFuncR[i] = DB_TO_LINEAR(mFilterFuncR[i]); mFilterFuncR[mWindowSize-i]=mFilterFuncR[i]; //Fill entire array } - mFilterFuncR[i] = (float)(pow(10., mFilterFuncR[i]/20.)); //do last one + mFilterFuncR[i] = DB_TO_LINEAR(mFilterFuncR[i]); //do last one //transfer to time domain to do the padding and windowing float *outr = new float[mWindowSize]; @@ -2773,7 +2771,7 @@ void EqualizationPanel::OnPaint(wxPaintEvent & WXUNUSED(event)) yF += mOutr[halfM]; yF = fabs(yF); if(yF!=0.) - yF = 20.0*log10(yF); //20 here as an amplitude + yF = LINEAR_TO_DB(yF); else yF = mEffect->mdBMin; } diff --git a/src/effects/Equalization.h b/src/effects/Equalization.h index b07f58f2814ea23534294c42fa9c5d024ae45ab4..a2ec0a9047ade5746728f324834724a352ffb77e 100644 --- a/src/effects/Equalization.h +++ b/src/effects/Equalization.h @@ -35,8 +35,6 @@ #endif #include "Effect.h" -#include "../Envelope.h" -#include "../WaveTrack.h" #include "../xml/XMLTagHandler.h" #include "../widgets/Grid.h" #include "../widgets/Ruler.h" @@ -45,6 +43,7 @@ #define EQUALIZATION_PLUGIN_SYMBOL XO("Equalization") +class Envelope; class EqualizationPanel; // diff --git a/src/effects/FindClipping.cpp b/src/effects/FindClipping.cpp index 864e499b8aa4c5ace0d67fc41ed57496b7dfd752..bccbbec05c30afdbee80506cae5ae350453137d2 100644 --- a/src/effects/FindClipping.cpp +++ b/src/effects/FindClipping.cpp @@ -30,6 +30,9 @@ #include "../ShuttleGui.h" #include "../widgets/valnum.h" +#include "../LabelTrack.h" +#include "../WaveTrack.h" + // Define keys, defaults, minimums, and maximums for the effect parameters // // Name Type Key Def Min Max Scale diff --git a/src/effects/FindClipping.h b/src/effects/FindClipping.h index d5e2270457e09fd7c33feff4d7b3278baabdeea4..0505c253c3a87320f1c989a4646aa27c21f095f6 100644 --- a/src/effects/FindClipping.h +++ b/src/effects/FindClipping.h @@ -14,10 +14,9 @@ class wxString; -#include <wx/string.h> +class LabelTrack; -#include "../LabelTrack.h" -#include "../WaveTrack.h" +#include <wx/string.h> #include "Effect.h" diff --git a/src/effects/Generator.cpp b/src/effects/Generator.cpp index b4b741d998ed11d65a8292d9d6d72fca67ffd326..0c82567b1f9cd710bb0ea0ceb5607b6b4ec66d73 100644 --- a/src/effects/Generator.cpp +++ b/src/effects/Generator.cpp @@ -14,10 +14,12 @@ **********************************************************************/ +#include "Generator.h" + #include "../Project.h" #include "../Prefs.h" +#include "../WaveTrack.h" -#include "Generator.h" #include "TimeWarper.h" #include <memory> diff --git a/src/effects/NoiseReduction.cpp b/src/effects/NoiseReduction.cpp index d02985d0b0f8c3c25a845846f4ff51d6c665cbf4..9081132aff2eb0776371b8b0f533c1dd23a2427e 100644 --- a/src/effects/NoiseReduction.cpp +++ b/src/effects/NoiseReduction.cpp @@ -43,6 +43,8 @@ #include "../ShuttleGui.h" #include "../Prefs.h" +#include "../WaveTrack.h" + #include <algorithm> #include <vector> #include <math.h> @@ -765,10 +767,10 @@ EffectNoiseReduction::Worker::Worker const int nAttackBlocks = 1 + (int)(settings.mAttackTime * sampleRate / mStepSize); const int nReleaseBlocks = 1 + (int)(settings.mReleaseTime * sampleRate / mStepSize); // Applies to amplitudes, divide by 20: - mNoiseAttenFactor = pow(10.0, noiseGain / 20.0); + mNoiseAttenFactor = DB_TO_LINEAR(noiseGain); // Apply to gain factors which apply to amplitudes, divide by 20: - mOneBlockAttack = pow(10.0, (noiseGain / (20.0 * nAttackBlocks))); - mOneBlockRelease = pow(10.0, (noiseGain / (20.0 * nReleaseBlocks))); + mOneBlockAttack = DB_TO_LINEAR(noiseGain / nAttackBlocks); + mOneBlockRelease = DB_TO_LINEAR(noiseGain / nReleaseBlocks); // Applies to power, divide by 10: mOldSensitivityFactor = pow(10.0, settings.mOldSensitivity / 10.0); diff --git a/src/effects/NoiseRemoval.cpp b/src/effects/NoiseRemoval.cpp index 0ac3f4bc206ed148fcd43f15fb930bcb1b5afc61..a1f39364c241a2f170bbda5280b814615b5093c3 100644 --- a/src/effects/NoiseRemoval.cpp +++ b/src/effects/NoiseRemoval.cpp @@ -275,10 +275,8 @@ void EffectNoiseRemoval::Initialize() mFreqSmoothingBins = (int)(mFreqSmoothingHz * mWindowSize / mSampleRate); mAttackDecayBlocks = 1 + (int)(mAttackDecayTime * mSampleRate / (mWindowSize / 2)); - // Applies to amplitudes, divide by 20: - mNoiseAttenFactor = pow(10.0, mNoiseGain/20.0); - // Applies to gain factors which apply to amplitudes, divide by 20: - mOneBlockAttackDecay = pow(10.0, (mNoiseGain / (20.0 * mAttackDecayBlocks))); + mNoiseAttenFactor = DB_TO_LINEAR(mNoiseGain); + mOneBlockAttackDecay = DB_TO_LINEAR(mNoiseGain / mAttackDecayBlocks); // Applies to power, divide by 10: mSensitivityFactor = pow(10.0, mSensitivity/10.0); mMinSignalBlocks = diff --git a/src/effects/Normalize.cpp b/src/effects/Normalize.cpp index 7b090d95f400849e3c7b08690af192b7201045b2..fe3d8971d92e769de87535f025d4e06ee216c1cb 100644 --- a/src/effects/Normalize.cpp +++ b/src/effects/Normalize.cpp @@ -16,6 +16,7 @@ #include "../Audacity.h" // for rint from configwin.h +#include "Normalize.h" #include <math.h> @@ -28,8 +29,6 @@ #include "../WaveTrack.h" #include "../widgets/valnum.h" -#include "Normalize.h" - // Define keys, defaults, minimums, and maximums for the effect parameters // // Name Type Key Def Min Max Scale @@ -152,9 +151,8 @@ bool EffectNormalize::Process() float ratio; if( mGain ) - ratio = pow(10.0,TrapDouble(mLevel, // same value used for all tracks - MIN_Level, - MAX_Level)/20.0); + // same value used for all tracks + ratio = DB_TO_LINEAR(TrapDouble(mLevel, MIN_Level, MAX_Level)); else ratio = 1.0; @@ -285,7 +283,7 @@ void EffectNormalize::PopulateOrExchange(ShuttleGui & S) mGain ? wxT("true") : wxT("false")); mGainCheckBox->SetValidator(wxGenericValidator(&mGain)); - FloatingPointValidator<double> vldLevel(1, &mLevel); + FloatingPointValidator<double> vldLevel(2, &mLevel, NUM_VAL_ONE_TRAILING_ZERO); vldLevel.SetRange(MIN_Level, MAX_Level); mLevelTextCtrl = S.AddTextBox(wxT(""), wxT(""), 10); mLevelTextCtrl->SetName(_("Maximum amplitude dB")); diff --git a/src/effects/Normalize.h b/src/effects/Normalize.h index a5ab075c5b9a2ce5150b363b2196e9b217d065f6..84ac09ac0523af9d8d909776babc93585d3ad454 100644 --- a/src/effects/Normalize.h +++ b/src/effects/Normalize.h @@ -18,8 +18,6 @@ #include <wx/string.h> #include <wx/textctrl.h> -#include "../WaveTrack.h" - #include "Effect.h" class ShuttleGui; diff --git a/src/effects/Paulstretch.cpp b/src/effects/Paulstretch.cpp index 5b1c98a40c2ee974f3fb74caf0a2f069d6a645a9..76e21a04201a98c69de75bd365155fedf0e1e736 100644 --- a/src/effects/Paulstretch.cpp +++ b/src/effects/Paulstretch.cpp @@ -27,11 +27,13 @@ #include "../FFT.h" #include "../widgets/valnum.h" +#include "../WaveTrack.h" + // Define keys, defaults, minimums, and maximums for the effect parameters // // Name Type Key Def Min Max Scale Param( Amount, float, XO("Stretch Factor"), 10.0, 1.0, FLT_MAX, 1 ); -Param( Time, float, XO("Time Resolution"), 0.25f, 0.001f, FLT_MAX, 1 ); +Param( Time, float, XO("Time Resolution"), 0.25f, 0.00099f, FLT_MAX, 1 ); class PaulStretch { @@ -170,7 +172,7 @@ void EffectPaulstretch::PopulateOrExchange(ShuttleGui & S) */ S.AddTextBox(_("Stretch Factor:"), wxT(""), 10)->SetValidator(vldAmount); - FloatingPointValidator<float> vldTime(1, &time_resolution); + FloatingPointValidator<float> vldTime(3, &time_resolution, NUM_VAL_ONE_TRAILING_ZERO); vldTime.SetMin(MIN_Time); S.AddTextBox(_("Time Resolution (seconds):"), wxT(""), 10)->SetValidator(vldTime); } diff --git a/src/effects/Paulstretch.h b/src/effects/Paulstretch.h index 44dbd69fd245d97c22f5d01fc720ab25a3a58903..0741aeb0411d824dc18b85270e772bc8df892809 100644 --- a/src/effects/Paulstretch.h +++ b/src/effects/Paulstretch.h @@ -12,8 +12,6 @@ #include <wx/string.h> -#include "../WaveTrack.h" - #include "Effect.h" class ShuttleGui; diff --git a/src/effects/Phaser.cpp b/src/effects/Phaser.cpp index 260a1dec0d38937bf43b7815b7549f682bd9a429..529353a8224571983eba6b1211be26631b229783 100644 --- a/src/effects/Phaser.cpp +++ b/src/effects/Phaser.cpp @@ -45,8 +45,8 @@ enum // Name Type Key Def Min Max Scale Param( Stages, int, XO("Stages"), 2, 2, NUM_STAGES, 1 ); Param( DryWet, int, XO("DryWet"), 128, 0, 255, 1 ); -Param( Freq, double, XO("Freq"), 0.4, 0.1, 4.0, 10 ); -Param( Phase, double, XO("Phase"), 0.0, 0.0, 359.0, 1 ); +Param( Freq, double, XO("Freq"), 0.4, 0.001,4.0, 10.0 ); +Param( Phase, double, XO("Phase"), 0.0, 0.0, 360.0, 1 ); Param( Depth, int, XO("Depth"), 100, 0, 255, 1 ); Param( Feedback, int, XO("Feedback"), 0, -100, 100, 1 ); @@ -152,7 +152,7 @@ sampleCount EffectPhaser::ProcessBlock(float **inBlock, float **outBlock, sample { double in = ibuf[i]; - double m = in + fbout * mFeedback / 100; + double m = in + fbout * mFeedback / 101; // Feedback must be less than 100% to avoid infinite gain. if (((skipcount++) % lfoskipsamples) == 0) { @@ -222,6 +222,7 @@ bool EffectPhaser::SetAutomationParameters(EffectAutomationParameters & parms) void EffectPhaser::PopulateOrExchange(ShuttleGui & S) { S.SetBorder(5); + S.AddSpace(0, 5); S.StartMultiColumn(3, wxEXPAND); { @@ -229,7 +230,7 @@ void EffectPhaser::PopulateOrExchange(ShuttleGui & S) IntegerValidator<int> vldStages(&mStages); vldStages.SetRange(MIN_Stages, MAX_Stages); - mStagesT = S.Id(ID_Stages).AddTextBox(_("Stages:"), wxT(""), 12); + mStagesT = S.Id(ID_Stages).AddTextBox(_("Stages:"), wxT(""), 15); mStagesT->SetValidator(vldStages); S.SetStyle(wxSL_HORIZONTAL); @@ -240,7 +241,7 @@ void EffectPhaser::PopulateOrExchange(ShuttleGui & S) IntegerValidator<int> vldDryWet(&mDryWet); vldDryWet.SetRange(MIN_DryWet, MAX_DryWet); - mDryWetT = S.Id(ID_DryWet).AddTextBox(_("Dry/Wet:"), wxT(""), 12); + mDryWetT = S.Id(ID_DryWet).AddTextBox(_("Dry/Wet:"), wxT(""), 15); mDryWetT->SetValidator(vldDryWet); S.SetStyle(wxSL_HORIZONTAL); @@ -248,19 +249,19 @@ void EffectPhaser::PopulateOrExchange(ShuttleGui & S) mDryWetS->SetName(_("Dry Wet")); mDryWetS->SetMinSize(wxSize(100, -1)); - FloatingPointValidator<double> vldFreq(1, &mFreq); + FloatingPointValidator<double> vldFreq(5, &mFreq, NUM_VAL_ONE_TRAILING_ZERO); vldFreq.SetRange(MIN_Freq, MAX_Freq); - mFreqT = S.Id(ID_Freq).AddTextBox(_("LFO Frequency (Hz):"), wxT(""), 12); + mFreqT = S.Id(ID_Freq).AddTextBox(_("LFO Frequency (Hz):"), wxT(""), 15); mFreqT->SetValidator(vldFreq); S.SetStyle(wxSL_HORIZONTAL); - mFreqS = S.Id(ID_Freq).AddSlider(wxT(""), DEF_Freq * SCL_Freq, MAX_Freq * SCL_Freq, MIN_Freq * SCL_Freq); + mFreqS = S.Id(ID_Freq).AddSlider(wxT(""), DEF_Freq * SCL_Freq, MAX_Freq * SCL_Freq, 0.0); mFreqS ->SetName(_("LFO frequency in hertz")); mFreqS ->SetMinSize(wxSize(100, -1)); FloatingPointValidator<double> vldPhase(1, &mPhase); vldPhase.SetRange(MIN_Phase, MAX_Phase); - mPhaseT = S.Id(ID_Phase).AddTextBox(_("LFO Start Phase (deg.):"), wxT(""), 12); + mPhaseT = S.Id(ID_Phase).AddTextBox(_("LFO Start Phase (deg.):"), wxT(""), 15); mPhaseT->SetValidator(vldPhase); S.SetStyle(wxSL_HORIZONTAL); @@ -271,7 +272,7 @@ void EffectPhaser::PopulateOrExchange(ShuttleGui & S) IntegerValidator<int> vldDepth(&mDepth); vldDepth.SetRange(MIN_Depth, MAX_Depth); - mDepthT = S.Id(ID_Depth).AddTextBox(_("Depth:"), wxT(""), 12); + mDepthT = S.Id(ID_Depth).AddTextBox(_("Depth:"), wxT(""), 15); mDepthT->SetValidator(vldDepth); S.SetStyle(wxSL_HORIZONTAL); @@ -281,7 +282,7 @@ void EffectPhaser::PopulateOrExchange(ShuttleGui & S) IntegerValidator<int> vldFeedback(&mFeedback); vldFeedback.SetRange(MIN_Feedback, MAX_Feedback); - mFeedbackT = S.Id(ID_Feedback).AddTextBox(_("Feedback (%):"), wxT(""), 12); + mFeedbackT = S.Id(ID_Feedback).AddTextBox(_("Feedback (%):"), wxT(""), 15); mFeedbackT->SetValidator(vldFeedback); S.SetStyle(wxSL_HORIZONTAL); @@ -331,7 +332,6 @@ bool EffectPhaser::TransferDataFromWindow() void EffectPhaser::OnStagesSlider(wxCommandEvent & evt) { mStages = (evt.GetInt() / SCL_Stages) & ~1; // must be even; - mPhaseS->SetValue(mStages * SCL_Stages); mStagesT->GetValidator()->TransferToWindow(); EnableApply(mUIParent->Validate()); } @@ -346,6 +346,7 @@ void EffectPhaser::OnDryWetSlider(wxCommandEvent & evt) void EffectPhaser::OnFreqSlider(wxCommandEvent & evt) { mFreq = (double) evt.GetInt() / SCL_Freq; + if (mFreq < MIN_Freq) mFreq = MIN_Freq; mFreqT->GetValidator()->TransferToWindow(); EnableApply(mUIParent->Validate()); } diff --git a/src/effects/Reverse.cpp b/src/effects/Reverse.cpp index e55c6e309a0c3fbad844db9f857732b356aad069..8ec87a89a72d38ef4bc850b476d9029be7308182 100644 --- a/src/effects/Reverse.cpp +++ b/src/effects/Reverse.cpp @@ -15,14 +15,14 @@ #include "../Audacity.h" +#include "Reverse.h" #include <math.h> #include <wx/intl.h> #include "../LabelTrack.h" - -#include "Reverse.h" +#include "../WaveTrack.h" // // EffectReverse diff --git a/src/effects/Reverse.h b/src/effects/Reverse.h index d01816ab77064a289d819855cfb49c857dffe6ba..1080f76c78eec4684b61e55d01ced0ac0340ad7b 100644 --- a/src/effects/Reverse.h +++ b/src/effects/Reverse.h @@ -15,8 +15,6 @@ #include <wx/string.h> -#include "../WaveTrack.h" - #include "Effect.h" #define REVERSE_PLUGIN_SYMBOL XO("Reverse") diff --git a/src/effects/ScienFilter.cpp b/src/effects/ScienFilter.cpp index 838e8273e9fe5916dca3d056dbd14fbefcf4c21f..7dee7f0e142f30bf1bcd9ca56bec975aafdfb28b 100644 --- a/src/effects/ScienFilter.cpp +++ b/src/effects/ScienFilter.cpp @@ -725,7 +725,7 @@ bool EffectScienFilter::CalcFilter() } if ((mOrder & 1) == 0) { - float fTemp = pow (10.0, -wxMax(0.001, mRipple) / 20.0); // at DC the response is down R dB (for even-order) + float fTemp = DB_TO_LINEAR(-wxMax(0.001, mRipple)); // at DC the response is down R dB (for even-order) mpBiquad[0].fNumerCoeffs [0] *= fTemp; mpBiquad[0].fNumerCoeffs [1] *= fTemp; mpBiquad[0].fNumerCoeffs [2] *= fTemp; @@ -761,7 +761,7 @@ bool EffectScienFilter::CalcFilter() case kChebyshevTypeII: // Chebyshev Type 2 float fSZeroX, fSZeroY; float fSPoleX, fSPoleY; - eps = pow (10.0, -wxMax(0.001, mStopbandRipple) / 20.0); + eps = DB_TO_LINEAR(-wxMax(0.001, mStopbandRipple)); a = log (1 / eps + sqrt(1 / square(eps) + 1)) / mOrder; // Assume even order @@ -1131,7 +1131,7 @@ void EffectScienFilterPanel::OnPaint(wxPaintEvent & WXUNUSED(evt)) x = mEnvRect.x + i; freq = pow(10.0, loLog + i * step); //Hz yF = mEffect->FilterMagnAtFreq (freq); - yF = 20.0 * log10(yF); + yF = LINEAR_TO_DB(yF); if (yF < mDbMin) { diff --git a/src/effects/Silence.cpp b/src/effects/Silence.cpp index 39b30d0d7b3092b311d39a1fdcb443e7427a5cc7..2894ef1e71ad7db73cde5255d9e4c37936786b36 100644 --- a/src/effects/Silence.cpp +++ b/src/effects/Silence.cpp @@ -19,6 +19,7 @@ #include <wx/intl.h> #include "../ShuttleGui.h" +#include "../WaveTrack.h" EffectSilence::EffectSilence() { diff --git a/src/effects/Silence.h b/src/effects/Silence.h index 25be9f049174ea7e44f16a316913c01d29ef4158..f956472577c88be438a3f5726efdd9a45d475ea5 100644 --- a/src/effects/Silence.h +++ b/src/effects/Silence.h @@ -15,7 +15,6 @@ #include <wx/string.h> -#include "../WaveTrack.h" #include "../widgets/NumericTextCtrl.h" #include "Generator.h" diff --git a/src/effects/StereoToMono.cpp b/src/effects/StereoToMono.cpp index d45c85e9a2d1a933f9aabeaefd283edeebd9e880..bfdcf5a654fb6510a1fe048233b6b431c87d1f42 100644 --- a/src/effects/StereoToMono.cpp +++ b/src/effects/StereoToMono.cpp @@ -14,12 +14,12 @@ *//*******************************************************************/ #include "../Audacity.h" +#include "StereoToMono.h" #include <wx/intl.h> #include "../Project.h" - -#include "StereoToMono.h" +#include "../WaveTrack.h" EffectStereoToMono::EffectStereoToMono() { diff --git a/src/effects/TwoPassSimpleMono.cpp b/src/effects/TwoPassSimpleMono.cpp index 57fe0bfb83f9ebf5447ce2ad585e1123b1cc119e..d1dbefd6e89e8cbe0958489903708293cbb99a2f 100644 --- a/src/effects/TwoPassSimpleMono.cpp +++ b/src/effects/TwoPassSimpleMono.cpp @@ -22,6 +22,8 @@ doing the second pass over all selected tracks. #include "TwoPassSimpleMono.h" +#include "../WaveTrack.h" + bool EffectTwoPassSimpleMono::Process() { mPass = 0; diff --git a/src/effects/Wahwah.cpp b/src/effects/Wahwah.cpp index a14213c32f712e124ac84937d1e45af46b77a532..7cf5510933c9a1c62ba4a6c1353e9fbcd91dda77 100644 --- a/src/effects/Wahwah.cpp +++ b/src/effects/Wahwah.cpp @@ -217,7 +217,7 @@ void EffectWahwah::PopulateOrExchange(ShuttleGui & S) { S.SetStretchyCol(2); - FloatingPointValidator<double> vldfreq(1, &mFreq); + FloatingPointValidator<double> vldfreq(5, &mFreq, NUM_VAL_ONE_TRAILING_ZERO); vldfreq.SetRange(MIN_Freq, MAX_Freq); mFreqT = S.Id(ID_Freq).AddTextBox(_("LFO Frequency (Hz):"), wxT(""), 12); mFreqT->SetValidator(vldfreq); diff --git a/src/effects/nyquist/Nyquist.cpp b/src/effects/nyquist/Nyquist.cpp index 244067e6fb2d631d0661e6c7f95c41a4450c2f83..580d0d1788678befbb2f2cf78c26091567112b33 100644 --- a/src/effects/nyquist/Nyquist.cpp +++ b/src/effects/nyquist/Nyquist.cpp @@ -45,6 +45,7 @@ effects from this one class. #include "../../FileNames.h" #include "../../Internat.h" #include "../../LabelTrack.h" +#include "../../prefs/SpectrogramSettings.h" #include "../../Project.h" #include "../../ShuttleGui.h" #include "../../WaveClip.h" @@ -539,34 +540,6 @@ bool NyquistEffect::Process() Internat::ToString(mT1).c_str()); mProps += wxString::Format(wxT("(putprop '*SELECTION* (list %s) 'TRACKS)\n"), waveTrackList.c_str()); mProps += wxString::Format(wxT("(putprop '*SELECTION* %d 'CHANNELS)\n"), numChannels); - - wxString lowHz = wxT("nil"); - wxString highHz = wxT("nil"); - wxString centerHz = wxT("nil"); - wxString bandwidth = wxT("nil"); - -#if defined(EXPERIMENTAL_SPECTRAL_EDITING) - if (mF0 >= 0.0) { - lowHz.Printf(wxT("(float %s)"), Internat::ToString(mF0).c_str()); - } - - if (mF1 >= 0.0) { - highHz.Printf(wxT("(float %s)"), Internat::ToString(mF1).c_str()); - } - - if ((mF0 >= 0.0) && (mF1 >= 0.0)) { - centerHz.Printf(wxT("(float %s)"), Internat::ToString(sqrt(mF0 * mF1)).c_str()); - } - - if ((mF0 > 0.0) && (mF1 >= mF0)) { - bandwidth.Printf(wxT("(float %s)"), Internat::ToString(log(mF1 / mF0)/log(2.0)).c_str()); - } - -#endif - mProps += wxString::Format(wxT("(putprop '*SELECTION* %s 'LOW-HZ)\n"), lowHz.c_str()); - mProps += wxString::Format(wxT("(putprop '*SELECTION* %s 'CENTER-HZ)\n"), centerHz.c_str()); - mProps += wxString::Format(wxT("(putprop '*SELECTION* %s 'HIGH-HZ)\n"), highHz.c_str()); - mProps += wxString::Format(wxT("(putprop '*SELECTION* %s 'BANDWIDTH)\n"), bandwidth.c_str()); } // Keep track of whether the current track is first selected in its sync-lock group @@ -621,6 +594,45 @@ bool NyquistEffect::Process() nyx_set_os_callback(StaticOSCallback, (void *)this); nyx_capture_output(StaticOutputCallback, (void *)this); + if (mVersion >= 4) + { + mPerTrackProps = wxEmptyString; + wxString lowHz = wxT("nil"); + wxString highHz = wxT("nil"); + wxString centerHz = wxT("nil"); + wxString bandwidth = wxT("nil"); + + const WaveTrack::WaveTrackDisplay display = mCurTrack[0]->GetDisplay(); + const bool bAllowSpectralEditing = + (display == WaveTrack::Spectrum) && + mCurTrack[0]->GetSpectrogramSettings().SpectralSelectionEnabled(); + + if (bAllowSpectralEditing) { +#if defined(EXPERIMENTAL_SPECTRAL_EDITING) + if (mF0 >= 0.0) { + lowHz.Printf(wxT("(float %s)"), Internat::ToString(mF0).c_str()); + } + + if (mF1 >= 0.0) { + highHz.Printf(wxT("(float %s)"), Internat::ToString(mF1).c_str()); + } + + if ((mF0 >= 0.0) && (mF1 >= 0.0)) { + centerHz.Printf(wxT("(float %s)"), Internat::ToString(sqrt(mF0 * mF1)).c_str()); + } + + if ((mF0 > 0.0) && (mF1 >= mF0)) { + bandwidth.Printf(wxT("(float %s)"), Internat::ToString(log(mF1 / mF0) / log(2.0)).c_str()); + } + } + +#endif + mPerTrackProps += wxString::Format(wxT("(putprop '*SELECTION* %s 'LOW-HZ)\n"), lowHz.c_str()); + mPerTrackProps += wxString::Format(wxT("(putprop '*SELECTION* %s 'CENTER-HZ)\n"), centerHz.c_str()); + mPerTrackProps += wxString::Format(wxT("(putprop '*SELECTION* %s 'HIGH-HZ)\n"), highHz.c_str()); + mPerTrackProps += wxString::Format(wxT("(putprop '*SELECTION* %s 'BANDWIDTH)\n"), bandwidth.c_str()); + } + success = ProcessOne(); nyx_capture_output(NULL, (void *)NULL); @@ -765,6 +777,7 @@ bool NyquistEffect::ProcessOne() if (mVersion >= 4) { cmd += mProps; + cmd += mPerTrackProps; // Set the track TYPE and VIEW properties wxString type; @@ -776,13 +789,8 @@ bool NyquistEffect::ProcessOne() type = wxT("wave"); switch (((WaveTrack *) mCurTrack[0])->GetDisplay()) { - case WaveTrack::WaveformDisplay: view = wxT("\"Waveform\""); break; - case WaveTrack::WaveformDBDisplay: view = wxT("\"Waveform (dB)\""); break; - case WaveTrack::SpectrumDisplay: view = wxT("\"Spectrogram\""); break; - case WaveTrack::SpectrumLogDisplay: view = wxT("\"Spectrogram log(f)\""); break; - case WaveTrack::SpectralSelectionDisplay: view = wxT("\"Spectral Selection\""); break; - case WaveTrack::SpectralSelectionLogDisplay: view = wxT("\"Spectral Selection log(f)\""); break; - case WaveTrack::PitchDisplay: view = wxT("\"Pitch (EAC)\""); break; + case WaveTrack::Waveform: view = wxT("\"Waveform\""); break; + case WaveTrack::Spectrum: view = wxT("\"Spectrum\""); break; default: view = wxT("NIL"); break; } break; diff --git a/src/effects/nyquist/Nyquist.h b/src/effects/nyquist/Nyquist.h index 47b9e224654e3a3f790762330f6ae13a36a25c72..794275fefca4946ae24b2ecf5bb03d3df4e41339 100644 --- a/src/effects/nyquist/Nyquist.h +++ b/src/effects/nyquist/Nyquist.h @@ -223,6 +223,7 @@ private: wxArrayString mCategories; wxString mProps; + wxString mPerTrackProps; bool mRestoreSplits; int mMergeClips; diff --git a/src/effects/vamp/VampEffect.cpp b/src/effects/vamp/VampEffect.cpp index 058b1afcad26f2194ef4015d31bd7f6663d2546b..4f4e00fbccf4034912e0d6c94e25b1efffee5ab6 100644 --- a/src/effects/vamp/VampEffect.cpp +++ b/src/effects/vamp/VampEffect.cpp @@ -40,6 +40,9 @@ #include "../../ShuttleGui.h" #include "../../widgets/valnum.h" +#include "../../LabelTrack.h" +#include "../../WaveTrack.h" + enum { ID_Program = 10000, diff --git a/src/effects/vamp/VampEffect.h b/src/effects/vamp/VampEffect.h index 7e4d08d59218a8511d9af5f8bdd6e77c706bd4d1..1c660d09d542a0ff648954a7fcf190c33dbfbf11 100644 --- a/src/effects/vamp/VampEffect.h +++ b/src/effects/vamp/VampEffect.h @@ -25,10 +25,10 @@ #include <vamp-hostsdk/PluginLoader.h> -#include "../../LabelTrack.h" - #include "../Effect.h" +class LabelTrack; + #define VAMPEFFECTS_VERSION wxT("1.0.0.0") #define VAMPEFFECTS_FAMILY wxT("Vamp") diff --git a/src/export/Export.cpp b/src/export/Export.cpp index 283a084541a91d60ec0752223f68299091b0322a..b505852ffefd8c1a33367117dd181a866ece0afa 100644 --- a/src/export/Export.cpp +++ b/src/export/Export.cpp @@ -61,16 +61,13 @@ #include "../DirManager.h" #include "../FileFormats.h" #include "../Internat.h" -#include "../LabelTrack.h" #include "../Mix.h" #include "../Prefs.h" #include "../Project.h" #include "../ShuttleGui.h" -#include "../Track.h" #include "../WaveTrack.h" #include "../widgets/Warning.h" #include "../AColor.h" -#include "../TimeTrack.h" #include "../Dependencies.h" //---------------------------------------------------------------------------- diff --git a/src/export/ExportCL.cpp b/src/export/ExportCL.cpp index 2bab9da0d68e9cee599e983812a60886c709e096..1b250e4b61b936a1eb2a3239010ab9e5f2b0b65e 100644 --- a/src/export/ExportCL.cpp +++ b/src/export/ExportCL.cpp @@ -18,7 +18,7 @@ #include <wx/button.h> #include <wx/combobox.h> #include <wx/log.h> -#include <wx/panel.h> +#include <wx/msgdlg.h> #include <wx/process.h> #include <wx/sizer.h> #include <wx/textctrl.h> @@ -32,6 +32,8 @@ #include "../float_cast.h" #include "../widgets/FileHistory.h" +#include "../Track.h" + //---------------------------------------------------------------------------- // ExportCLOptions diff --git a/src/export/ExportFFmpeg.cpp b/src/export/ExportFFmpeg.cpp index 951b57c6d4e83db6514ecb7582a4ca447a6f2424..fb437eafdeb36a4d907de444988c002343fbb6a0 100644 --- a/src/export/ExportFFmpeg.cpp +++ b/src/export/ExportFFmpeg.cpp @@ -36,13 +36,11 @@ function. #include "../FileFormats.h" #include "../Internat.h" -#include "../LabelTrack.h" #include "../Mix.h" #include "../Prefs.h" #include "../Project.h" #include "../Tags.h" #include "../Track.h" -#include "../WaveTrack.h" #include "Export.h" #include "ExportFFmpeg.h" diff --git a/src/export/ExportFFmpegDialogs.cpp b/src/export/ExportFFmpegDialogs.cpp index e8fce8360202966fb9589f8af8d4983c8b2dc88e..1782c62686c29741f477efed2210abedc93e196d 100644 --- a/src/export/ExportFFmpegDialogs.cpp +++ b/src/export/ExportFFmpegDialogs.cpp @@ -56,13 +56,10 @@ #include "../FileFormats.h" #include "../Internat.h" -#include "../LabelTrack.h" #include "../Mix.h" #include "../Prefs.h" #include "../Project.h" #include "../Tags.h" -#include "../Track.h" -#include "../WaveTrack.h" #include "Export.h" diff --git a/src/export/ExportFLAC.cpp b/src/export/ExportFLAC.cpp index a025ba1451c45f046431ecaad358af2da3a1d732..b0972a543bd117113b15fddc8aedbd2534943755 100644 --- a/src/export/ExportFLAC.cpp +++ b/src/export/ExportFLAC.cpp @@ -41,6 +41,8 @@ and libvorbis examples, Monty <monty@xiph.org> #include "../Internat.h" #include "../Tags.h" +#include "../Track.h" + //---------------------------------------------------------------------------- // ExportFLACOptions Class //---------------------------------------------------------------------------- diff --git a/src/export/ExportMP2.cpp b/src/export/ExportMP2.cpp index cac351702d74c1463ccc27d8117a1525f574e09d..bd1b4f191cd335b1ce9c01066f43786173de8828 100644 --- a/src/export/ExportMP2.cpp +++ b/src/export/ExportMP2.cpp @@ -55,7 +55,7 @@ #include "../Project.h" #include "../ShuttleGui.h" #include "../Tags.h" -#include "../WaveTrack.h" +#include "../Track.h" #define LIBTWOLAME_STATIC #include "twolame.h" diff --git a/src/export/ExportMP3.cpp b/src/export/ExportMP3.cpp index 001d78acfac6bd22c97f2eba14e6499ad4af5ad0..d1185e20d84a523e1de5e30f2cfd26efd84a3e35 100644 --- a/src/export/ExportMP3.cpp +++ b/src/export/ExportMP3.cpp @@ -86,7 +86,7 @@ #include "../Project.h" #include "../ShuttleGui.h" #include "../Tags.h" -#include "../WaveTrack.h" +#include "../Track.h" #include "../widgets/LinkingHtmlWindow.h" #include "FileDialog.h" diff --git a/src/export/ExportMultiple.cpp b/src/export/ExportMultiple.cpp index deeb7f30c64e60f5c780c2d3666c7fcd10291803..20f938c3b60da41a514b9b45946ea9a3a86ed95d 100644 --- a/src/export/ExportMultiple.cpp +++ b/src/export/ExportMultiple.cpp @@ -48,6 +48,7 @@ #include "../Prefs.h" #include "../ShuttleGui.h" #include "../Tags.h" +#include "../WaveTrack.h" #include "../widgets/HelpSystem.h" @@ -104,6 +105,7 @@ END_EVENT_TABLE() ExportMultiple::ExportMultiple(AudacityProject *project) : wxDialog(project, wxID_ANY, wxString(_("Export Multiple"))) +, mIterator(new TrackListIterator) { SetName(GetTitle()); @@ -137,6 +139,7 @@ ExportMultiple::ExportMultiple(AudacityProject *project) ExportMultiple::~ExportMultiple() { + delete mIterator; } void ExportMultiple::CountTracksAndLabels() @@ -146,7 +149,7 @@ void ExportMultiple::CountTracksAndLabels() mNumWaveTracks = 0; Track* pTrack; - for (pTrack = mIterator.First(mTracks); pTrack != NULL; pTrack = mIterator.Next()) + for (pTrack = mIterator->First(mTracks); pTrack != NULL; pTrack = mIterator->Next()) { switch (pTrack->GetKind()) { @@ -731,7 +734,7 @@ int ExportMultiple::ExportMultipleByTrack(bool byName, wxString title; // un-messed-with title of file for tagging with /* Remember which tracks were selected, and set them to unselected */ - for (tr = mIterator.First(mTracks); tr != NULL; tr = mIterator.Next()) { + for (tr = mIterator->First(mTracks); tr != NULL; tr = mIterator->Next()) { if (tr->GetKind() != Track::Wave) { continue; } @@ -747,7 +750,7 @@ int ExportMultiple::ExportMultipleByTrack(bool byName, } /* Examine all tracks in turn, collecting export information */ - for (tr = mIterator.First(mTracks); tr != NULL; tr = mIterator.Next()) { + for (tr = mIterator->First(mTracks); tr != NULL; tr = mIterator->Next()) { // Want only non-muted wave tracks. if ((tr->GetKind() != Track::Wave) || tr->GetMute()) @@ -760,7 +763,7 @@ int ExportMultiple::ExportMultipleByTrack(bool byName, // Check for a linked track tr2 = NULL; if (tr->GetLinked()) { - tr2 = mIterator.Next(); + tr2 = mIterator->Next(); if (tr2) { // Make sure it gets included @@ -830,7 +833,7 @@ int ExportMultiple::ExportMultipleByTrack(bool byName, // loop int count = 0; // count the number of sucessful runs ExportKit activeSetting; // pointer to the settings in use for this export - for (tr = mIterator.First(mTracks); tr != NULL; tr = mIterator.Next()) { + for (tr = mIterator->First(mTracks); tr != NULL; tr = mIterator->Next()) { // Want only non-muted wave tracks. if ((tr->GetKind() != Track::Wave) || (tr->GetMute() == true)) { @@ -843,7 +846,7 @@ int ExportMultiple::ExportMultipleByTrack(bool byName, // Check for a linked track tr2 = NULL; if (tr->GetLinked()) { - tr2 = mIterator.Next(); + tr2 = mIterator->Next(); if (tr2) { // Select it also tr2->SetSelected(true); diff --git a/src/export/ExportMultiple.h b/src/export/ExportMultiple.h index a1cc8324a8bb0fa20641176bc73facfb930893c6..06304cb86dc22e747035669fe274a75c21261f28 100644 --- a/src/export/ExportMultiple.h +++ b/src/export/ExportMultiple.h @@ -17,7 +17,6 @@ #include <wx/listctrl.h> #include "Export.h" -#include "../Track.h" #include "../Tags.h" // we need to know about the Tags class for metadata class wxButton; @@ -27,7 +26,9 @@ class wxRadioButton; class wxTextCtrl; class AudacityProject; +class LabelTrack; class ShuttleGui; +class TrackListIterator; class ExportMultiple : public wxDialog { @@ -107,7 +108,7 @@ private: AudacityProject *mProject; TrackList *mTracks; /**< The list of tracks in the project that is being exported */ - TrackListIterator mIterator; /**< Iterator used to work through all the + TrackListIterator *mIterator; /**< Iterator used to work through all the tracks in the project */ LabelTrack *mLabels; int mNumLabels; diff --git a/src/export/ExportOGG.cpp b/src/export/ExportOGG.cpp index 19f73c8250049713ba83675e8c48fb650acfc060..5fb62c17ef0694063723b0e612372bcd91c5ad1f 100644 --- a/src/export/ExportOGG.cpp +++ b/src/export/ExportOGG.cpp @@ -36,6 +36,7 @@ #include "../Internat.h" #include "../Tags.h" +#include "../Track.h" //---------------------------------------------------------------------------- // ExportOGGOptions diff --git a/src/export/ExportPCM.cpp b/src/export/ExportPCM.cpp index 27c5002f6d441e524b75dce66b0ad1f88794040d..cee02cb22552ec842dcba8b51093f523fd640855 100644 --- a/src/export/ExportPCM.cpp +++ b/src/export/ExportPCM.cpp @@ -28,14 +28,12 @@ #include "../FileFormats.h" #include "../Internat.h" -#include "../LabelTrack.h" #include "../Mix.h" #include "../Prefs.h" #include "../Project.h" #include "../ShuttleGui.h" #include "../Tags.h" #include "../Track.h" -#include "../WaveTrack.h" #include "../ondemand/ODManager.h" #include "Export.h" diff --git a/src/import/Import.cpp b/src/import/Import.cpp index eff3e380afe0476c1de8f0418f695581568e95ea..b211bf6f836dd256c47c8fa1d3bac248988753f3 100644 --- a/src/import/Import.cpp +++ b/src/import/Import.cpp @@ -58,7 +58,6 @@ and ImportLOF.cpp. #include "ImportFLAC.h" #include "ImportFFmpeg.h" #include "ImportGStreamer.h" -#include "../Track.h" #include "../Prefs.h" WX_DEFINE_LIST(ImportPluginList); diff --git a/src/import/ImportLOF.cpp b/src/import/ImportLOF.cpp index fb1d0ad1cd43fc5688bc30aee087cfae67a99830..31058691fb976a7e6081e4f5dba549c10f32ebc1 100644 --- a/src/import/ImportLOF.cpp +++ b/src/import/ImportLOF.cpp @@ -90,7 +90,6 @@ #include "../Project.h" #include "../FileFormats.h" #include "../Prefs.h" -#include "../WaveTrack.h" #include "../Internat.h" #define BINARY_FILE_CHECK_BUFFER_SIZE 1024 diff --git a/src/ondemand/ODComputeSummaryTask.cpp b/src/ondemand/ODComputeSummaryTask.cpp index 9885d0ec2cce937eea86c9e6cff5f78fe445e512..7bc0ca0c0d87ba971cef2b3436b63ddfdb6c66e5 100644 --- a/src/ondemand/ODComputeSummaryTask.cpp +++ b/src/ondemand/ODComputeSummaryTask.cpp @@ -20,6 +20,8 @@ updating the ODPCMAliasBlockFile and the GUI of the newly available data. #include "ODComputeSummaryTask.h" #include "../blockfile/ODPCMAliasBlockFile.h" +#include "../Sequence.h" +#include "../WaveTrack.h" #include <wx/wx.h> //36 blockfiles > 3 minutes stereo 44.1kHz per ODTask::DoSome diff --git a/src/ondemand/ODDecodeTask.cpp b/src/ondemand/ODDecodeTask.cpp index 3761d4ebfc33b26ec3b1691468a68141499e46d3..bd4f483aeacae29cf1818eb5d55894c8487d8c97 100644 --- a/src/ondemand/ODDecodeTask.cpp +++ b/src/ondemand/ODDecodeTask.cpp @@ -18,6 +18,8 @@ updating the ODPCMAliasBlockFile and the GUI of the newly available data. #include "ODDecodeTask.h" #include "../blockfile/ODDecodeBlockFile.h" +#include "../Sequence.h" +#include "../WaveTrack.h" #include <wx/wx.h> ///Creates a new task that computes summaries for a wavetrack that needs to be specified through SetWaveTrack() diff --git a/src/ondemand/ODManager.cpp b/src/ondemand/ODManager.cpp index c14a293ec31b16d180cd8c05ca0a922ea5733034..8acc72e7f712ca904b3e528b9d75945a3f886b6a 100644 --- a/src/ondemand/ODManager.cpp +++ b/src/ondemand/ODManager.cpp @@ -541,12 +541,12 @@ bool ODManager::HasLoadedODFlag() } ///fills in the status bar message for a given track -void ODManager::FillTipForWaveTrack( WaveTrack * t, const wxChar ** ppTip ) +void ODManager::FillTipForWaveTrack( WaveTrack * t, wxString &tip ) { mQueuesMutex.Lock(); for(unsigned int i=0;i<mQueues.size();i++) { - mQueues[i]->FillTipForWaveTrack(t,ppTip); + mQueues[i]->FillTipForWaveTrack(t, tip); } mQueuesMutex.Unlock(); } diff --git a/src/ondemand/ODManager.h b/src/ondemand/ODManager.h index 1b23672a8b221c989f09cc4e8165b58fa9b770e8..2a255298c7dbd2a33515c7273bf544ebc2e10ce3 100644 --- a/src/ondemand/ODManager.h +++ b/src/ondemand/ODManager.h @@ -98,7 +98,7 @@ class ODManager static bool IsInstanceCreated(); ///fills in the status bar message for a given track - void FillTipForWaveTrack( WaveTrack * t, const wxChar ** ppTip ); + void FillTipForWaveTrack( WaveTrack * t, wxString &tip ); ///Gets the total percent complete for all tasks combined. float GetOverallPercentComplete(); diff --git a/src/ondemand/ODWaveTrackTaskQueue.cpp b/src/ondemand/ODWaveTrackTaskQueue.cpp index e6152cf6c8267461f238a701fd5e34db3c5ffbcb..ee4fe629ee4b82118ee807927d2b94d13e611b24 100644 --- a/src/ondemand/ODWaveTrackTaskQueue.cpp +++ b/src/ondemand/ODWaveTrackTaskQueue.cpp @@ -325,7 +325,7 @@ ODTask* ODWaveTrackTaskQueue::GetFrontTask() } ///fills in the status bar message for a given track -void ODWaveTrackTaskQueue::FillTipForWaveTrack( WaveTrack * t, const wxChar ** ppTip ) +void ODWaveTrackTaskQueue::FillTipForWaveTrack( WaveTrack * t, wxString &tip ) { if(ContainsWaveTrack(t) && GetNumTasks()) { @@ -335,7 +335,7 @@ void ODWaveTrackTaskQueue::FillTipForWaveTrack( WaveTrack * t, const wxChar ** p // else // msg.Printf(_("%s %d additional tasks remaining."), GetFrontTask()->GetTip().c_str(), GetNumTasks()); - *ppTip = mTipMsg.c_str(); + tip = mTipMsg.c_str(); } } diff --git a/src/ondemand/ODWaveTrackTaskQueue.h b/src/ondemand/ODWaveTrackTaskQueue.h index 67821513011b7828c0956209757addbc39c419f7..5b05e5571090252a4f04e89a5831c9f5e24dfa38 100644 --- a/src/ondemand/ODWaveTrackTaskQueue.h +++ b/src/ondemand/ODWaveTrackTaskQueue.h @@ -92,7 +92,7 @@ class ODWaveTrackTaskQueue ODTask* GetTask(size_t x); ///fills in the status bar message for a given track - void FillTipForWaveTrack( WaveTrack * t, const wxChar ** ppTip ); + void FillTipForWaveTrack( WaveTrack * t, wxString &tip ); protected: diff --git a/src/prefs/BatchPrefs.cpp b/src/prefs/BatchPrefs.cpp index 8f7664d2c3d3e7827243703c75f8e754336ebc9a..58454628c32aae20f02da7f152415dee80f39f27 100644 --- a/src/prefs/BatchPrefs.cpp +++ b/src/prefs/BatchPrefs.cpp @@ -21,7 +21,6 @@ #include <wx/textdlg.h> #include "BatchPrefs.h" -#include "../Envelope.h" #include "../Languages.h" #include "../Prefs.h" #include "../Project.h" @@ -82,3 +81,8 @@ bool BatchPrefs::Apply() BatchPrefs::~BatchPrefs() { } + +PrefsPanel *BatchPrefsFactory::Create(wxWindow *parent) +{ + return new BatchPrefs(parent); +} diff --git a/src/prefs/BatchPrefs.h b/src/prefs/BatchPrefs.h index 427e7233c0cfb36a1ed13c3cc544513af7130844..98210b97373283c7b9ccfa601ced39e4b3940f85 100644 --- a/src/prefs/BatchPrefs.h +++ b/src/prefs/BatchPrefs.h @@ -34,4 +34,9 @@ private: DECLARE_EVENT_TABLE(); }; +class BatchPrefsFactory : public PrefsPanelFactory +{ +public: + virtual PrefsPanel *Create(wxWindow *parent); +}; #endif diff --git a/src/prefs/DevicePrefs.cpp b/src/prefs/DevicePrefs.cpp index 24e5fa5021eb1c7be35c344165739e86c4772538..c0663c84c4d09c7144038f780c904873fcf7059a 100644 --- a/src/prefs/DevicePrefs.cpp +++ b/src/prefs/DevicePrefs.cpp @@ -373,3 +373,8 @@ bool DevicePrefs::Apply() return true; } + +PrefsPanel *DevicePrefsFactory::Create(wxWindow *parent) +{ + return new DevicePrefs(parent); +} diff --git a/src/prefs/DevicePrefs.h b/src/prefs/DevicePrefs.h index 67d3bef24324e30e8c77b8805ea05b4956c59fcd..bb3bc7b6534f613d8db6c3394f91887ee52b10d2 100644 --- a/src/prefs/DevicePrefs.h +++ b/src/prefs/DevicePrefs.h @@ -54,4 +54,10 @@ class DevicePrefs :public PrefsPanel DECLARE_EVENT_TABLE(); }; +class DevicePrefsFactory : public PrefsPanelFactory +{ +public: + virtual PrefsPanel *Create(wxWindow *parent); +}; + #endif diff --git a/src/prefs/DirectoriesPrefs.cpp b/src/prefs/DirectoriesPrefs.cpp index 606e3891b4eddb17ddc5eb29b2e5b3fdb0312e28..1a48313ff1a4e82f30e45fe861bb2d8dbca8ecb3 100644 --- a/src/prefs/DirectoriesPrefs.cpp +++ b/src/prefs/DirectoriesPrefs.cpp @@ -242,3 +242,8 @@ bool DirectoriesPrefs::Apply() return true; } + +PrefsPanel *DirectoriesPrefsFactory::Create(wxWindow *parent) +{ + return new DirectoriesPrefs(parent); +} diff --git a/src/prefs/DirectoriesPrefs.h b/src/prefs/DirectoriesPrefs.h index 40407185764637f8d7c6a16943d9656cd22d21d8..423fd005d657c5ba7f39ae47e27f746cb34b2821 100644 --- a/src/prefs/DirectoriesPrefs.h +++ b/src/prefs/DirectoriesPrefs.h @@ -38,4 +38,9 @@ class DirectoriesPrefs :public PrefsPanel DECLARE_EVENT_TABLE(); }; +class DirectoriesPrefsFactory : public PrefsPanelFactory +{ +public: + virtual PrefsPanel *Create(wxWindow *parent); +}; #endif diff --git a/src/prefs/EffectsPrefs.cpp b/src/prefs/EffectsPrefs.cpp index cf5ae326ee71d36e448241b8c9f4d69f68d2ec91..e8a36f1f8536cfabcda3a5db9874fb48b9178d03 100644 --- a/src/prefs/EffectsPrefs.cpp +++ b/src/prefs/EffectsPrefs.cpp @@ -165,3 +165,8 @@ bool EffectsPrefs::Apply() return true; } + +PrefsPanel *EffectsPrefsFactory::Create(wxWindow *parent) +{ + return new EffectsPrefs(parent); +} diff --git a/src/prefs/EffectsPrefs.h b/src/prefs/EffectsPrefs.h index 0d096c042747e8ebf6f13dca69e23ebe94ef62ea..484913352b987c3a006d9c3cd595005ca819f906 100644 --- a/src/prefs/EffectsPrefs.h +++ b/src/prefs/EffectsPrefs.h @@ -34,4 +34,9 @@ class EffectsPrefs :public PrefsPanel void PopulateOrExchange(ShuttleGui & S); }; +class EffectsPrefsFactory : public PrefsPanelFactory +{ +public: + virtual PrefsPanel *Create(wxWindow *parent); +}; #endif diff --git a/src/prefs/ExtImportPrefs.cpp b/src/prefs/ExtImportPrefs.cpp index 9e6550cb7399d558879ed7a3ef816a0a1dbbf0bf..26c1b6593b529f1114edf9838015f5d3b570ed2b 100644 --- a/src/prefs/ExtImportPrefs.cpp +++ b/src/prefs/ExtImportPrefs.cpp @@ -780,3 +780,8 @@ void ExtImportPrefsDropTarget::SetDataObject(wxDataObject* data) { this->m_dataObject = data; } + +PrefsPanel *ExtImportPrefsFactory::Create(wxWindow *parent) +{ + return new ExtImportPrefs(parent); +} diff --git a/src/prefs/ExtImportPrefs.h b/src/prefs/ExtImportPrefs.h index d97f29b697decc1f7aa0d8d81c8657b7058ecbe2..38670d8e315d1fcce7899efdcc3d7ad97428d331 100644 --- a/src/prefs/ExtImportPrefs.h +++ b/src/prefs/ExtImportPrefs.h @@ -107,4 +107,10 @@ class ExtImportPrefs:public PrefsPanel DECLARE_EVENT_TABLE() }; + +class ExtImportPrefsFactory : public PrefsPanelFactory +{ +public: + virtual PrefsPanel *Create(wxWindow *parent); +}; #endif diff --git a/src/prefs/GUIPrefs.cpp b/src/prefs/GUIPrefs.cpp index c6fc5aa04aeac61fab2b4d3b2cdce690280248c7..8c148a2d058db4872b73e8a327df64158a42069c 100644 --- a/src/prefs/GUIPrefs.cpp +++ b/src/prefs/GUIPrefs.cpp @@ -18,6 +18,7 @@ *//*******************************************************************/ #include "../Audacity.h" +#include "GUIPrefs.h" #include <wx/defs.h> @@ -26,7 +27,7 @@ #include "../Prefs.h" #include "../ShuttleGui.h" -#include "GUIPrefs.h" +#include "GUISettings.h" GUIPrefs::GUIPrefs(wxWindow * parent) : PrefsPanel(parent, _("Interface")) @@ -99,9 +100,10 @@ void GUIPrefs::PopulateOrExchange(ShuttleGui & S) S.StartMultiColumn(2); { + const wxString defaultRange = wxString::Format(wxT("%d"), ENV_DB_RANGE); S.TieChoice(_("Meter/Waveform dB &range:"), - wxT("/GUI/EnvdBRange"), - wxT("60"), + ENV_DB_KEY, + defaultRange, mRangeChoices, mRangeCodes); S.SetSizeHints(mRangeChoices); @@ -158,3 +160,8 @@ bool GUIPrefs::Apply() return true; } + +PrefsPanel *GUIPrefsFactory::Create(wxWindow *parent) +{ + return new GUIPrefs(parent); +} diff --git a/src/prefs/GUIPrefs.h b/src/prefs/GUIPrefs.h index e3af2b7f31467c70c7aa1fa3038c82e05fd883c1..7f114f53a9310b747b2db66200137d5b3ac66a12 100644 --- a/src/prefs/GUIPrefs.h +++ b/src/prefs/GUIPrefs.h @@ -43,4 +43,9 @@ class GUIPrefs :public PrefsPanel wxArrayString mRangeChoices; }; +class GUIPrefsFactory : public PrefsPanelFactory +{ +public: + virtual PrefsPanel *Create(wxWindow *parent); +}; #endif diff --git a/src/prefs/GUISettings.h b/src/prefs/GUISettings.h new file mode 100644 index 0000000000000000000000000000000000000000..df0ad6a5b13132fedf0bacc9b0138b0ff40269a7 --- /dev/null +++ b/src/prefs/GUISettings.h @@ -0,0 +1,18 @@ +/********************************************************************** + +Audacity: A Digital Audio Editor + +GUIPrefs.h + +Paul Licameli + Moved a constant here from Envelope.h where it did not belong + Define the key string in one place here too + +**********************************************************************/ +#ifndef __AUDACITY_GUI_SETTINGS__ +#define __AUDACITY_GUI_SETTINGS__ + +#define ENV_DB_KEY (wxT("/GUI/EnvdBRange")) +#define ENV_DB_RANGE 60 + +#endif diff --git a/src/prefs/ImportExportPrefs.cpp b/src/prefs/ImportExportPrefs.cpp index f6e9538f269df2bf5e7c2bd91d1f5676bcdb2494..609689cc90c93c8ed3e423efb9863fa147d97731 100644 --- a/src/prefs/ImportExportPrefs.cpp +++ b/src/prefs/ImportExportPrefs.cpp @@ -109,3 +109,8 @@ bool ImportExportPrefs::Apply() return true; } + +PrefsPanel *ImportExportPrefsFactory::Create(wxWindow *parent) +{ + return new ImportExportPrefs(parent); +} diff --git a/src/prefs/ImportExportPrefs.h b/src/prefs/ImportExportPrefs.h index 9ba891ea7df145b5334256d3a6a5d73b0647c4be..9ffe0354190c5309a46f8f0ff00d18ef6de9f56f 100644 --- a/src/prefs/ImportExportPrefs.h +++ b/src/prefs/ImportExportPrefs.h @@ -33,4 +33,9 @@ class ImportExportPrefs :public PrefsPanel void PopulateOrExchange(ShuttleGui & S); }; +class ImportExportPrefsFactory : public PrefsPanelFactory +{ +public: + virtual PrefsPanel *Create(wxWindow *parent); +}; #endif diff --git a/src/prefs/KeyConfigPrefs.cpp b/src/prefs/KeyConfigPrefs.cpp index 103795f04140ed01b98dc89e489941fc9e256911..5c1ed5d4e951005313b706409fe1c91155ebe60a 100644 --- a/src/prefs/KeyConfigPrefs.cpp +++ b/src/prefs/KeyConfigPrefs.cpp @@ -20,12 +20,15 @@ KeyConfigPrefs and MousePrefs use. *//*********************************************************************/ #include "../Audacity.h" +#include "../Experimental.h" +#include "KeyConfigPrefs.h" #include <wx/defs.h> #include <wx/ffile.h> #include <wx/intl.h> #include <wx/filedlg.h> #include <wx/button.h> +#include <wx/msgdlg.h> #include "../Prefs.h" #include "../Project.h" @@ -35,7 +38,6 @@ KeyConfigPrefs and MousePrefs use. #include "../Internat.h" #include "../ShuttleGui.h" -#include "KeyConfigPrefs.h" #include "FileDialog.h" @@ -1211,3 +1213,8 @@ void KeyConfigPrefs::Cancel() } #endif + +PrefsPanel *KeyConfigPrefsFactory::Create(wxWindow *parent) +{ + return new KeyConfigPrefs(parent); +} diff --git a/src/prefs/KeyConfigPrefs.h b/src/prefs/KeyConfigPrefs.h index 36f869ec46219e0e30ed00f2372c7b8e5ece75bf..07bbd0b1d24c7776dadb0bcd4bbff5e74616ae3d 100644 --- a/src/prefs/KeyConfigPrefs.h +++ b/src/prefs/KeyConfigPrefs.h @@ -30,6 +30,8 @@ class ShuttleGui; #include "PrefsPanel.h" +class wxStaticText; + class KeyConfigPrefs :public PrefsPanel { public: @@ -141,6 +143,12 @@ class KeyConfigPrefs:public PrefsPanel DECLARE_EVENT_TABLE(); }; + #endif +class KeyConfigPrefsFactory : public PrefsPanelFactory +{ +public: + virtual PrefsPanel *Create(wxWindow *parent); +}; #endif diff --git a/src/prefs/LibraryPrefs.cpp b/src/prefs/LibraryPrefs.cpp index 6c019f9afcfc3e7980a859e3bd34540c765110bc..ee3e90126c75612254010863e6a7da53bf405ff8 100644 --- a/src/prefs/LibraryPrefs.cpp +++ b/src/prefs/LibraryPrefs.cpp @@ -236,3 +236,8 @@ bool LibraryPrefs::Apply() return true; } + +PrefsPanel *LibraryPrefsFactory::Create(wxWindow *parent) +{ + return new LibraryPrefs(parent); +} diff --git a/src/prefs/LibraryPrefs.h b/src/prefs/LibraryPrefs.h index 15e54a98fd2e196c497eb2019793f83077dc109f..f3a35417d9032b78d42e3d4de41e140a7b3d618f 100644 --- a/src/prefs/LibraryPrefs.h +++ b/src/prefs/LibraryPrefs.h @@ -46,4 +46,9 @@ class LibraryPrefs :public PrefsPanel DECLARE_EVENT_TABLE(); }; +class LibraryPrefsFactory : public PrefsPanelFactory +{ +public: + virtual PrefsPanel *Create(wxWindow *parent); +}; #endif diff --git a/src/prefs/MidiIOPrefs.cpp b/src/prefs/MidiIOPrefs.cpp index d541e6ec322f4a286514d5a589a85d9ddad3aba9..382876e1b43827e1821ac3ca7349685e1c27f919 100644 --- a/src/prefs/MidiIOPrefs.cpp +++ b/src/prefs/MidiIOPrefs.cpp @@ -284,4 +284,9 @@ bool MidiIOPrefs::Validate() return true; } +PrefsPanel *MidiIOPrefsFactory::Create(wxWindow *parent) +{ + return new MidiIOPrefs(parent); +} + #endif diff --git a/src/prefs/MidiIOPrefs.h b/src/prefs/MidiIOPrefs.h index 81da992c3a8e52c0064ae1c84a0fc99a4db28684..1970b7061a049dac21ff77bd3fa177fda3167246 100644 --- a/src/prefs/MidiIOPrefs.h +++ b/src/prefs/MidiIOPrefs.h @@ -62,6 +62,11 @@ class MidiIOPrefs:public PrefsPanel DECLARE_EVENT_TABLE(); }; +class MidiIOPrefsFactory : public PrefsPanelFactory +{ +public: + virtual PrefsPanel *Create(wxWindow *parent); +}; #endif #endif diff --git a/src/prefs/ModulePrefs.cpp b/src/prefs/ModulePrefs.cpp index a9a2d9c30f0cb71337429f65349c7a59a3b6437c..01544b50b03a34c97ef517e013943bfb73890d2a 100644 --- a/src/prefs/ModulePrefs.cpp +++ b/src/prefs/ModulePrefs.cpp @@ -161,5 +161,9 @@ void ModulePrefs::SetModuleStatus( wxString fname, int iStatus ){ gPrefs->Flush(); } +PrefsPanel *ModulePrefsFactory::Create(wxWindow *parent) +{ + return new ModulePrefs(parent); +} diff --git a/src/prefs/ModulePrefs.h b/src/prefs/ModulePrefs.h index 9014e96a57a6005d8cc02a979bb6ecd91a8853b7..09d80a1d2cb016946db4ceb860cf51640c031797 100644 --- a/src/prefs/ModulePrefs.h +++ b/src/prefs/ModulePrefs.h @@ -50,4 +50,9 @@ class ModulePrefs:public PrefsPanel wxArrayString mPaths; }; +class ModulePrefsFactory : public PrefsPanelFactory +{ +public: + virtual PrefsPanel *Create(wxWindow *parent); +}; #endif diff --git a/src/prefs/MousePrefs.cpp b/src/prefs/MousePrefs.cpp index 4618ddf39fa7e2dacbdeb9af37e15f0b5c96c893..42d99f78c6f0f1331fd5113aeea682f282f46ce1 100644 --- a/src/prefs/MousePrefs.cpp +++ b/src/prefs/MousePrefs.cpp @@ -196,3 +196,8 @@ bool MousePrefs::Apply() // PopulateOrExchange(S); return true; } + +PrefsPanel *MousePrefsFactory::Create(wxWindow *parent) +{ + return new MousePrefs(parent); +} diff --git a/src/prefs/MousePrefs.h b/src/prefs/MousePrefs.h index 33f5254eae34f83933150a8b189e3966985966c6..df880373204307a78d6c6d067d9c19ae7fa11761 100644 --- a/src/prefs/MousePrefs.h +++ b/src/prefs/MousePrefs.h @@ -38,4 +38,9 @@ class MousePrefs :public PrefsPanel wxListCtrl * mList; }; +class MousePrefsFactory : public PrefsPanelFactory +{ +public: + virtual PrefsPanel *Create(wxWindow *parent); +}; #endif diff --git a/src/prefs/PlaybackPrefs.cpp b/src/prefs/PlaybackPrefs.cpp index 997d9be135854b0f573f99b165e002331dd0848b..d3c56e5c33b8714a8431bacd524cffe6524771d5 100644 --- a/src/prefs/PlaybackPrefs.cpp +++ b/src/prefs/PlaybackPrefs.cpp @@ -122,3 +122,8 @@ bool PlaybackPrefs::Apply() return true; } + +PrefsPanel *PlaybackPrefsFactory::Create(wxWindow *parent) +{ + return new PlaybackPrefs(parent); +} diff --git a/src/prefs/PlaybackPrefs.h b/src/prefs/PlaybackPrefs.h index 8384fb584ee860962110a4ec868dd237efaab9a7..057b51d840c2de36b2d510efee638e3d580cf4d8 100644 --- a/src/prefs/PlaybackPrefs.h +++ b/src/prefs/PlaybackPrefs.h @@ -32,4 +32,10 @@ class PlaybackPrefs :public PrefsPanel void PopulateOrExchange(ShuttleGui & S); }; +class PlaybackPrefsFactory : public PrefsPanelFactory +{ +public: + virtual PrefsPanel *Create(wxWindow *parent); +}; + #endif diff --git a/src/prefs/PrefsDialog.cpp b/src/prefs/PrefsDialog.cpp index 91f18bc65de7be9e2be3ce9cef1ea3ee144bbd75..39cc0a56c64ecdcbf9bcd6768fed9e526e5d2dcf 100644 --- a/src/prefs/PrefsDialog.cpp +++ b/src/prefs/PrefsDialog.cpp @@ -15,6 +15,7 @@ *//*******************************************************************/ #include "../Audacity.h" +#include "PrefsDialog.h" #include <wx/defs.h> #include <wx/button.h> @@ -41,7 +42,6 @@ #include "../Prefs.h" #include "../ShuttleGui.h" -#include "PrefsDialog.h" #include "PrefsPanel.h" #include "BatchPrefs.h" @@ -64,6 +64,7 @@ #include "ThemePrefs.h" #include "TracksPrefs.h" #include "WarningsPrefs.h" +#include "WaveformPrefs.h" #include "ExtImportPrefs.h" #ifdef EXPERIMENTAL_MIDI_OUT @@ -81,11 +82,14 @@ class wxTreebookExt : public wxTreebook { public: wxTreebookExt( wxWindow *parent, - wxWindowID id) : wxTreebook( parent, id ) + wxWindowID id, const wxString &titlePrefix) + : wxTreebook( parent, id ) + , mTitlePrefix(titlePrefix) {;}; ~wxTreebookExt(){;}; virtual int ChangeSelection(size_t n); virtual int SetSelection(size_t n); + const wxString mTitlePrefix; }; @@ -100,7 +104,7 @@ int wxTreebookExt::ChangeSelection(size_t n) { int wxTreebookExt::SetSelection(size_t n) { int i = wxTreebook::SetSelection(n); - wxString Temp = wxString(_("Preferences: ")) + GetPageText( n ); + wxString Temp = wxString(mTitlePrefix) + GetPageText( n ); ((wxDialog*)GetParent())->SetTitle( Temp ); ((wxDialog*)GetParent())->SetName( Temp ); return i; @@ -108,11 +112,86 @@ int wxTreebookExt::SetSelection(size_t n) -PrefsDialog::PrefsDialog(wxWindow * parent) +PrefsDialog::Factories +&PrefsDialog::DefaultFactories() +{ + // To do, perhaps: create this table by registration, without including each PrefsPanel + // class... and thus allowing a plug-in protocol + static DevicePrefsFactory devicePrefsFactory; + static PlaybackPrefsFactory playbackPrefsFactory; + static RecordingPrefsFactory recordingPrefsFactory; +#ifdef EXPERIMENTAL_MIDI_OUT + static MidiIOPrefsFactory midiIOPrefsFactory; +#endif + static QualityPrefsFactory qualityPrefsFactory; + static GUIPrefsFactory guiPrefsFactory; + static TracksPrefsFactory tracksPrefsFactory; + static ImportExportPrefsFactory importExportPrefsFactory; + static ExtImportPrefsFactory extImportPrefsFactory; + static ProjectsPrefsFactory projectsPrefsFactory; +#if !defined(DISABLE_DYNAMIC_LOADING_FFMPEG) || !defined(DISABLE_DYNAMIC_LOADING_LAME) + static LibraryPrefsFactory libraryPrefsFactory; +#endif + static WaveformPrefsFactory waveformPrefsFactory; + static SpectrumPrefsFactory spectrumPrefsFactory; + static DirectoriesPrefsFactory directoriesPrefsFactory; + static WarningsPrefsFactory warningsPrefsFactory; + static EffectsPrefsFactory effectsPrefsFactory; +#ifdef EXPERIMENTAL_THEME_PREFS + static ThemePrefsFactory themePrefsFactory; +#endif + // static BatchPrefsFactory batchPrefsFactory; + static KeyConfigPrefsFactory keyConfigPrefsFactory; + static MousePrefsFactory mousePrefsFactory; +#ifdef EXPERIMENTAL_MODULE_PREFS + static ModulePrefsFactory modulePrefsFactory; +#endif + + static PrefsNode nodes[] = { + &devicePrefsFactory, + &playbackPrefsFactory, + &recordingPrefsFactory, +#ifdef EXPERIMENTAL_MIDI_OUT + &midiIOPrefsFactory, +#endif + &qualityPrefsFactory, + &guiPrefsFactory, + &tracksPrefsFactory, + &importExportPrefsFactory, + &extImportPrefsFactory, + &projectsPrefsFactory, +#if !defined(DISABLE_DYNAMIC_LOADING_FFMPEG) || !defined(DISABLE_DYNAMIC_LOADING_LAME) + &libraryPrefsFactory, +#endif + &waveformPrefsFactory, + &spectrumPrefsFactory, + &directoriesPrefsFactory, + &warningsPrefsFactory, + &effectsPrefsFactory, +#ifdef EXPERIMENTAL_THEME_PREFS + &themePrefsFactory, +#endif + // &batchPrefsFactory, + &keyConfigPrefsFactory, + &mousePrefsFactory, +#ifdef EXPERIMENTAL_MODULE_PREFS + &modulePrefsFactory, +#endif + }; + + static Factories factories(nodes, nodes + sizeof(nodes) / sizeof(nodes[0])); + return factories; +} + + +PrefsDialog::PrefsDialog + (wxWindow * parent, const wxString &titlePrefix, Factories &factories) : wxDialog(parent, wxID_ANY, wxString(_("Audacity Preferences")), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) +, mFactories(factories) +, mTitlePrefix(titlePrefix) { ShuttleGui S(this, eIsCreating); @@ -120,42 +199,36 @@ PrefsDialog::PrefsDialog(wxWindow * parent) { S.StartHorizontalLay(wxALIGN_LEFT | wxEXPAND, true); { - mCategories = new wxTreebookExt(this, wxID_ANY); + mCategories = new wxTreebookExt(this, wxID_ANY, mTitlePrefix); S.Prop(1); S.AddWindow(mCategories, wxEXPAND); - wxWindow *w; - // Parameters are: AddPage(page, name, IsSelected, imageId). - w = new DevicePrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); - w = new PlaybackPrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); - w = new RecordingPrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); -#ifdef EXPERIMENTAL_MIDI_OUT - w = new MidiIOPrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); -#endif - w = new QualityPrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); - w = new GUIPrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); - w = new TracksPrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); - w = new ImportExportPrefs(mCategories);mCategories->AddPage(w, w->GetName(), false, 0); - w = new ExtImportPrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); - w = new ProjectsPrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); -#if !defined(DISABLE_DYNAMIC_LOADING_FFMPEG) || !defined(DISABLE_DYNAMIC_LOADING_LAME) - w = new LibraryPrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); -#endif - w = new SpectrumPrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); - w = new DirectoriesPrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); - w = new WarningsPrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); - w = new EffectsPrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); - -#ifdef EXPERIMENTAL_THEME_PREFS - w = new ThemePrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); -#endif - -// w = new BatchPrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); - w = new KeyConfigPrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); - w = new MousePrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); -#ifdef EXPERIMENTAL_MODULE_PREFS - w = new ModulePrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); -#endif + { + typedef std::pair<int, int> IntPair; + std::vector<IntPair> stack; + int iPage = 0; + for (Factories::const_iterator it = factories.begin(), end = factories.end(); + it != end; ++it, ++iPage) + { + const PrefsNode &node = *it; + PrefsPanelFactory &factory = *node.pFactory; + wxWindow *const w = factory.Create(mCategories); + if (stack.empty()) + // Parameters are: AddPage(page, name, IsSelected, imageId). + mCategories->AddPage(w, w->GetName(), false, 0); + else { + IntPair &top = *stack.rbegin(); + mCategories->InsertSubPage(top.first, w, w->GetName(), false, 0); + if (--top.second == 0) { + // Expand all nodes before the layout calculation + mCategories->ExpandNode(top.first, true); + stack.pop_back(); + } + } + if (node.nChildren > 0) + stack.push_back(IntPair(iPage, node.nChildren)); + } + } } S.EndHorizontalLay(); } @@ -163,23 +236,6 @@ PrefsDialog::PrefsDialog(wxWindow * parent) S.AddStandardButtons(eOkButton | eCancelButton); - /* long is signed, size_t is unsigned. On some platforms they are different - * lengths as well. So we must check that the stored category is both > 0 - * and within the possible range of categories, making the first check on the - * _signed_ value to avoid issues when converting an unsigned one. - */ - size_t selected; - long prefscat = gPrefs->Read(wxT("/Prefs/PrefsCategory"), 0L); - if (prefscat > 0L ) - selected = prefscat; // only assign if number will fit - else - selected = 0; // use 0 if value can't be assigned - - if (selected >= mCategories->GetPageCount()) - selected = 0; // clamp to available range of tabs - - mCategories->SetSelection(selected); - #if defined(__WXGTK__) mCategories->GetTreeCtrl()->EnsureVisible(mCategories->GetTreeCtrl()->GetRootItem()); #endif @@ -189,6 +245,14 @@ PrefsDialog::PrefsDialog(wxWindow * parent) Fit(); wxSize sz = GetSize(); + // Collapse nodes only after layout so the tree is wide enough + { + int iPage = 0; + for (Factories::const_iterator it = factories.begin(), end = factories.end(); + it != end; ++it, ++iPage) + mCategories->ExpandNode(iPage, it->expanded); + } + // This ASSERT used to limit us to 800 x 600. // However, we think screens have got bigger now, and that was a bit too restrictive. // The impetus for increasing the limit (before we ASSERT) was that this ASSERT @@ -219,8 +283,25 @@ PrefsDialog::~PrefsDialog() { } +int PrefsDialog::ShowModal() +{ + /* long is signed, size_t is unsigned. On some platforms they are different + * lengths as well. So we must check that the stored category is both > 0 + * and within the possible range of categories, making the first check on the + * _signed_ value to avoid issues when converting an unsigned one. + */ + long selected = GetPreferredPage(); + if (selected < 0 || size_t(selected) >= mCategories->GetPageCount()) + selected = 0; // clamp to available range of tabs + mCategories->SetSelection(selected); + + return wxDialog::ShowModal(); +} + void PrefsDialog::OnCancel(wxCommandEvent & WXUNUSED(event)) { + RecordExpansionState(); + for (size_t i = 0; i < mCategories->GetPageCount(); i++) { ((PrefsPanel *) mCategories->GetPage(i))->Cancel(); } @@ -238,6 +319,8 @@ void PrefsDialog::OnTreeKeyDown(wxTreeEvent & event) void PrefsDialog::OnOK(wxCommandEvent & WXUNUSED(event)) { + RecordExpansionState(); + // Validate all pages first for (size_t i = 0; i < mCategories->GetPageCount(); i++) { PrefsPanel *panel = (PrefsPanel *) mCategories->GetPage(i); @@ -256,8 +339,7 @@ void PrefsDialog::OnOK(wxCommandEvent & WXUNUSED(event)) panel->Apply(); } - gPrefs->Write(wxT("/Prefs/PrefsCategory"), (long)mCategories->GetSelection()); - gPrefs->Flush(); + SavePreferredPage(); #if USE_PORTMIXER if (gAudioIO) { @@ -307,7 +389,39 @@ void PrefsDialog::SelectPageByName(wxString pageName) } } -void PrefsDialog::ShowTempDirPage() +int PrefsDialog::GetSelectedPage() const +{ + return mCategories->GetSelection(); +} + +GlobalPrefsDialog::GlobalPrefsDialog(wxWindow * parent, Factories &factories) + : PrefsDialog(parent, _("Preferences: "), factories) +{ +} + +GlobalPrefsDialog::~GlobalPrefsDialog() +{ +} + +long GlobalPrefsDialog::GetPreferredPage() { - SelectPageByName(_("Directories")); + long prefscat = gPrefs->Read(wxT("/Prefs/PrefsCategory"), 0L); + return prefscat; +} + +void GlobalPrefsDialog::SavePreferredPage() +{ + gPrefs->Write(wxT("/Prefs/PrefsCategory"), (long)GetSelectedPage()); + gPrefs->Flush(); +} + +void PrefsDialog::RecordExpansionState() +{ + // Remember expansion state of the tree control + { + int iPage = 0; + for (Factories::iterator it = mFactories.begin(), end = mFactories.end(); + it != end; ++it, ++iPage) + it->expanded = mCategories->IsNodeExpanded(iPage); + } } diff --git a/src/prefs/PrefsDialog.h b/src/prefs/PrefsDialog.h index 13f3d3e0c03eb5388dd2759ad4f3e4cdf6671cda..a4b4689214a8f975ea5ef111968afab82b811779 100644 --- a/src/prefs/PrefsDialog.h +++ b/src/prefs/PrefsDialog.h @@ -12,6 +12,7 @@ #ifndef __AUDACITY_PREFS_DIALOG__ #define __AUDACITY_PREFS_DIALOG__ +#include <vector> #include <wx/button.h> #include <wx/event.h> #include <wx/dialog.h> @@ -19,24 +20,74 @@ #include <wx/treebook.h> #include <wx/window.h> +class PrefsPanelFactory; + +#ifdef __GNUC__ +#define CONST +#else +#define CONST const +#endif + class PrefsDialog:public wxDialog { public: - PrefsDialog(wxWindow * parent); + // An array of PrefsNode specifies the tree of pages in pre-order traversal. + struct PrefsNode { + PrefsPanelFactory * CONST pFactory; + CONST int nChildren; + bool expanded; + + PrefsNode(PrefsPanelFactory *pFactory_, int nChildren_ = 0) + : pFactory(pFactory_), nChildren(nChildren_), expanded(false) + {} + }; + typedef std::vector<PrefsNode> Factories; + static Factories &DefaultFactories(); + + PrefsDialog(wxWindow * parent, + const wxString &titlePrefix = _("Preferences: "), + Factories &factories = DefaultFactories()); virtual ~PrefsDialog(); + // Defined this so a protected virtual can be invoked after the constructor + virtual int ShowModal(); + void OnCategoryChange(wxCommandEvent & e); void OnOK(wxCommandEvent & e); void OnCancel(wxCommandEvent & e); void OnTreeKeyDown(wxTreeEvent & e); // Used to dismiss the dialog when enter is pressed with focus on tree void SelectPageByName(wxString pageName); - void ShowTempDirPage(); - private: + // Accessor to help implementations of SavePreferredPage(), + // such as by saving a preference after DoModal() returns + int GetSelectedPage() const; + + protected: + // Decide which page to open first; return -1 for undecided + virtual long GetPreferredPage() = 0; + + // Called after OK is clicked and all pages validate + virtual void SavePreferredPage() = 0; + +private: + void RecordExpansionState(); wxTreebook *mCategories; + Factories &mFactories; + const wxString mTitlePrefix; DECLARE_EVENT_TABLE() }; +// This adds code appropriate only to the original use of PrefsDialog for +// global settings -- not its reuses elsewhere as in View Settings +class GlobalPrefsDialog : public PrefsDialog +{ +public: + GlobalPrefsDialog(wxWindow * parent, Factories &factories = DefaultFactories()); + virtual ~GlobalPrefsDialog(); + virtual long GetPreferredPage(); + virtual void SavePreferredPage(); +}; + #endif diff --git a/src/prefs/PrefsPanel.h b/src/prefs/PrefsPanel.h index e35eacf44612768aaef9783893cfa42c0f44dad9..2af21079a42d20d4eb225b06c1f442a84e89870c 100644 --- a/src/prefs/PrefsPanel.h +++ b/src/prefs/PrefsPanel.h @@ -61,4 +61,10 @@ class PrefsPanel:public wxPanel } }; +class PrefsPanelFactory +{ +public: + virtual PrefsPanel *Create(wxWindow *parent) = 0; +}; + #endif diff --git a/src/prefs/ProjectsPrefs.cpp b/src/prefs/ProjectsPrefs.cpp index 56f22f8c8a303dc300219f8cafc51c208ac0481d..fc1e076304f710c3ac1b2483589657047ffa3189 100644 --- a/src/prefs/ProjectsPrefs.cpp +++ b/src/prefs/ProjectsPrefs.cpp @@ -79,3 +79,8 @@ bool ProjectsPrefs::Apply() return true; } + +PrefsPanel *ProjectsPrefsFactory::Create(wxWindow *parent) +{ + return new ProjectsPrefs(parent); +} diff --git a/src/prefs/ProjectsPrefs.h b/src/prefs/ProjectsPrefs.h index 3f1a0079139cfea7be26e36cdb3e7f5d273c1d76..480a49f717df08793e9c83452fc1e57438677dda 100644 --- a/src/prefs/ProjectsPrefs.h +++ b/src/prefs/ProjectsPrefs.h @@ -33,4 +33,9 @@ class ProjectsPrefs :public PrefsPanel void PopulateOrExchange(ShuttleGui & S); }; +class ProjectsPrefsFactory : public PrefsPanelFactory +{ +public: + virtual PrefsPanel *Create(wxWindow *parent); +}; #endif diff --git a/src/prefs/QualityPrefs.cpp b/src/prefs/QualityPrefs.cpp index 10c5fb1b0173e8e2fbdc360af85fb1039553c31f..1f7e54918533ef80499bb3fc5192c8803be7b92a 100644 --- a/src/prefs/QualityPrefs.cpp +++ b/src/prefs/QualityPrefs.cpp @@ -16,6 +16,7 @@ *//*******************************************************************/ #include "../Audacity.h" +#include "QualityPrefs.h" #include <wx/defs.h> @@ -26,8 +27,6 @@ #include "../SampleFormat.h" #include "../ShuttleGui.h" -#include "QualityPrefs.h" - #define ID_SAMPLE_RATE_CHOICE 7001 BEGIN_EVENT_TABLE(QualityPrefs, PrefsPanel) @@ -228,3 +227,8 @@ bool QualityPrefs::Apply() return true; } + +PrefsPanel *QualityPrefsFactory::Create(wxWindow *parent) +{ + return new QualityPrefs(parent); +} diff --git a/src/prefs/QualityPrefs.h b/src/prefs/QualityPrefs.h index 726da2490c23e2c843f6e35d2ebbe955c67af46b..778417a2c651faf830f7071b3ca7ea71f20d00fb 100644 --- a/src/prefs/QualityPrefs.h +++ b/src/prefs/QualityPrefs.h @@ -53,4 +53,9 @@ class QualityPrefs :public PrefsPanel DECLARE_EVENT_TABLE(); }; +class QualityPrefsFactory : public PrefsPanelFactory +{ +public: + virtual PrefsPanel *Create(wxWindow *parent); +}; #endif diff --git a/src/prefs/RecordingPrefs.cpp b/src/prefs/RecordingPrefs.cpp index 01e3db2a496026d022886d67414a8d772a274e1d..fcc054c0c8bf5c5740753e93697791f65401e5cc 100644 --- a/src/prefs/RecordingPrefs.cpp +++ b/src/prefs/RecordingPrefs.cpp @@ -19,18 +19,17 @@ *//********************************************************************/ #include "../Audacity.h" +#include "RecordingPrefs.h" #include <wx/defs.h> #include <wx/textctrl.h> #include <algorithm> #include "../AudioIO.h" -#include "../Envelope.h" +#include "../prefs/GUISettings.h" #include "../Prefs.h" #include "../ShuttleGui.h" -#include "RecordingPrefs.h" - using std::min; RecordingPrefs::RecordingPrefs(wxWindow * parent) @@ -113,7 +112,7 @@ void RecordingPrefs::PopulateOrExchange(ShuttleGui & S) { S.SetStretchyCol(1); - int dBRange = gPrefs->Read(wxT("/GUI/EnvdBRange"), ENV_DB_RANGE); + int dBRange = gPrefs->Read(ENV_DB_KEY, ENV_DB_RANGE); S.TieSlider(_("Sound Activation Le&vel (dB):"), wxT("/AudioIO/SilenceLevel"), -50, @@ -202,3 +201,8 @@ bool RecordingPrefs::Apply() #endif return gPrefs->Flush(); } + +PrefsPanel *RecordingPrefsFactory::Create(wxWindow *parent) +{ + return new RecordingPrefs(parent); +} diff --git a/src/prefs/RecordingPrefs.h b/src/prefs/RecordingPrefs.h index d4f1dd122225d322f247745a62751010d2946952..f3f8b9ee19ccf56d0fdbaab97575ab51eb751b66 100644 --- a/src/prefs/RecordingPrefs.h +++ b/src/prefs/RecordingPrefs.h @@ -32,4 +32,9 @@ class RecordingPrefs :public PrefsPanel void PopulateOrExchange(ShuttleGui & S); }; +class RecordingPrefsFactory : public PrefsPanelFactory +{ +public: + virtual PrefsPanel *Create(wxWindow *parent); +}; #endif diff --git a/src/prefs/SpectrogramSettings.cpp b/src/prefs/SpectrogramSettings.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ff2c1649aad52108f18796ec71a9547579f5c6ea --- /dev/null +++ b/src/prefs/SpectrogramSettings.cpp @@ -0,0 +1,621 @@ +/********************************************************************** + +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 "../NumberScale.h" + +#include <algorithm> +#include <wx/msgdlg.h> + +#include "../FFT.h" +#include "../Prefs.h" +#include "../RealFFTf.h" + +#include <cmath> + +SpectrogramSettings::Globals::Globals() +{ + LoadPrefs(); +} + +void SpectrogramSettings::Globals::SavePrefs() +{ +#ifdef SPECTRAL_SELECTION_GLOBAL_SWITCH + gPrefs->Write(wxT("/Spectrum/EnableSpectralSelection"), spectralSelection); +#endif +} + +void SpectrogramSettings::Globals::LoadPrefs() +{ +#ifdef SPECTRAL_SELECTION_GLOBAL_SWITCH + spectralSelection + = (gPrefs->Read(wxT("/Spectrum/EnableSpectralSelection"), 0L) != 0); +#endif +} + +SpectrogramSettings::Globals +&SpectrogramSettings::Globals::Get() +{ + static Globals instance; + return instance; +} + +SpectrogramSettings::SpectrogramSettings() + : hFFT(0) + , window(0) +{ + LoadPrefs(); +} + +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) + , scaleType(other.scaleType) +#ifndef SPECTRAL_SELECTION_GLOBAL_SWITCH + , spectralSelection(other.spectralSelection) +#endif + , algorithm(other.algorithm) +#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; + scaleType = other.scaleType; +#ifndef SPECTRAL_SELECTION_GLOBAL_SWITCH + spectralSelection = other.spectralSelection; +#endif + algorithm = other.algorithm; +#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; +} + +namespace +{ + wxArrayString &scaleNamesArray() + { + static wxArrayString theArray; + return theArray; + } + + wxArrayString &algorithmNamesArray() + { + static wxArrayString theArray; + return theArray; + } +} + +//static +void SpectrogramSettings::InvalidateNames() +{ + scaleNamesArray().Clear(); + algorithmNamesArray().Clear(); +} + +//static +const wxArrayString &SpectrogramSettings::GetScaleNames() +{ + wxArrayString &theArray = scaleNamesArray(); + + if (theArray.IsEmpty()) { + // Keep in correspondence with enum SpectrogramSettings::ScaleType: + theArray.Add(_("Linear")); + theArray.Add(_("Logarithmic")); + theArray.Add(_("Mel")); + theArray.Add(_("Bark")); + theArray.Add(_("Erb")); + theArray.Add(_("Undertone")); + } + + return theArray; +} + +//static +const wxArrayString &SpectrogramSettings::GetAlgorithmNames() +{ + wxArrayString &theArray = algorithmNamesArray(); + + if (theArray.IsEmpty()) { + // Keep in correspondence with enum SpectrogramSettings::Algorithm: + theArray.Add(_("STFT")); + theArray.Add(_("Pitch (enhanced autocorrelation)")); + } + + return theArray; +} + +bool SpectrogramSettings::Validate(bool quiet) +{ + if (!quiet && + maxFreq < 100) { + wxMessageBox(_("Maximum frequency must be 100 Hz or above")); + return false; + } + else + maxFreq = std::max(100, maxFreq); + + if (!quiet && + minFreq < 0) { + wxMessageBox(_("Minimum frequency must be at least 0 Hz")); + return false; + } + else + minFreq = std::max(0, minFreq); + + if (!quiet && + maxFreq <= minFreq) { + wxMessageBox(_("Minimum frequency must be less than maximum frequency")); + return false; + } + else + maxFreq = std::max(1 + minFreq, maxFreq); + + if (!quiet && + range <= 0) { + wxMessageBox(_("The range must be at least 1 dB")); + return false; + } + else + range = std::max(1, range); + + if (!quiet && + frequencyGain < 0) { + wxMessageBox(_("The frequency gain cannot be negative")); + return false; + } + else if (!quiet && + frequencyGain > 60) { + wxMessageBox(_("The frequency gain must be no more than 60 dB/dec")); + return false; + } + else + frequencyGain = + std::max(0, std::min(60, frequencyGain)); + + // The rest are controlled by drop-down menus so they can't go wrong + // in the Preferences dialog, but we also come here after reading fom saved + // preference files, which could be or from future versions. Validate quietly. + windowType = + std::max(0, std::min(NumWindowFuncs() - 1, windowType)); + scaleType = + ScaleType(std::max(0, + std::min(int(SpectrogramSettings::stNumScaleTypes) - 1, + int(scaleType)))); + algorithm = Algorithm( + std::max(0, std::min(int(algNumAlgorithms) - 1, int(algorithm))) + ); + ConvertToEnumeratedWindowSizes(); + ConvertToActualWindowSizes(); + + return true; +} + +void SpectrogramSettings::LoadPrefs() +{ + minFreq = gPrefs->Read(wxT("/Spectrum/MinFreq"), 0L); + + maxFreq = gPrefs->Read(wxT("/Spectrum/MaxFreq"), 8000L); + + range = gPrefs->Read(wxT("/Spectrum/Range"), 80L); + gain = gPrefs->Read(wxT("/Spectrum/Gain"), 20L); + frequencyGain = gPrefs->Read(wxT("/Spectrum/FrequencyGain"), 0L); + + windowSize = gPrefs->Read(wxT("/Spectrum/FFTSize"), 256); + +#ifdef EXPERIMENTAL_ZERO_PADDED_SPECTROGRAMS + zeroPaddingFactor = gPrefs->Read(wxT("/Spectrum/ZeroPaddingFactor"), 1); +#endif + + gPrefs->Read(wxT("/Spectrum/WindowType"), &windowType, eWinFuncHanning); + + isGrayscale = (gPrefs->Read(wxT("/Spectrum/Grayscale"), 0L) != 0); + + scaleType = ScaleType(gPrefs->Read(wxT("/Spectrum/ScaleType"), 0L)); + +#ifndef SPECTRAL_SELECTION_GLOBAL_SWITCH + spectralSelection = (gPrefs->Read(wxT("/Spectrum/EnableSpectralSelection"), 0L) != 0); +#endif + + algorithm = Algorithm(gPrefs->Read(wxT("/Spectrum/Algorithm"), 0L)); + +#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 + + // Enforce legal values + Validate(true); + + // 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 + logMinFreq = gPrefs->Read(wxT("/SpectrumLog/MinFreq"), -1); + if (logMinFreq < 0) + logMinFreq = minFreq; + if (logMinFreq < 1) + logMinFreq = 1; + logMaxFreq = gPrefs->Read(wxT("/SpectrumLog/MaxFreq"), -1); + if (logMaxFreq < 0) + logMaxFreq = maxFreq; + logMaxFreq = + std::max(logMinFreq + 1, logMaxFreq); + + InvalidateCaches(); +} + +void SpectrogramSettings::SavePrefs() +{ + gPrefs->Write(wxT("/Spectrum/MinFreq"), minFreq); + gPrefs->Write(wxT("/Spectrum/MaxFreq"), maxFreq); + + // Nothing wrote these. They only varied from the linear scale bounds in-session. -- PRL + // gPrefs->Write(wxT("/SpectrumLog/MaxFreq"), logMinFreq); + // gPrefs->Write(wxT("/SpectrumLog/MinFreq"), logMaxFreq); + + gPrefs->Write(wxT("/Spectrum/Range"), range); + gPrefs->Write(wxT("/Spectrum/Gain"), gain); + gPrefs->Write(wxT("/Spectrum/FrequencyGain"), frequencyGain); + + gPrefs->Write(wxT("/Spectrum/FFTSize"), windowSize); + +#ifdef EXPERIMENTAL_ZERO_PADDED_SPECTROGRAMS + gPrefs->Write(wxT("/Spectrum/ZeroPaddingFactor"), zeroPaddingFactor); +#endif + + gPrefs->Write(wxT("/Spectrum/WindowType"), windowType); + + gPrefs->Write(wxT("/Spectrum/Grayscale"), isGrayscale); + + gPrefs->Write(wxT("/Spectrum/ScaleType"), scaleType); + +#ifndef SPECTRAL_SELECTION_GLOBAL_SWITCH + gPrefs->Write(wxT("/Spectrum/EnableSpectralSelection"), spectralSelection); +#endif + + gPrefs->Write(wxT("/Spectrum/Algorithm"), algorithm); + +#ifdef EXPERIMENTAL_FFT_Y_GRID + gPrefs->Write(wxT("/Spectrum/FFTYGrid"), fftYGrid); +#endif //EXPERIMENTAL_FFT_Y_GRID + +#ifdef EXPERIMENTAL_FIND_NOTES + gPrefs->Write(wxT("/Spectrum/FFTFindNotes"), fftFindNotes); + gPrefs->Write(wxT("/Spectrum/FindNotesMinA"), findNotesMinA); + gPrefs->Write(wxT("/Spectrum/FindNotesN"), numberOfMaxima); + gPrefs->Write(wxT("/Spectrum/FindNotesQuantize"), findNotesQuantize); +#endif //EXPERIMENTAL_FIND_NOTES +} + +void SpectrogramSettings::InvalidateCaches() +{ + 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 +} + +void SpectrogramSettings::ConvertToEnumeratedWindowSizes() +{ + unsigned size; + int logarithm; + + logarithm = -LogMinWindowSize; + size = unsigned(windowSize); + while (size > 1) + size >>= 1, ++logarithm; + windowSize = std::max(0, std::min(NumWindowSizes - 1, logarithm)); + +#ifdef EXPERIMENTAL_ZERO_PADDED_SPECTROGRAMS + // Choices for zero padding begin at 1 + logarithm = 0; + size = unsigned(zeroPaddingFactor); + while (zeroPaddingFactor > 1) + zeroPaddingFactor >>= 1, ++logarithm; + zeroPaddingFactor = std::max(0, + std::min(LogMaxWindowSize - (windowSize + LogMinWindowSize), + logarithm + )); +#endif +} + +void SpectrogramSettings::ConvertToActualWindowSizes() +{ + windowSize = 1 << (windowSize + LogMinWindowSize); +#ifdef EXPERIMENTAL_ZERO_PADDED_SPECTROGRAMS + zeroPaddingFactor = 1 << zeroPaddingFactor; +#endif +} + +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() const +{ + return windowSize +#ifdef EXPERIMENTAL_ZERO_PADDED_SPECTROGRAMS + * ((algorithm == algSTFT) ? zeroPaddingFactor : 1); +#endif + ; +} + +NumberScale SpectrogramSettings::GetScale +(double rate, bool bins) const +{ + int minFreq, maxFreq; + NumberScaleType type = nstLinear; + const int half = GetFFTLength() / 2; + + // Don't assume the correspondence of the enums will remain direct in the future. + // Do this switch. + switch (scaleType) { + default: + wxASSERT(false); + case stLinear: + type = nstLinear; break; + case stLogarithmic: + type = nstLogarithmic; break; + case stMel: + type = nstMel; break; + case stBark: + type = nstBark; break; + case stErb: + type = nstErb; break; + case stUndertone: + type = nstUndertone; break; + } + + switch (scaleType) { + default: + wxASSERT(false); + case stLinear: + minFreq = GetMinFreq(rate); + maxFreq = GetMaxFreq(rate); + break; + case stLogarithmic: + case stMel: + case stBark: + case stErb: + minFreq = GetLogMinFreq(rate); + maxFreq = GetLogMaxFreq(rate); + break; + case stUndertone: + { + const float bin2 = rate / half; + minFreq = std::max(int(0.5 + bin2), GetLogMinFreq(rate)); + maxFreq = GetLogMaxFreq(rate); + } + break; + } + + return NumberScale(type, minFreq, maxFreq, + bins ? rate / (2 * half) : 1.0f); +} + +bool SpectrogramSettings::SpectralSelectionEnabled() const +{ +#ifdef SPECTRAL_SELECTION_GLOBAL_SWITCH + return Globals::Get().spectralSelection; +#else + return spectralSelection; +#endif +} diff --git a/src/prefs/SpectrogramSettings.h b/src/prefs/SpectrogramSettings.h new file mode 100644 index 0000000000000000000000000000000000000000..57c1cc58ab5437d58a593755a477d8419b570bd7 --- /dev/null +++ b/src/prefs/SpectrogramSettings.h @@ -0,0 +1,158 @@ +/********************************************************************** + +Audacity: A Digital Audio Editor + +SpectrogramSettings.h + +Paul Licameli + +**********************************************************************/ + +#ifndef __AUDACITY_SPECTROGRAM_SETTINGS__ +#define __AUDACITY_SPECTROGRAM_SETTINGS__ + +#include "../Experimental.h" + +#undef SPECTRAL_SELECTION_GLOBAL_SWITCH + +struct FFTParam; +class NumberScale; +class SpectrumPrefs; +class wxArrayString; + +class SpectrogramSettings +{ + friend class SpectrumPrefs; +public: + + // Singleton for settings that are not per-track + class Globals + { + public: + static Globals &Get(); + void SavePrefs(); + +#ifdef SPECTRAL_SELECTION_GLOBAL_SWITCH + bool spectralSelection; +#endif + + private: + Globals(); + void LoadPrefs(); + }; + + enum { + LogMinWindowSize = 3, + LogMaxWindowSize = 15, + + NumWindowSizes = LogMaxWindowSize - LogMinWindowSize + 1, + }; + + // Do not assume that this enumeration will remain the + // same as NumberScaleType in future. That enum may become + // more general purpose. + enum ScaleType { + stLinear, + stLogarithmic, + stMel, + stBark, + stErb, + stUndertone, + + stNumScaleTypes, + }; + + static void InvalidateNames(); // in case of language change + static const wxArrayString &GetScaleNames(); + static const wxArrayString &GetAlgorithmNames(); + + static SpectrogramSettings &defaults(); + SpectrogramSettings(); + SpectrogramSettings(const SpectrogramSettings &other); + SpectrogramSettings& operator= (const SpectrogramSettings &other); + ~SpectrogramSettings(); + + bool IsDefault() const + { + return this == &defaults(); + } + + bool Validate(bool quiet); + void LoadPrefs(); + void SavePrefs(); + void InvalidateCaches(); + void DestroyWindows(); + void CacheWindows() const; + void ConvertToEnumeratedWindowSizes(); + void ConvertToActualWindowSizes(); + + // If "bins" is false, units are Hz + NumberScale GetScale + (double rate, bool bins) 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; + bool SpectralSelectionEnabled() 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() const; // window size (times zero padding, if STFT) + + bool isGrayscale; + + ScaleType scaleType; + +#ifndef SPECTRAL_SELECTION_GLOBAL_SWITCH + bool spectralSelection; // But should this vary per track? -- PRL +#endif + + enum Algorithm { + algSTFT = 0, + algPitchEAC, + + algNumAlgorithms, + }; + Algorithm algorithm; + +#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 diff --git a/src/prefs/SpectrumPrefs.cpp b/src/prefs/SpectrumPrefs.cpp index 118df5a384dc6dc7fb02fb9eae21039cd9106808..80564c71b921a79f279e197b36c7bbab04828427 100644 --- a/src/prefs/SpectrumPrefs.cpp +++ b/src/prefs/SpectrumPrefs.cpp @@ -20,18 +20,33 @@ #include <wx/defs.h> #include <wx/intl.h> #include <wx/msgdlg.h> +#include <wx/checkbox.h> -#include "../Prefs.h" +#include "../FFT.h" #include "../Project.h" #include "../ShuttleGui.h" -#include "../FFT.h" +#include "../WaveTrack.h" +#include "../TrackPanel.h" #include <algorithm> -SpectrumPrefs::SpectrumPrefs(wxWindow * parent) +SpectrumPrefs::SpectrumPrefs(wxWindow * parent, WaveTrack *wt) : PrefsPanel(parent, _("Spectrograms")) +, mWt(wt) +, mPopulating(false) { - int windowSize = gPrefs->Read(wxT("/Spectrum/FFTSize"), 256); + if (mWt) { + SpectrogramSettings &settings = wt->GetSpectrogramSettings(); + mDefaulted = (&SpectrogramSettings::defaults() == &settings); + mTempSettings = settings; + } + else { + mTempSettings = SpectrogramSettings::defaults(); + mDefaulted = false; + } + + const int windowSize = mTempSettings.windowSize; + mTempSettings.ConvertToEnumeratedWindowSizes(); Populate(windowSize); } @@ -39,13 +54,23 @@ SpectrumPrefs::~SpectrumPrefs() { } -enum { maxWindowSize = 32768 }; - enum { ID_WINDOW_SIZE = 10001, #ifdef EXPERIMENTAL_ZERO_PADDED_SPECTROGRAMS - ID_PADDING_SIZE = 10002, + ID_WINDOW_TYPE, + ID_PADDING_SIZE, + ID_SCALE, + ID_ALGORITHM, + ID_MINIMUM, + ID_MAXIMUM, + ID_GAIN, + ID_RANGE, + ID_FREQUENCY_GAIN, + ID_GRAYSCALE, + ID_SPECTRAL_SELECTION, #endif + ID_DEFAULTS, + ID_APPLY, }; void SpectrumPrefs::Populate(int windowSize) @@ -63,26 +88,21 @@ void SpectrumPrefs::Populate(int windowSize) mSizeChoices.Add(wxT("8192")); mSizeChoices.Add(wxT("16384")); mSizeChoices.Add(_("32768 - most narrowband")); - - int lastCode = 0; - for (size_t i = 0; i < mSizeChoices.GetCount(); i++) { - mSizeCodes.Add(lastCode = 1 << (i + 3)); - } - wxASSERT(lastCode == maxWindowSize); + wxASSERT(mSizeChoices.size() == SpectrogramSettings::NumWindowSizes); PopulatePaddingChoices(windowSize); for (int i = 0; i < NumWindowFuncs(); i++) { mTypeChoices.Add(WindowFuncName(i)); - mTypeCodes.Add(i); } + mScaleChoices = SpectrogramSettings::GetScaleNames(); + + mAlgorithmChoices = SpectrogramSettings::GetAlgorithmNames(); //------------------------- Main section -------------------- // Now construct the GUI itself. - // Use 'eIsCreatingFromPrefs' so that the GUI is - // initialised with values from gPrefs. - ShuttleGui S(this, eIsCreatingFromPrefs); + ShuttleGui S(this, eIsCreating); PopulateOrExchange(S); // ----------------------- End of main section -------------- } @@ -107,14 +127,12 @@ void SpectrumPrefs::PopulatePaddingChoices(int windowSize) pPaddingSizeControl->Clear(); } - mZeroPaddingCodes.Clear(); - int padding = 1; int numChoices = 0; + const int maxWindowSize = 1 << (SpectrogramSettings::LogMaxWindowSize); while (windowSize <= maxWindowSize) { const wxString numeral = wxString::Format(wxT("%d"), padding); mZeroPaddingChoices.Add(numeral); - mZeroPaddingCodes.Add(padding); if (pPaddingSizeControl) pPaddingSizeControl->Append(numeral); windowSize <<= 1; @@ -131,174 +149,182 @@ void SpectrumPrefs::PopulatePaddingChoices(int windowSize) void SpectrumPrefs::PopulateOrExchange(ShuttleGui & S) { + mPopulating = true; + S.SetBorder(2); - S.StartStatic(_("FFT Window")); + // S.StartStatic(_("Track Settings")); { - S.StartMultiColumn(2); + mDefaultsCheckbox = 0; + if (mWt) { + mDefaultsCheckbox = S.Id(ID_DEFAULTS).TieCheckBox(_("Defaults"), mDefaulted); + } + S.StartStatic(_("FFT Window")); { - S.Id(ID_WINDOW_SIZE).TieChoice(_("Window &size:"), - wxT("/Spectrum/FFTSize"), - 256, - mSizeChoices, - mSizeCodes); - S.SetSizeHints(mSizeChoices); - - S.TieChoice(_("Window &type:"), - wxT("/Spectrum/WindowType"), - 3, - mTypeChoices, - mTypeCodes); - S.SetSizeHints(mTypeChoices); + S.StartMultiColumn(2); + { + S.Id(ID_WINDOW_SIZE).TieChoice(_("Window &size:"), + mTempSettings.windowSize, + &mSizeChoices); + S.SetSizeHints(mSizeChoices); + + S.Id(ID_WINDOW_TYPE).TieChoice(_("Window &type:"), + mTempSettings.windowType, + &mTypeChoices); + S.SetSizeHints(mTypeChoices); #ifdef EXPERIMENTAL_ZERO_PADDED_SPECTROGRAMS - S.Id(ID_PADDING_SIZE).TieChoice(_("&Zero padding factor") + wxString(wxT(":")), - wxT("/Spectrum/ZeroPaddingFactor"), - mZeroPaddingChoice, - mZeroPaddingChoices, - mZeroPaddingCodes); - S.SetSizeHints(mZeroPaddingChoices); + mZeroPaddingChoiceCtrl = + S.Id(ID_PADDING_SIZE).TieChoice(_("&Zero padding factor") + wxString(wxT(":")), + mTempSettings.zeroPaddingFactor, + &mZeroPaddingChoices); + S.SetSizeHints(mZeroPaddingChoices); #endif + } + S.EndMultiColumn(); } - S.EndMultiColumn(); - } - S.EndStatic(); + S.EndStatic(); - S.StartStatic(_("Display")); - { - S.StartTwoColumn(); + S.StartStatic(_("Display")); { - mMinFreq = - S.TieNumericTextBox(_("Mi&nimum Frequency (Hz):"), - wxT("/Spectrum/MinFreq"), - 0, - 12); - - mMaxFreq = - S.TieNumericTextBox(_("Ma&ximum Frequency (Hz):"), - wxT("/Spectrum/MaxFreq"), - 8000, - 12); - - mGain = - S.TieNumericTextBox(_("&Gain (dB):"), - wxT("/Spectrum/Gain"), - 20, - 8); - - mRange = - S.TieNumericTextBox(_("&Range (dB):"), - wxT("/Spectrum/Range"), - 80, - 8); - - mFrequencyGain = - S.TieNumericTextBox(_("Frequency g&ain (dB/dec):"), - wxT("/Spectrum/FrequencyGain"), - 0, - 4); - } - S.EndTwoColumn(); - - S.TieCheckBox(_("S&how the spectrum using grayscale colors"), - wxT("/Spectrum/Grayscale"), - false); + S.StartTwoColumn(); + { + S.Id(ID_SCALE).TieChoice(_("S&cale") + wxString(wxT(":")), + *(int*)&mTempSettings.scaleType, + &mScaleChoices); + + mAlgorithmChoice = + S.Id(ID_ALGORITHM).TieChoice(_("Algorithm") + wxString(wxT(":")), + *(int*)&mTempSettings.algorithm, + &mAlgorithmChoices); + + mMinFreq = + S.Id(ID_MINIMUM).TieNumericTextBox(_("Mi&nimum Frequency (Hz):"), + mTempSettings.minFreq, + 12); + + mMaxFreq = + S.Id(ID_MAXIMUM).TieNumericTextBox(_("Ma&ximum Frequency (Hz):"), + mTempSettings.maxFreq, + 12); + + mGain = + S.Id(ID_GAIN).TieNumericTextBox(_("&Gain (dB):"), + mTempSettings.gain, + 8); + + mRange = + S.Id(ID_RANGE).TieNumericTextBox(_("&Range (dB):"), + mTempSettings.range, + 8); + + mFrequencyGain = + S.Id(ID_FREQUENCY_GAIN).TieNumericTextBox(_("Frequency g&ain (dB/dec):"), + mTempSettings.frequencyGain, + 4); + } + S.EndTwoColumn(); + + S.Id(ID_GRAYSCALE).TieCheckBox(_("S&how the spectrum using grayscale colors"), + mTempSettings.isGrayscale); + +#ifndef SPECTRAL_SELECTION_GLOBAL_SWITCH + S.Id(ID_SPECTRAL_SELECTION).TieCheckBox(_("Ena&ble spectral selection"), + mTempSettings.spectralSelection); +#endif #ifdef EXPERIMENTAL_FFT_Y_GRID - S.TieCheckBox(_("Show a grid along the &Y-axis"), - wxT("/Spectrum/FFTYGrid"), - false); + S.TieCheckBox(_("Show a grid along the &Y-axis"), + mTempSettings.fftYGrid); #endif //EXPERIMENTAL_FFT_Y_GRID - } - S.EndStatic(); + } + S.EndStatic(); #ifdef EXPERIMENTAL_FIND_NOTES - /* i18n-hint: FFT stands for Fast Fourier Transform and probably shouldn't be translated*/ - S.StartStatic(_("FFT Find Notes")); - { - S.StartTwoColumn(); + /* i18n-hint: FFT stands for Fast Fourier Transform and probably shouldn't be translated*/ + S.StartStatic(_("FFT Find Notes")); { - mFindNotesMinA = - S.TieNumericTextBox(_("Minimum Amplitude (dB):"), - wxT("/Spectrum/FindNotesMinA"), - -30L, - 8); - - mFindNotesN = - S.TieNumericTextBox(_("Max. Number of Notes (1..128):"), - wxT("/Spectrum/FindNotesN"), - 5L, - 8); + S.StartTwoColumn(); + { + mFindNotesMinA = + S.TieNumericTextBox(_("Minimum Amplitude (dB):"), + mTempSettings.fftFindNotes, + 8); + + mFindNotesN = + S.TieNumericTextBox(_("Max. Number of Notes (1..128):"), + mTempSettings.findNotesMinA, + 8); + } + S.EndTwoColumn(); + + S.TieCheckBox(_("&Find Notes"), + mTempSettings.numberOfMaxima); + + S.TieCheckBox(_("&Quantize Notes"), + mTempSettings.findNotesQuantize); } - S.EndTwoColumn(); - - S.TieCheckBox(_("&Find Notes"), - wxT("/Spectrum/FFTFindNotes"), - false); + S.EndStatic(); +#endif //EXPERIMENTAL_FIND_NOTES + } + // S.EndStatic(); - S.TieCheckBox(_("&Quantize Notes"), - wxT("/Spectrum/FindNotesQuantize"), - false); +#ifdef SPECTRAL_SELECTION_GLOBAL_SWITCH + S.StartStatic(_("Global settings")); + { + S.TieCheckBox(_("Ena&ble spectral selection"), + SpectrogramSettings::Globals::Get().spectralSelection); } S.EndStatic(); -#endif //EXPERIMENTAL_FIND_NOTES +#endif + + S.StartMultiColumn(2, wxALIGN_RIGHT); + { + S.Id(ID_APPLY).AddButton(_("Appl&y")); + } + S.EndMultiColumn(); + + EnableDisableSTFTOnlyControls(); + + mPopulating = false; } bool SpectrumPrefs::Validate() { + // Do checking for whole numbers + + // ToDo: use wxIntegerValidator<unsigned> when available + long maxFreq; if (!mMaxFreq->GetValue().ToLong(&maxFreq)) { wxMessageBox(_("The maximum frequency must be an integer")); return false; } - if (maxFreq < 100) { - wxMessageBox(_("Maximum frequency must be 100 Hz or above")); - return false; - } long minFreq; if (!mMinFreq->GetValue().ToLong(&minFreq)) { wxMessageBox(_("The minimum frequency must be an integer")); return false; } - if (minFreq < 0) { - wxMessageBox(_("Minimum frequency must be at least 0 Hz")); - return false; - } - - if (maxFreq < minFreq) { - wxMessageBox(_("Minimum frequency must be less than maximum frequency")); - return false; - } long gain; if (!mGain->GetValue().ToLong(&gain)) { wxMessageBox(_("The gain must be an integer")); return false; } + long range; if (!mRange->GetValue().ToLong(&range)) { wxMessageBox(_("The range must be a positive integer")); return false; } - if (range <= 0) { - wxMessageBox(_("The range must be at least 1 dB")); - return false; - } long frequencygain; if (!mFrequencyGain->GetValue().ToLong(&frequencygain)) { wxMessageBox(_("The frequency gain must be an integer")); return false; } - if (frequencygain < 0) { - wxMessageBox(_("The frequency gain cannot be negative")); - return false; - } - if (frequencygain > 60) { - wxMessageBox(_("The frequency gain must be no more than 60 dB/dec")); - return false; - } + #ifdef EXPERIMENTAL_FIND_NOTES long findNotesMinA; if (!mFindNotesMinA->GetValue().ToLong(&findNotesMinA)) { @@ -317,199 +343,155 @@ bool SpectrumPrefs::Validate() } #endif //EXPERIMENTAL_FIND_NOTES - return true; + ShuttleGui S(this, eIsGettingFromDialog); + PopulateOrExchange(S); + + // Delegate range checking to SpectrogramSettings class + mTempSettings.ConvertToActualWindowSizes(); + const bool result = mTempSettings.Validate(false); + mTempSettings.ConvertToEnumeratedWindowSizes(); + return result; } bool SpectrumPrefs::Apply() { - ShuttleGui S(this, eIsSavingToPrefs); + const bool isOpenPage = this->IsShown(); + + WaveTrack *const partner = + mWt ? static_cast<WaveTrack*>(mWt->GetLink()) : 0; + + ShuttleGui S(this, eIsGettingFromDialog); PopulateOrExchange(S); - SpectrogramSettings::defaults().UpdatePrefs(); + + mTempSettings.ConvertToActualWindowSizes(); + SpectrogramSettings::Globals::Get().SavePrefs(); // always + + if (mWt) { + if (mDefaulted) { + mWt->SetSpectrogramSettings(NULL); + if (partner) + partner->SetSpectrogramSettings(NULL); + } + else { + SpectrogramSettings *pSettings = + &mWt->GetIndependentSpectrogramSettings(); + *pSettings = mTempSettings; + if (partner) { + pSettings = &partner->GetIndependentSpectrogramSettings(); + *pSettings = mTempSettings; + } + } + } + + if (!mWt || mDefaulted) { + SpectrogramSettings *const pSettings = &SpectrogramSettings::defaults(); + *pSettings = mTempSettings; + pSettings->SavePrefs(); + } + mTempSettings.ConvertToEnumeratedWindowSizes(); + + if (mWt && isOpenPage) { + // Future: open page will determine the track view type + mWt->SetDisplay(WaveTrack::Spectrum); + if (partner) + partner->SetDisplay(WaveTrack::Spectrum); + } return true; } -void SpectrumPrefs::OnWindowSize(wxCommandEvent &) +void SpectrumPrefs::OnControl(wxCommandEvent&) { + // Common routine for most controls + // If any per-track setting is changed, break the association with defaults + // Skip this, and View Settings... will be able to change defaults instead + // when the checkbox is on, as in the original design. + + if (mDefaultsCheckbox && !mPopulating) { + mDefaulted = false; + mDefaultsCheckbox->SetValue(false); + } +} + +void SpectrumPrefs::OnWindowSize(wxCommandEvent &evt) +{ + // Restrict choice of zero padding, so that product of window + // size and padding may not exceed the largest window size. wxChoice *const pWindowSizeControl = static_cast<wxChoice*>(wxWindow::FindWindowById(ID_WINDOW_SIZE, this)); - int windowSize = 1 << (pWindowSizeControl->GetSelection() + 3); + int windowSize = 1 << + (pWindowSizeControl->GetSelection() + SpectrogramSettings::LogMinWindowSize); PopulatePaddingChoices(windowSize); -} -BEGIN_EVENT_TABLE(SpectrumPrefs, PrefsPanel) - EVT_CHOICE(ID_WINDOW_SIZE, SpectrumPrefs::OnWindowSize) -END_EVENT_TABLE() + // Do the common part + OnControl(evt); +} -SpectrogramSettings::SpectrogramSettings() -: hFFT(0) -, window(0) +void SpectrumPrefs::OnDefaults(wxCommandEvent &) { - UpdatePrefs(); + if (mDefaultsCheckbox->IsChecked()) { + mTempSettings = SpectrogramSettings::defaults(); + mTempSettings.ConvertToEnumeratedWindowSizes(); + mDefaulted = true; + ShuttleGui S(this, eIsSettingToDialog); + PopulateOrExchange(S); + } } -SpectrogramSettings& SpectrogramSettings::defaults() +void SpectrumPrefs::OnAlgorithm(wxCommandEvent &evt) { - static SpectrogramSettings instance; - return instance; + EnableDisableSTFTOnlyControls(); + OnControl(evt); } -void SpectrogramSettings::UpdatePrefs() +void SpectrumPrefs::EnableDisableSTFTOnlyControls() { - 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; - } - + // Enable or disable other controls that are applicable only to STFT. + const bool STFT = (mAlgorithmChoice->GetSelection() == 0); + mGain->Enable(STFT); + mRange->Enable(STFT); + mFrequencyGain->Enable(STFT); #ifdef EXPERIMENTAL_ZERO_PADDED_SPECTROGRAMS - const int newZeroPaddingFactor = gPrefs->Read(wxT("/Spectrum/ZeroPaddingFactor"), 1); - if (newZeroPaddingFactor != zeroPaddingFactor) { - destroy = true; - zeroPaddingFactor = newZeroPaddingFactor; - } + mZeroPaddingChoiceCtrl->Enable(STFT); #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() +void SpectrumPrefs::OnApply(wxCommandEvent &) { - DestroyWindows(); -} - -void SpectrogramSettings::DestroyWindows() -{ -#ifdef EXPERIMENTAL_USE_REALFFTF - if (hFFT != NULL) { - EndFFT(hFFT); - hFFT = NULL; + if (Validate()) { + Apply(); + ::GetActiveProject()->GetTrackPanel()->Refresh(false); } - if (window != NULL) { - delete[] window; - window = NULL; - } -#endif } +BEGIN_EVENT_TABLE(SpectrumPrefs, PrefsPanel) + EVT_CHOICE(ID_WINDOW_SIZE, SpectrumPrefs::OnWindowSize) + EVT_CHECKBOX(ID_DEFAULTS, SpectrumPrefs::OnDefaults) + EVT_CHOICE(ID_ALGORITHM, SpectrumPrefs::OnAlgorithm) + + // Several controls with common routine that unchecks the default box + EVT_CHOICE(ID_WINDOW_TYPE, SpectrumPrefs::OnControl) + EVT_CHOICE(ID_PADDING_SIZE, SpectrumPrefs::OnControl) + EVT_CHOICE(ID_SCALE, SpectrumPrefs::OnControl) + EVT_TEXT(ID_MINIMUM, SpectrumPrefs::OnControl) + EVT_TEXT(ID_MAXIMUM, SpectrumPrefs::OnControl) + EVT_TEXT(ID_GAIN, SpectrumPrefs::OnControl) + EVT_TEXT(ID_RANGE, SpectrumPrefs::OnControl) + EVT_TEXT(ID_FREQUENCY_GAIN, SpectrumPrefs::OnControl) + EVT_CHECKBOX(ID_GRAYSCALE, SpectrumPrefs::OnControl) + EVT_CHECKBOX(ID_SPECTRAL_SELECTION, SpectrumPrefs::OnControl) + + EVT_BUTTON(ID_APPLY, SpectrumPrefs::OnApply) + +END_EVENT_TABLE() -namespace +SpectrumPrefsFactory::SpectrumPrefsFactory(WaveTrack *wt) +: mWt(wt) { - 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 +PrefsPanel *SpectrumPrefsFactory::Create(wxWindow *parent) { -#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 + return new SpectrumPrefs(parent, mWt); } diff --git a/src/prefs/SpectrumPrefs.h b/src/prefs/SpectrumPrefs.h index 20a1e7385d0fe7453c235fa1f251638d21195da9..84feb2869e95b87f5e0137522b8c368f72e51718 100644 --- a/src/prefs/SpectrumPrefs.h +++ b/src/prefs/SpectrumPrefs.h @@ -28,15 +28,20 @@ #include "../Experimental.h" #include "PrefsPanel.h" +#include "SpectrogramSettings.h" +class wxChoice; +class wxCheckBox; class wxTextCtrl; struct FFTParam; class ShuttleGui; +class SpectrogramSettings; +class WaveTrack; class SpectrumPrefs:public PrefsPanel { public: - SpectrumPrefs(wxWindow * parent); + SpectrumPrefs(wxWindow * parent, WaveTrack *wt); virtual ~SpectrumPrefs(); virtual bool Apply(); virtual bool Validate(); @@ -46,9 +51,18 @@ class SpectrumPrefs:public PrefsPanel void PopulatePaddingChoices(int windowSize); void PopulateOrExchange(ShuttleGui & S); + void OnControl(wxCommandEvent &event); void OnWindowSize(wxCommandEvent &event); + void OnDefaults(wxCommandEvent&); + void OnAlgorithm(wxCommandEvent &); + void OnApply(wxCommandEvent &); DECLARE_EVENT_TABLE() + void EnableDisableSTFTOnlyControls(); + + WaveTrack *const mWt; + bool mDefaulted; + wxTextCtrl *mMinFreq; wxTextCtrl *mMaxFreq; wxTextCtrl *mGain; @@ -56,72 +70,39 @@ class SpectrumPrefs:public PrefsPanel wxTextCtrl *mFrequencyGain; wxArrayString mSizeChoices; - wxArrayInt mSizeCodes; #ifdef EXPERIMENTAL_ZERO_PADDED_SPECTROGRAMS int mZeroPaddingChoice; + wxChoice *mZeroPaddingChoiceCtrl; wxArrayString mZeroPaddingChoices; - wxArrayInt mZeroPaddingCodes; #endif wxArrayString mTypeChoices; - wxArrayInt mTypeCodes; + wxArrayString mScaleChoices; + + wxChoice *mAlgorithmChoice; + wxArrayString mAlgorithmChoices; #ifdef EXPERIMENTAL_FIND_NOTES wxTextCtrl *mFindNotesMinA; wxTextCtrl *mFindNotesN; #endif -}; - - -class SpectrogramSettings -{ -public: - static SpectrogramSettings &defaults(); - SpectrogramSettings(); - ~SpectrogramSettings(); - - void UpdatePrefs(); - void DestroyWindows(); - void CacheWindows() const; - - int minFreq; - int maxFreq; - int logMinFreq; - int logMaxFreq; + wxCheckBox *mDefaultsCheckbox; - int range; - int gain; - int frequencyGain; + SpectrogramSettings mTempSettings; - int windowType; - int windowSize; -#ifdef EXPERIMENTAL_ZERO_PADDED_SPECTROGRAMS - int zeroPaddingFactor; -#endif - - bool isGrayscale; + bool mPopulating; +}; -#ifdef EXPERIMENTAL_FFT_Y_GRID - bool fftYGrid; -#endif //EXPERIMENTAL_FFT_Y_GRID +class SpectrumPrefsFactory : public PrefsPanelFactory +{ +public: + explicit SpectrumPrefsFactory(WaveTrack *wt = 0); + virtual PrefsPanel *Create(wxWindow *parent); -#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 +private: + WaveTrack *const mWt; }; - #endif diff --git a/src/prefs/ThemePrefs.cpp b/src/prefs/ThemePrefs.cpp index 2cbfd7ba3c109ce741d15049add6bd1b2e9af69a..f6d947b3ed493b3dcf9b508eb950c37b3f7c393f 100644 --- a/src/prefs/ThemePrefs.cpp +++ b/src/prefs/ThemePrefs.cpp @@ -205,3 +205,8 @@ bool ThemePrefs::Apply() return true; } + +PrefsPanel *ThemePrefsFactory::Create(wxWindow *parent) +{ + return new ThemePrefs(parent); +} diff --git a/src/prefs/ThemePrefs.h b/src/prefs/ThemePrefs.h index 40d080c8cf43cb18ce2c5215aa1ca21254e82db0..7668289d0d92af39b2bf1e2ffce3d46c40d092ea 100644 --- a/src/prefs/ThemePrefs.h +++ b/src/prefs/ThemePrefs.h @@ -41,4 +41,9 @@ class ThemePrefs :public PrefsPanel DECLARE_EVENT_TABLE(); }; +class ThemePrefsFactory : public PrefsPanelFactory +{ +public: + virtual PrefsPanel *Create(wxWindow *parent); +}; #endif diff --git a/src/prefs/TracksPrefs.cpp b/src/prefs/TracksPrefs.cpp index f94a322225a8c5e8772da6f63c29b26785714f20..495fc7ad40efa5c06b5b6c01c8c547b91e2e78e6 100644 --- a/src/prefs/TracksPrefs.cpp +++ b/src/prefs/TracksPrefs.cpp @@ -60,25 +60,10 @@ void TracksPrefs::Populate() // we don't display them by increasing integer values. mViewChoices.Add(_("Waveform")); - mViewCodes.Add(int(WaveTrack::WaveformDisplay)); + mViewCodes.Add(int(WaveTrack::Waveform)); - mViewChoices.Add(_("Waveform (dB)")); - mViewCodes.Add(int(WaveTrack::WaveformDBDisplay)); - - mViewChoices.Add(_("Spectrogram")); - mViewCodes.Add(int(WaveTrack::SpectrumDisplay)); - - mViewChoices.Add(_("Spectrogram log(f)")); - mViewCodes.Add(int(WaveTrack::SpectrumLogDisplay)); - - mViewChoices.Add(_("Spectral Selection")); - mViewCodes.Add(int(WaveTrack::SpectralSelectionDisplay)); - - mViewChoices.Add(_("Spectral Selection log(f)")); - mViewCodes.Add(int(WaveTrack::SpectralSelectionLogDisplay)); - - mViewChoices.Add(_("Pitch (EAC)")); - mViewCodes.Add(int(WaveTrack::PitchDisplay)); + mViewChoices.Add(_("Spectrum")); + mViewCodes.Add(WaveTrack::Spectrum); //------------------------- Main section -------------------- // Now construct the GUI itself. @@ -165,3 +150,8 @@ bool TracksPrefs::Apply() return true; } + +PrefsPanel *TracksPrefsFactory::Create(wxWindow *parent) +{ + return new TracksPrefs(parent); +} diff --git a/src/prefs/TracksPrefs.h b/src/prefs/TracksPrefs.h index aa0f54272e68a975812813f0f50a7a2d1a9bec58..be1baeaa0f56e13592c4690a0c9b3ef609540580 100644 --- a/src/prefs/TracksPrefs.h +++ b/src/prefs/TracksPrefs.h @@ -39,4 +39,9 @@ class TracksPrefs :public PrefsPanel wxArrayString mViewChoices; }; +class TracksPrefsFactory : public PrefsPanelFactory +{ +public: + virtual PrefsPanel *Create(wxWindow *parent); +}; #endif diff --git a/src/prefs/WarningsPrefs.cpp b/src/prefs/WarningsPrefs.cpp index 68d344593b32de661b55f275b76d2624b72ae413..c0cb5b47b5d4b9e1dc129f25314e52aa95b739f6 100644 --- a/src/prefs/WarningsPrefs.cpp +++ b/src/prefs/WarningsPrefs.cpp @@ -83,3 +83,8 @@ bool WarningsPrefs::Apply() return true; } + +PrefsPanel *WarningsPrefsFactory::Create(wxWindow *parent) +{ + return new WarningsPrefs(parent); +} diff --git a/src/prefs/WarningsPrefs.h b/src/prefs/WarningsPrefs.h index 8f789e163507fa37c7025aaefdde3fc56b4a670d..97e9605b6a65e53480917b37d457a37846267115 100644 --- a/src/prefs/WarningsPrefs.h +++ b/src/prefs/WarningsPrefs.h @@ -33,4 +33,9 @@ class WarningsPrefs :public PrefsPanel void PopulateOrExchange(ShuttleGui & S); }; +class WarningsPrefsFactory : public PrefsPanelFactory +{ +public: + virtual PrefsPanel *Create(wxWindow *parent); +}; #endif diff --git a/src/prefs/WaveformPrefs.cpp b/src/prefs/WaveformPrefs.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b29468947f5189e8b269bb21abbb6dd6a84d38c0 --- /dev/null +++ b/src/prefs/WaveformPrefs.cpp @@ -0,0 +1,215 @@ +/********************************************************************** + +Audacity: A Digital Audio Editor + +WaveformPrefs.cpp + +Paul Licameli + +*******************************************************************//** + +\class WaveformPrefs +\brief A PrefsPanel for spectrum settings. + +*//*******************************************************************/ + +#include "../Audacity.h" +#include "WaveformPrefs.h" + +#include <wx/checkbox.h> + +#include "../Project.h" +#include "../TrackPanel.h" +#include "../ShuttleGui.h" +#include "../WaveTrack.h" + +WaveformPrefs::WaveformPrefs(wxWindow * parent, WaveTrack *wt) +: PrefsPanel(parent, _("Waveforms")) +, mWt(wt) +, mPopulating(false) +{ + if (mWt) { + WaveformSettings &settings = wt->GetWaveformSettings(); + mDefaulted = (&WaveformSettings::defaults() == &settings); + mTempSettings = settings; + } + else { + mTempSettings = WaveformSettings::defaults(); + mDefaulted = false; + } + + Populate(); +} + +WaveformPrefs::~WaveformPrefs() +{ +} + +enum { + ID_DEFAULTS = 10001, + ID_APPLY, + + ID_SCALE, +}; + +void WaveformPrefs::Populate() +{ + mScaleChoices = WaveformSettings::GetScaleNames(); + + //------------------------- Main section -------------------- + // Now construct the GUI itself. + ShuttleGui S(this, eIsCreating); + PopulateOrExchange(S); + // ----------------------- End of main section -------------- +} + +void WaveformPrefs::PopulateOrExchange(ShuttleGui & S) +{ + mPopulating = true; + + S.SetBorder(2); + + // S.StartStatic(_("Track Settings")); + { + mDefaultsCheckbox = 0; + if (mWt) { + mDefaultsCheckbox = S.Id(ID_DEFAULTS).TieCheckBox(_("Defaults"), mDefaulted); + } + + S.StartStatic(_("Display")); + { + S.StartTwoColumn(); + { + S.Id(ID_SCALE).TieChoice(_("S&cale") + wxString(wxT(":")), + *(int*)&mTempSettings.scaleType, + &mScaleChoices); + } + S.EndTwoColumn(); + } + S.EndStatic(); + } + // S.EndStatic(); + + /* + S.StartStatic(_("Global settings")); + { + } + S.EndStatic(); + */ + + S.StartMultiColumn(2, wxALIGN_RIGHT); + { + S.Id(ID_APPLY).AddButton(_("Appl&y")); + } + S.EndMultiColumn(); + + mPopulating = false; +} + +bool WaveformPrefs::Validate() +{ + // Do checking for whole numbers + + // ToDo: use wxIntegerValidator<unsigned> when available + + ShuttleGui S(this, eIsGettingFromDialog); + PopulateOrExchange(S); + + // Delegate range checking to WaveformSettings class + const bool result = mTempSettings.Validate(false); + return result; +} + +bool WaveformPrefs::Apply() +{ + const bool isOpenPage = this->IsShown(); + + WaveTrack *const partner = + mWt ? static_cast<WaveTrack*>(mWt->GetLink()) : 0; + + ShuttleGui S(this, eIsGettingFromDialog); + PopulateOrExchange(S); + + WaveformSettings::Globals::Get().SavePrefs(); + + if (mWt) { + if (mDefaulted) { + mWt->SetWaveformSettings(NULL); + if (partner) + partner->SetWaveformSettings(NULL); + } + else { + WaveformSettings *pSettings = + &mWt->GetIndependentWaveformSettings(); + *pSettings = mTempSettings; + if (partner) { + pSettings = &partner->GetIndependentWaveformSettings(); + *pSettings = mTempSettings; + } + } + } + + if (!mWt || mDefaulted) { + WaveformSettings *const pSettings = + &WaveformSettings::defaults(); + *pSettings = mTempSettings; + pSettings->SavePrefs(); + } + + if (mWt && isOpenPage) { + mWt->SetDisplay(WaveTrack::Waveform); + if (partner) + partner->SetDisplay(WaveTrack::Waveform); + } + + return true; +} + +void WaveformPrefs::OnControl(wxCommandEvent&) +{ + // Common routine for most controls + // If any per-track setting is changed, break the association with defaults + // Skip this, and View Settings... will be able to change defaults instead + // when the checkbox is on, as in the original design. + + if (mDefaultsCheckbox && !mPopulating) { + mDefaulted = false; + mDefaultsCheckbox->SetValue(false); + } +} + +void WaveformPrefs::OnDefaults(wxCommandEvent &) +{ + if (mDefaultsCheckbox->IsChecked()) { + mTempSettings = WaveformSettings::defaults(); + mDefaulted = true; + ShuttleGui S(this, eIsSettingToDialog); + PopulateOrExchange(S); + } +} + +void WaveformPrefs::OnApply(wxCommandEvent &) +{ + if (Validate()) { + Apply(); + ::GetActiveProject()->GetTrackPanel()->Refresh(false); + } +} + +BEGIN_EVENT_TABLE(WaveformPrefs, PrefsPanel) + +EVT_CHOICE(ID_SCALE, WaveformPrefs::OnControl) + +EVT_CHECKBOX(ID_DEFAULTS, WaveformPrefs::OnDefaults) +EVT_BUTTON(ID_APPLY, WaveformPrefs::OnApply) +END_EVENT_TABLE() + +WaveformPrefsFactory::WaveformPrefsFactory(WaveTrack *wt) +: mWt(wt) +{ +} + +PrefsPanel *WaveformPrefsFactory::Create(wxWindow *parent) +{ + return new WaveformPrefs(parent, mWt); +} diff --git a/src/prefs/WaveformPrefs.h b/src/prefs/WaveformPrefs.h new file mode 100644 index 0000000000000000000000000000000000000000..9d119c1c63ef54d9beeaf79987390064efd2cfbc --- /dev/null +++ b/src/prefs/WaveformPrefs.h @@ -0,0 +1,60 @@ +/********************************************************************** + +Audacity: A Digital Audio Editor + +WaveformPrefs.h + +Paul Licameli + +**********************************************************************/ + + +#ifndef __AUDACITY_WAVEFORM_PREFS__ +#define __AUDACITY_WAVEFORM_PREFS__ + +#include "PrefsPanel.h" +#include "WaveformSettings.h" + +class ShuttleGui; +class WaveTrack; +class wxCheckBox; + +class WaveformPrefs :public PrefsPanel +{ +public: + WaveformPrefs(wxWindow * parent, WaveTrack *wt); + virtual ~WaveformPrefs(); + virtual bool Apply(); + virtual bool Validate(); + +private: + void Populate(); + void PopulateOrExchange(ShuttleGui & S); + + void OnControl(wxCommandEvent&); + void OnDefaults(wxCommandEvent&); + void OnApply(wxCommandEvent &); + DECLARE_EVENT_TABLE() + + WaveTrack *const mWt; + bool mDefaulted; + + wxCheckBox *mDefaultsCheckbox; + + wxArrayString mScaleChoices; + + WaveformSettings mTempSettings; + + bool mPopulating; +}; + +class WaveformPrefsFactory : public PrefsPanelFactory +{ +public: + explicit WaveformPrefsFactory(WaveTrack *wt = 0); + virtual PrefsPanel *Create(wxWindow *parent); + +private: + WaveTrack *const mWt; +}; +#endif diff --git a/src/prefs/WaveformSettings.cpp b/src/prefs/WaveformSettings.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3aa15f4bfde032534a0f136d0f10723855efc335 --- /dev/null +++ b/src/prefs/WaveformSettings.cpp @@ -0,0 +1,129 @@ +/********************************************************************** + +Audacity: A Digital Audio Editor + +WaveformSettings.cpp + +Paul Licameli + +*******************************************************************//** + +\class WaveformSettings +\brief Waveform settings, either for one track or as defaults. + +*//*******************************************************************/ + +#include "../Audacity.h" +#include "WaveformSettings.h" + +#include <algorithm> +#include <wx/intl.h> + +#include "../Prefs.h" + +WaveformSettings::Globals::Globals() +{ + LoadPrefs(); +} + +void WaveformSettings::Globals::SavePrefs() +{ +} + +void WaveformSettings::Globals::LoadPrefs() +{ +} + +WaveformSettings::Globals +&WaveformSettings::Globals::Get() +{ + static Globals instance; + return instance; +} + +WaveformSettings::WaveformSettings() +{ + LoadPrefs(); +} + +WaveformSettings::WaveformSettings(const WaveformSettings &other) + : scaleType(other.scaleType) +{ +} + +WaveformSettings &WaveformSettings::operator= (const WaveformSettings &other) +{ + if (this != &other) { + scaleType = other.scaleType; + } + return *this; +} + +WaveformSettings& WaveformSettings::defaults() +{ + static WaveformSettings instance; + return instance; +} + +bool WaveformSettings::Validate(bool quiet) +{ + quiet; + + scaleType = ScaleType( + std::max(0, std::min(int(stNumScaleTypes) - 1, int(scaleType))) + ); + + return true; +} + +void WaveformSettings::LoadPrefs() +{ + scaleType = ScaleType(gPrefs->Read(wxT("/Waveform/ScaleType"), 0L)); + + // Enforce legal values + Validate(true); + + Update(); +} + +void WaveformSettings::SavePrefs() +{ + gPrefs->Write(wxT("/Waveform/ScaleType"), long(scaleType)); +} + +void WaveformSettings::Update() +{ +} + +namespace +{ + wxArrayString &scaleNamesArray() + { + static wxArrayString theArray; + return theArray; + } +} + +//static +void WaveformSettings::InvalidateNames() +{ + scaleNamesArray().Clear(); +} + +//static +const wxArrayString &WaveformSettings::GetScaleNames() +{ + wxArrayString &theArray = scaleNamesArray(); + + if (theArray.IsEmpty()) { + // Keep in correspondence with enum WaveTrack::WaveTrackDisplay: + theArray.Add(_("Linear")); + theArray.Add(_("Logarithmic")); + } + + return theArray; +} + +WaveformSettings::~WaveformSettings() +{ +} diff --git a/src/prefs/WaveformSettings.h b/src/prefs/WaveformSettings.h new file mode 100644 index 0000000000000000000000000000000000000000..a62243aa3a358ec6af69733cba2241978826474e --- /dev/null +++ b/src/prefs/WaveformSettings.h @@ -0,0 +1,63 @@ +/********************************************************************** + +Audacity: A Digital Audio Editor + +WaveformSettings.h + +Paul Licameli + +**********************************************************************/ + +#ifndef __AUDACITY_WAVEFORM_SETTINGS__ +#define __AUDACITY_WAVEFORM_SETTINGS__ + +class wxArrayString; + +class WaveformSettings +{ +public: + + // Singleton for settings that are not per-track + class Globals + { + public: + static Globals &Get(); + void SavePrefs(); + + private: + Globals(); + void LoadPrefs(); + }; + + static WaveformSettings &defaults(); + WaveformSettings(); + WaveformSettings(const WaveformSettings &other); + WaveformSettings& operator= (const WaveformSettings &other); + ~WaveformSettings(); + + bool IsDefault() const + { + return this == &defaults(); + } + + bool Validate(bool quiet); + void LoadPrefs(); + void SavePrefs(); + void Update(); + + enum ScaleType { + stLinear, + stLogarithmic, + + stNumScaleTypes, + }; + + static void InvalidateNames(); // in case of language change + static const wxArrayString &GetScaleNames(); + + ScaleType scaleType; + + // Convenience + bool isLinear() const { return stLinear == scaleType; } +}; +#endif diff --git a/src/toolbars/ControlToolBar.cpp b/src/toolbars/ControlToolBar.cpp index c3abd8646a9dec98f1bfd0b3bd67c5de03cc9bf3..8a856a3c9e64d5caa1cee3c89d701d4bfac416ec 100644 --- a/src/toolbars/ControlToolBar.cpp +++ b/src/toolbars/ControlToolBar.cpp @@ -36,6 +36,7 @@ #include "../Audacity.h" #include "../Experimental.h" +#include "ControlToolBar.h" // For compilers that support precompilation, includes "wx/wx.h". #include <wx/wxprec.h> @@ -51,7 +52,6 @@ #endif #include <wx/tooltip.h> -#include "ControlToolBar.h" #include "TranscriptionToolBar.h" #include "MeterToolBar.h" @@ -62,7 +62,7 @@ #include "../Prefs.h" #include "../Project.h" #include "../Theme.h" -#include "../Track.h" +#include "../WaveTrack.h" #include "../widgets/AButton.h" #include "../widgets/Meter.h" diff --git a/src/toolbars/EditToolBar.cpp b/src/toolbars/EditToolBar.cpp index 16237ed01948d59891b88e198205854c9488b0e3..9a77732b5edb134025228cadec0e179858508f21 100644 --- a/src/toolbars/EditToolBar.cpp +++ b/src/toolbars/EditToolBar.cpp @@ -52,6 +52,7 @@ #include "../Prefs.h" #include "../Project.h" #include "../Theme.h" +#include "../Track.h" #include "../UndoManager.h" #include "../widgets/AButton.h" diff --git a/src/toolbars/SpectralSelectionBar.cpp b/src/toolbars/SpectralSelectionBar.cpp index ae6167e44342542389ee5bf4e2f8fe8b2899ae17..fb443452c71a54e3ea6a97ec8f9ecee4059940d6 100644 --- a/src/toolbars/SpectralSelectionBar.cpp +++ b/src/toolbars/SpectralSelectionBar.cpp @@ -158,12 +158,14 @@ void SpectralSelectionBar::Populate() mLowCtrl = new NumericTextCtrl( NumericConverter::FREQUENCY, this, OnLowID, frequencyFormatName, 0.0); + mLowCtrl->SetInvalidValue(SelectedRegion::UndefinedFrequency); mLowCtrl->SetName(_("Low Frequency:")); mLowCtrl->EnableMenu(); subSizer->Add(mLowCtrl, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 5); mHighCtrl = new NumericTextCtrl( NumericConverter::FREQUENCY, this, OnHighID, frequencyFormatName, 0.0); + mHighCtrl->SetInvalidValue(SelectedRegion::UndefinedFrequency); mHighCtrl->SetName(wxString(_("High Frequency:"))); mHighCtrl->EnableMenu(); subSizer->Add(mHighCtrl, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 0); @@ -265,6 +267,10 @@ void SpectralSelectionBar::ModifySpectralSelection(bool done) top = SelectedRegion::UndefinedFrequency; } + mLow = bottom; + mHigh = top; + SetBounds(); + // Notify project and track panel, which may change // the values again, and call back to us in SetFrequencies() mListener->SSBL_ModifySpectralSelection(bottom, top, done); @@ -349,11 +355,25 @@ void SpectralSelectionBar::ValuesToControls() mWidthCtrl->SetValue(mWidth); } else { + SetBounds(); mLowCtrl->SetValue(mLow); mHighCtrl->SetValue(mHigh); } } +void SpectralSelectionBar::SetBounds() +{ + if (mHigh >= 0) + mLowCtrl->SetMaxValue(mHigh); + else + mLowCtrl->ResetMaxValue(); + + if (mLow >= 0) + mHighCtrl->SetMinValue(mLow); + else + mHighCtrl->ResetMinValue(); +} + void SpectralSelectionBar::SetFrequencies(double bottom, double top) { mLow = bottom; diff --git a/src/toolbars/SpectralSelectionBar.h b/src/toolbars/SpectralSelectionBar.h index 953d13045ead20a97a3308e327b5267481e1d211..4bdd0fbf11ef5723aae81ca4596d9c276368c610 100644 --- a/src/toolbars/SpectralSelectionBar.h +++ b/src/toolbars/SpectralSelectionBar.h @@ -49,6 +49,7 @@ public: private: void ValuesToControls(); + void SetBounds(); void OnUpdate(wxCommandEvent &evt); void OnCtrl(wxCommandEvent &evt); void OnChoice(wxCommandEvent &evt); diff --git a/src/toolbars/TranscriptionToolBar.cpp b/src/toolbars/TranscriptionToolBar.cpp index 31c7ab0f3620bce31a99c4714d5fb6522a9a95b5..b520b14ffaed4d075c4ade8ab27114a027d418ce 100644 --- a/src/toolbars/TranscriptionToolBar.cpp +++ b/src/toolbars/TranscriptionToolBar.cpp @@ -15,6 +15,7 @@ *//*******************************************************************/ #include "../Audacity.h" +#include "TranscriptionToolBar.h" // For compilers that support precompilation, includes "wx/wx.h". #include <wx/wxprec.h> @@ -28,7 +29,6 @@ #endif // WX_PRECOMP #include "../Envelope.h" -#include "TranscriptionToolBar.h" #include "ControlToolBar.h" #include "../AudacityApp.h" diff --git a/src/toolbars/TranscriptionToolBar.h b/src/toolbars/TranscriptionToolBar.h index 2ca08bf76b4aa758d6c0213608d3fb77a45ae0aa..8ae652694284dca40ee8f1638627ae2bf9b633c6 100644 --- a/src/toolbars/TranscriptionToolBar.h +++ b/src/toolbars/TranscriptionToolBar.h @@ -18,7 +18,7 @@ #include <wx/brush.h> #include <wx/pen.h> -#include "../Sequence.h" +#include "audacity/Types.h" #include "../Theme.h" class wxBitmap; @@ -95,6 +95,15 @@ class TranscriptionToolBar:public ToolBar { virtual void OnMakeLabel(wxCommandEvent & event); virtual void OnAutomateSelection(wxCommandEvent & event); virtual void OnSensitivitySlider(wxCommandEvent & event); + + virtual void Populate(); + virtual void Repaint(wxDC * WXUNUSED(dc)) {} + virtual void EnableDisableButtons(); + virtual void UpdatePrefs(); + + void OnFocus(wxFocusEvent &event); + void OnCaptureKey(wxCommandEvent &event); + virtual double GetSensitivity(); virtual void SetKeyType(wxCommandEvent & event); #endif diff --git a/src/widgets/ASlider.cpp b/src/widgets/ASlider.cpp index 10caa3d0201163070a54bf01a8ffe4ae977cf4e9..fb107a69ba39e9dfd304f603df8d5761e3164a00 100644 --- a/src/widgets/ASlider.cpp +++ b/src/widgets/ASlider.cpp @@ -217,7 +217,7 @@ bool SliderDialog::TransferDataFromWindow() mTextCtrl->GetValue().ToDouble(&value); if (mStyle == DB_SLIDER) - value = pow(10.0, value / 20.0); + value = DB_TO_LINEAR(value); mSlider->Set(value); return true; @@ -1231,7 +1231,7 @@ float LWSlider::DragPositionToValue(int fromPos, bool shiftDown) float LWSlider::Get( bool convert ) { if (mStyle == DB_SLIDER) - return ( convert ? pow(10.0f, mCurrentValue / 20.0f) : mCurrentValue ); + return (convert ? DB_TO_LINEAR(mCurrentValue) : mCurrentValue); else return mCurrentValue; } @@ -1241,7 +1241,7 @@ void LWSlider::Set(float value) if (mIsDragging) return; if (mStyle == DB_SLIDER) - mCurrentValue = 20.0f*log10(value); + mCurrentValue = LINEAR_TO_DB(value); else mCurrentValue = value; diff --git a/src/widgets/Meter.cpp b/src/widgets/Meter.cpp index fabc0cba82b965fc79570097b56b52288b1b2d8f..18aee1f51c21b20134dbe059805f932e877fd934 100644 --- a/src/widgets/Meter.cpp +++ b/src/widgets/Meter.cpp @@ -61,6 +61,7 @@ #include "../AudioIO.h" #include "../AColor.h" #include "../ImageManipulation.h" +#include "../prefs/GUISettings.h" #include "../Project.h" #include "../toolbars/MeterToolBar.h" #include "../toolbars/ControlToolBar.h" @@ -366,7 +367,7 @@ Meter::~Meter() void Meter::UpdatePrefs() { - mDBRange = gPrefs->Read(wxT("/GUI/EnvdBRange"), ENV_DB_RANGE); + mDBRange = gPrefs->Read(ENV_DB_KEY, ENV_DB_RANGE); mMeterRefreshRate = gPrefs->Read(Key(wxT("RefreshRate")), 30); mGradient = gPrefs->Read(Key(wxT("Bars")), wxT("Gradient")) == wxT("Gradient"); @@ -864,7 +865,7 @@ static float ToDB(float v, float range) { double db; if (v > 0) - db = 20 * log10(fabs(v)); + db = LINEAR_TO_DB(fabs(v)); else db = -999; return ClipZeroToOne((db + range) / range); @@ -995,7 +996,7 @@ void Meter::OnMeterUpdate(wxTimerEvent & WXUNUSED(event)) } else { double decayAmount = mDecayRate * deltaT; - double decayFactor = pow(10.0, -decayAmount/20); + double decayFactor = DB_TO_LINEAR(-decayAmount); mBar[j].peak = floatMax(msg.peak[j], mBar[j].peak * decayFactor); } diff --git a/src/widgets/Meter.h b/src/widgets/Meter.h index c97e0a0116411150fab0773e1310dfa4a5fd5f89..55bfd7fa2b8737383a94ed0dc78b0d0fe6389574 100644 --- a/src/widgets/Meter.h +++ b/src/widgets/Meter.h @@ -21,7 +21,6 @@ #include <wx/timer.h> #include "../SampleFormat.h" -#include "../Sequence.h" #include "Ruler.h" // Event used to notify all meters of preference changes @@ -57,8 +56,8 @@ class MeterUpdateMsg int tailPeakCount[kMaxMeterBars]; /* neither constructor nor destructor do anything */ - MeterUpdateMsg() { }; - ~MeterUpdateMsg() { }; + MeterUpdateMsg() { } + ~MeterUpdateMsg() { } /* for debugging purposes, printing the values out is really handy */ /** \brief Print out all the values in the meter update message */ wxString toString(); diff --git a/src/widgets/NumericTextCtrl.cpp b/src/widgets/NumericTextCtrl.cpp index 73bab1830bed1e0c5688a91c0039db4d5a62514b..181528e7a49c2f85d8843f7e066f4047c49f2e4f 100644 --- a/src/widgets/NumericTextCtrl.cpp +++ b/src/widgets/NumericTextCtrl.cpp @@ -167,7 +167,8 @@ different formats. #include "../Audacity.h" #include "NumericTextCtrl.h" -#include "../Sequence.h" // for sampleCount +#include "audacity/Types.h" +#include "../AudacityApp.h" #include "../Theme.h" #include "../AllThemeResources.h" #include "../AColor.h" @@ -175,6 +176,7 @@ different formats. #include <algorithm> #include <math.h> +#include <limits> #include <wx/wx.h> #include <wx/dcmemory.h> @@ -531,6 +533,10 @@ NumericConverter::NumericConverter(Type type, double value, double sampleRate) { + ResetMinValue(); + ResetMaxValue(); + mInvalidValue = -1.0; + mDefaultNdx = 0; mType = type; @@ -863,7 +869,7 @@ void NumericConverter::ControlsToValue() if (mFields.GetCount() > 0 && mValueString.Mid(mFields[0].pos, 1) == wxChar('-')) { - mValue = -1; + mValue = mInvalidValue; return; } @@ -904,7 +910,7 @@ void NumericConverter::ControlsToValue() t = frames * 1.001 / 30.; } - mValue = t; + mValue = std::max(mMinValue, std::min(mMaxValue, t)); } void NumericConverter::SetFormatName(const wxString & formatName) @@ -935,6 +941,35 @@ void NumericConverter::SetValue(double newValue) ControlsToValue(); } +void NumericConverter::SetMinValue(double minValue) +{ + mMinValue = minValue; + if (mMaxValue < minValue) + mMaxValue = minValue; + if (mValue < minValue) + SetValue(minValue); +} + +void NumericConverter::ResetMinValue() +{ + mMinValue = std::numeric_limits<double>::min(); +} + +void NumericConverter::SetMaxValue(double maxValue) +{ + mMaxValue = maxValue; + if (mMinValue > maxValue) { + mMinValue = maxValue; + } + if (mValue > maxValue) + SetValue(maxValue); +} + +void NumericConverter::ResetMaxValue() +{ + mMaxValue = std::numeric_limits<double>::max(); +} + double NumericConverter::GetValue() { ControlsToValue(); @@ -1079,6 +1114,8 @@ void NumericConverter::Adjust(int steps, int dir) mValue = 0.; } + mValue = std::max(mMinValue, std::min(mMaxValue, mValue)); + mValue /= mScalingFactor; if (!mNtscDrop) @@ -1141,6 +1178,7 @@ NumericTextCtrl::NumericTextCtrl(NumericConverter::Type type, mAutoPos(autoPos) , mType(type) { + mAllowInvalidValue = false; mDigitBoxW = 10; mDigitBoxH = 16; @@ -1179,6 +1217,7 @@ NumericTextCtrl::~NumericTextCtrl() // Set the focus to the first (left-most) non-zero digit // If all digits are zero, the right-most position is focused +// If all digits are hyphens (invalid), the left-most position is focused void NumericTextCtrl::UpdateAutoFocus() { if (!mAutoPos) @@ -1248,6 +1287,15 @@ void NumericTextCtrl::EnableMenu(bool enable) Fit(); } +void NumericTextCtrl::SetInvalidValue(double invalidValue) +{ + const bool wasInvalid = mAllowInvalidValue && (mValue == mInvalidValue); + mAllowInvalidValue = true; + mInvalidValue = invalidValue; + if (wasInvalid) + SetValue(invalidValue); +} + bool NumericTextCtrl::Layout() { unsigned int i, j; @@ -1564,6 +1612,7 @@ void NumericTextCtrl::OnCaptureKey(wxCommandEvent &event) case WXK_TAB: case WXK_RETURN: case WXK_NUMPAD_ENTER: + case '-': return; default: @@ -1586,6 +1635,7 @@ void NumericTextCtrl::OnKeyUp(wxKeyEvent &event) keyCode -= WXK_NUMPAD0 - '0'; if ((keyCode >= '0' && keyCode <= '9') || + (keyCode == '-') || (keyCode == WXK_BACK) || (keyCode == WXK_UP) || (keyCode == WXK_DOWN)) { @@ -1618,7 +1668,7 @@ void NumericTextCtrl::OnKeyDown(wxKeyEvent &event) if (!mReadOnly && (keyCode >= '0' && keyCode <= '9')) { int digitPosition = mDigits[mFocusedDigit].pos; if (mValueString[digitPosition] == wxChar('-')) { - mValue = 0; + mValue = std::max(mMinValue, std::min(mMaxValue, 0.0)); ValueToControls(); // Beware relocation of the string digitPosition = mDigits[mFocusedDigit].pos; @@ -1630,6 +1680,11 @@ void NumericTextCtrl::OnKeyDown(wxKeyEvent &event) Updated(); } + else if (!mReadOnly && keyCode == '-') { + if (mAllowInvalidValue) + SetValue(mInvalidValue); + } + else if (!mReadOnly && keyCode == WXK_BACK) { // Moves left, replaces that char with '0', stays there... mFocusedDigit--; diff --git a/src/widgets/NumericTextCtrl.h b/src/widgets/NumericTextCtrl.h index 631042e01c43b8ecaa532dd2cc0aaeaa957da7fd..be5c8d495775ffbbc5e1f80ff292cd071094ab47 100644 --- a/src/widgets/NumericTextCtrl.h +++ b/src/widgets/NumericTextCtrl.h @@ -23,6 +23,8 @@ #include <wx/string.h> #include <wx/textctrl.h> +#include "../Audacity.h" + #if wxUSE_ACCESSIBILITY #include <wx/access.h> #endif @@ -71,6 +73,11 @@ public: void SetFormatString(const wxString & formatString); void SetSampleRate(double sampleRate); void SetValue(double newValue); + void SetMinValue(double minValue); + void ResetMinValue(); + void SetMaxValue(double maxValue); + void ResetMaxValue(); + double GetValue(); wxString GetString(); @@ -95,6 +102,10 @@ protected: double mValue; + double mMinValue; + double mMaxValue; + double mInvalidValue; + wxString mFormatString; NumericFieldArray mFields; @@ -147,6 +158,12 @@ class NumericTextCtrl: public wxControl, public NumericConverter void SetReadOnly(bool readOnly = true); void EnableMenu(bool enable = true); + // The text control permits typing '-' to make the value invalid only if this + // function has previously been called. + // Maybe you want something other than the default of -1 to indicate the invalid value + // this control returns to the program, so you can specify. + void SetInvalidValue(double invalidValue); + int GetFocusedField() { return mLastField; } int GetFocusedDigit() { return mFocusedDigit; } @@ -200,6 +217,8 @@ private: NumericConverter::Type mType; + bool mAllowInvalidValue; + DECLARE_EVENT_TABLE() }; diff --git a/src/widgets/Ruler.cpp b/src/widgets/Ruler.cpp index 5ff2ce5d709ac1b4badc63d2f6adcf38d9b96007..11d4842107196f8deafff8ad2523fed7f2b79300 100644 --- a/src/widgets/Ruler.cpp +++ b/src/widgets/Ruler.cpp @@ -76,6 +76,7 @@ array of Ruler::Label. #include "../TimeTrack.h" #include "../TrackPanel.h" #include "../Menus.h" +#include "../NumberScale.h" #include "../Prefs.h" #include "../Snap.h" @@ -97,6 +98,7 @@ using std::max; // Ruler::Ruler() + : mpNumberScale(0) { mMin = mHiddenMin = 0.0; mMax = mHiddenMax = 100.0; @@ -180,6 +182,8 @@ Ruler::~Ruler() delete[] mMinorLabels; if (mMinorMinorLabels) delete[] mMinorMinorLabels; + + delete mpNumberScale; } void Ruler::SetTwoTone(bool twoTone) @@ -324,6 +328,23 @@ void Ruler::SetFonts(const wxFont &minorFont, const wxFont &majorFont, const wxF Invalidate(); } +void Ruler::SetNumberScale(const NumberScale *pScale) +{ + if (!pScale) { + if (mpNumberScale) { + delete mpNumberScale; + Invalidate(); + } + } + else { + if (!mpNumberScale || *mpNumberScale != *pScale) { + delete mpNumberScale; + mpNumberScale = new NumberScale(*pScale); + Invalidate(); + } + } +} + void Ruler::OfflimitsPixels(int start, int end) { int i; @@ -1170,13 +1191,17 @@ void Ruler::Update(TimeTrack* timetrack)// Envelope *speedEnv, long minSpeed, lo } else { // log case - mDigits=2; //TODO: implement dynamic digit computation + + NumberScale numberScale(mpNumberScale + ? *mpNumberScale + : NumberScale(nstLogarithmic, mMin, mMax, 1.0f) + ); + + mDigits=2; //TODO: implement dynamic digit computation double loLog = log10(mMin); double hiLog = log10(mMax); - double scale = mLength/(hiLog - loLog); int loDecade = (int) floor(loLog); - int pos; double val; double startDecade = pow(10., (double)loDecade); @@ -1184,12 +1209,12 @@ void Ruler::Update(TimeTrack* timetrack)// Envelope *speedEnv, long minSpeed, lo double decade = startDecade; double delta=hiLog-loLog, steps=fabs(delta); double step = delta>=0 ? 10 : 0.1; - double rMin=wxMin(mMin, mMax), rMax=wxMax(mMin, mMax); + double rMin=std::min(mMin, mMax), rMax=std::max(mMin, mMax); for(i=0; i<=steps; i++) { // if(i!=0) { val = decade; - if(val > rMin && val < rMax) { - pos = (int)(((log10(val) - loLog)*scale)+0.5); + if(val >= rMin && val < rMax) { + const int pos(0.5 + mLength * numberScale.ValueToPosition(val)); Tick(pos, val, true, false); } } @@ -1209,7 +1234,7 @@ void Ruler::Update(TimeTrack* timetrack)// Envelope *speedEnv, long minSpeed, lo for(j=start; j!=end; j+=mstep) { val = decade * j; if(val >= rMin && val < rMax) { - pos = (int)(((log10(val) - loLog)*scale)+0.5); + const int pos(0.5 + mLength * numberScale.ValueToPosition(val)); Tick(pos, val, false, true); } } @@ -1224,13 +1249,16 @@ void Ruler::Update(TimeTrack* timetrack)// Envelope *speedEnv, long minSpeed, lo { start=100; end= 10; mstep=-1; } steps++; - for(i=0; i<=steps; i++) { - for(int f=start; f!=int(end); f+=mstep) { - if (int(f/10)!=f/10.0f) { - val = decade * f/10; - if(val >= rMin && val < rMax) { - pos = (int)(((log10(val) - loLog)*scale)+0.5); - Tick(pos, val, false, false); + for (i = 0; i <= steps; i++) { + // PRL: Bug1038. Don't label 1.6, rounded, as a duplicate tick for "2" + if (!(mFormat == IntFormat && decade < 10.0)) { + for (int f = start; f != int(end); f += mstep) { + if (int(f / 10) != f / 10.0f) { + val = decade * f / 10; + if (val >= rMin && val < rMax) { + const int pos(0.5 + mLength * numberScale.ValueToPosition(val)); + Tick(pos, val, false, false); + } } } } @@ -1909,8 +1937,8 @@ void AdornedRulerPanel::OnMouseEvents(wxMouseEvent &evt) TrackPanel *tp = mProject->GetTrackPanel(); int mousePosX, width, height; tp->GetTracksUsableArea(&width, &height); - mousePosX = wxMax(evt.GetX(), tp->GetLeftOffset()); - mousePosX = wxMin(mousePosX, tp->GetLeftOffset() + width - 1); + mousePosX = std::max(evt.GetX(), tp->GetLeftOffset()); + mousePosX = std::min(mousePosX, tp->GetLeftOffset() + width - 1); bool isWithinStart = IsWithinMarker(mousePosX, mOldPlayRegionStart); bool isWithinEnd = IsWithinMarker(mousePosX, mOldPlayRegionEnd); @@ -1925,7 +1953,7 @@ void AdornedRulerPanel::OnMouseEvents(wxMouseEvent &evt) mLastMouseX = mousePosX; mQuickPlayPos = Pos2Time(mousePosX); // If not looping, restrict selection to end of project - if (!evt.ShiftDown()) mQuickPlayPos = wxMin(t1, mQuickPlayPos); + if (!evt.ShiftDown()) mQuickPlayPos = std::min(t1, mQuickPlayPos); if (evt.Leaving()) { @@ -2492,7 +2520,7 @@ void AdornedRulerPanel::DrawQuickPlayIndicator(wxDC * dc, bool clear) TrackPanel *tp = mProject->GetTrackPanel(); wxClientDC cdc(tp); - double latestEnd = wxMax(mProject->GetTracks()->GetEndTime(), mProject->GetSel1()); + double latestEnd = std::max(mProject->GetTracks()->GetEndTime(), mProject->GetSel1()); if (clear || (mQuickPlayPos >= latestEnd)) { tp->TrackPanel::DrawQuickPlayIndicator(cdc, -1); return; diff --git a/src/widgets/Ruler.h b/src/widgets/Ruler.h index 935659e8132d38ec50475c06233a92a571657362..f33ad2e33c9ed436330903bbd07b5ba0c90da68a 100644 --- a/src/widgets/Ruler.h +++ b/src/widgets/Ruler.h @@ -16,13 +16,13 @@ #include <wx/font.h> #include <wx/panel.h> #include <wx/window.h> -#include "../Envelope.h" #include "../Experimental.h" class ViewInfo; class AudacityProject; class TimeTrack; class SnapManager; +class NumberScale; class AUDACITY_DLL_API Ruler { public: @@ -98,6 +98,9 @@ class AUDACITY_DLL_API Ruler { // Good defaults are provided, but you can override here void SetFonts(const wxFont &minorFont, const wxFont &majorFont, const wxFont &minorMinorFont); + // Copies *pScale if it is not NULL + void SetNumberScale(const NumberScale *pScale); + // The ruler will not draw text within this (pixel) range. // Use this if you have another graphic object obscuring part // of the ruler's area. The values start and end are interpreted @@ -227,6 +230,8 @@ private: bool mTwoTone; bool mUseZoomInfo; int mLeftOffset; + + NumberScale *mpNumberScale; }; class AUDACITY_DLL_API RulerPanel : public wxPanel { diff --git a/win/Projects/Audacity/Audacity.vcxproj b/win/Projects/Audacity/Audacity.vcxproj index 413659967222e237897a034d5d44b28aa1033405..c4bf71f31361bcff43c6512b2d865d1752a0d853 100755 --- a/win/Projects/Audacity/Audacity.vcxproj +++ b/win/Projects/Audacity/Audacity.vcxproj @@ -179,6 +179,9 @@ <ClCompile Include="..\..\..\src\PlatformCompatibility.cpp" /> <ClCompile Include="..\..\..\src\PluginManager.cpp" /> <ClCompile Include="..\..\..\src\Prefs.cpp" /> + <ClCompile Include="..\..\..\src\prefs\SpectrogramSettings.cpp" /> + <ClCompile Include="..\..\..\src\prefs\WaveformPrefs.cpp" /> + <ClCompile Include="..\..\..\src\prefs\WaveformSettings.cpp" /> <ClCompile Include="..\..\..\src\Printing.cpp" /> <ClCompile Include="..\..\..\src\Profiler.cpp" /> <ClCompile Include="..\..\..\src\Project.cpp" /> @@ -421,11 +424,17 @@ <ClInclude Include="..\..\..\src\import\MultiFormatReader.h" /> <ClInclude Include="..\..\..\src\import\SpecPowerMeter.h" /> <ClInclude Include="..\..\..\src\ModuleManager.h" /> + <ClInclude Include="..\..\..\src\NumberScale.h" /> + <ClInclude Include="..\..\..\src\prefs\GUISettings.h" /> + <ClInclude Include="..\..\..\src\prefs\SpectrogramSettings.h" /> + <ClInclude Include="..\..\..\src\prefs\WaveformPrefs.h" /> + <ClInclude Include="..\..\..\src\prefs\WaveformSettings.h" /> <ClInclude Include="..\..\..\src\RevisionIdent.h" /> <ClInclude Include="..\..\..\src\SelectedRegion.h" /> <ClInclude Include="..\..\..\src\SseMathFuncs.h" /> <ClInclude Include="..\..\..\src\toolbars\SpectralSelectionBar.h" /> <ClInclude Include="..\..\..\src\toolbars\SpectralSelectionBarListener.h" /> + <ClInclude Include="..\..\..\src\WaveTrackLocation.h" /> <ClInclude Include="..\..\..\src\widgets\HelpSystem.h" /> <ClInclude Include="..\..\..\src\widgets\NumericTextCtrl.h" /> <ClInclude Include="..\..\configwin.h" /> diff --git a/win/Projects/Audacity/Audacity.vcxproj.filters b/win/Projects/Audacity/Audacity.vcxproj.filters index 6754ad973693aa39fd5e6ac167668840313d4478..abab8c6ac3ba340f3b2ff119e9078250ca8dcc57 100755 --- a/win/Projects/Audacity/Audacity.vcxproj.filters +++ b/win/Projects/Audacity/Audacity.vcxproj.filters @@ -3,69 +3,71 @@ <ItemGroup> <Filter Include="src"> <UniqueIdentifier>{348bf572-4c97-4a76-89f3-117a94118ff5}</UniqueIdentifier> + <Extensions> + </Extensions> </Filter> - <Filter Include="src/effects"> - <UniqueIdentifier>{eaa919b2-fa74-43bf-882e-d62b1365d884}</UniqueIdentifier> - </Filter> - <Filter Include="src/effects/VST"> - <UniqueIdentifier>{99325e00-3930-4e03-a599-999f275db78e}</UniqueIdentifier> - </Filter> - <Filter Include="src/export"> - <UniqueIdentifier>{45fbd203-4e13-441d-a7a2-e4614d6a67f7}</UniqueIdentifier> + <Filter Include="Resources"> + <UniqueIdentifier>{67e0ccd0-e2da-46a1-80b9-b27e85475080}</UniqueIdentifier> </Filter> - <Filter Include="src/import"> - <UniqueIdentifier>{fcf0dda3-8121-4954-94ef-7cec6d1a163d}</UniqueIdentifier> + <Filter Include="plug-ins"> + <UniqueIdentifier>{cfc19d3c-fac3-4724-b677-d446d9dd10a5}</UniqueIdentifier> </Filter> - <Filter Include="src/prefs"> - <UniqueIdentifier>{aa973747-536e-4acd-a418-f1aacd9698ed}</UniqueIdentifier> + <Filter Include="nyquist"> + <UniqueIdentifier>{df132fc5-4e81-4e57-a754-f9d639179bca}</UniqueIdentifier> </Filter> - <Filter Include="src/widgets"> - <UniqueIdentifier>{daec450f-84fa-4e72-ba52-e0733f2c5acf}</UniqueIdentifier> + <Filter Include="nyquist\rawwaves"> + <UniqueIdentifier>{5e31814b-dcd1-4c9a-977b-88b4a51e8226}</UniqueIdentifier> </Filter> - <Filter Include="Resources"> - <UniqueIdentifier>{67e0ccd0-e2da-46a1-80b9-b27e85475080}</UniqueIdentifier> + <Filter Include="includes"> + <UniqueIdentifier>{ce332b42-4385-473c-ad9c-f385ea2e6c73}</UniqueIdentifier> </Filter> - <Filter Include="src/xml"> - <UniqueIdentifier>{b2dffd13-d86c-4502-833b-3fa052e447a5}</UniqueIdentifier> + <Filter Include="includes\audacity"> + <UniqueIdentifier>{2bfa6793-371a-4d2e-b3f4-fb033a0c5729}</UniqueIdentifier> </Filter> - <Filter Include="src/effects/nyquist"> - <UniqueIdentifier>{bcfcf79a-6a8d-4768-8ee1-cf503eaecbf9}</UniqueIdentifier> + <Filter Include="src\blockfile"> + <UniqueIdentifier>{884d4cdc-e8f1-45f3-b5a6-5b8ac56b7d91}</UniqueIdentifier> </Filter> - <Filter Include="src/commands"> + <Filter Include="src\commands"> <UniqueIdentifier>{045249ee-cc52-4743-a1b9-e0532f4488d5}</UniqueIdentifier> </Filter> - <Filter Include="src/blockfile"> - <UniqueIdentifier>{884d4cdc-e8f1-45f3-b5a6-5b8ac56b7d91}</UniqueIdentifier> - </Filter> - <Filter Include="src/effects/ladspa"> - <UniqueIdentifier>{ab8cc474-825f-462e-a5da-d2055f6235ed}</UniqueIdentifier> + <Filter Include="src\effects"> + <UniqueIdentifier>{eaa919b2-fa74-43bf-882e-d62b1365d884}</UniqueIdentifier> </Filter> - <Filter Include="src/toolbars"> - <UniqueIdentifier>{03d93315-5b4c-4f40-aded-9b496497657d}</UniqueIdentifier> + <Filter Include="src\export"> + <UniqueIdentifier>{45fbd203-4e13-441d-a7a2-e4614d6a67f7}</UniqueIdentifier> </Filter> - <Filter Include="src/effects/vamp"> - <UniqueIdentifier>{1cd73294-06e2-42be-b7c0-2d620f621ec2}</UniqueIdentifier> + <Filter Include="src\import"> + <UniqueIdentifier>{fcf0dda3-8121-4954-94ef-7cec6d1a163d}</UniqueIdentifier> </Filter> - <Filter Include="src/ondemand"> + <Filter Include="src\ondemand"> <UniqueIdentifier>{4180976f-8b29-41b8-af53-86d2aed120ec}</UniqueIdentifier> </Filter> - <Filter Include="plug-ins"> - <UniqueIdentifier>{cfc19d3c-fac3-4724-b677-d446d9dd10a5}</UniqueIdentifier> + <Filter Include="src\prefs"> + <UniqueIdentifier>{aa973747-536e-4acd-a418-f1aacd9698ed}</UniqueIdentifier> </Filter> - <Filter Include="nyquist"> - <UniqueIdentifier>{df132fc5-4e81-4e57-a754-f9d639179bca}</UniqueIdentifier> + <Filter Include="src\toolbars"> + <UniqueIdentifier>{03d93315-5b4c-4f40-aded-9b496497657d}</UniqueIdentifier> </Filter> - <Filter Include="nyquist\rawwaves"> - <UniqueIdentifier>{5e31814b-dcd1-4c9a-977b-88b4a51e8226}</UniqueIdentifier> + <Filter Include="src\widgets"> + <UniqueIdentifier>{daec450f-84fa-4e72-ba52-e0733f2c5acf}</UniqueIdentifier> </Filter> - <Filter Include="src/effects/lv2"> + <Filter Include="src\xml"> + <UniqueIdentifier>{b2dffd13-d86c-4502-833b-3fa052e447a5}</UniqueIdentifier> + </Filter> + <Filter Include="src\effects\ladspa"> + <UniqueIdentifier>{ab8cc474-825f-462e-a5da-d2055f6235ed}</UniqueIdentifier> + </Filter> + <Filter Include="src\effects\lv2"> <UniqueIdentifier>{cfbc5496-9828-4c04-8e02-35a5e81cf092}</UniqueIdentifier> </Filter> - <Filter Include="includes"> - <UniqueIdentifier>{ce332b42-4385-473c-ad9c-f385ea2e6c73}</UniqueIdentifier> + <Filter Include="src\effects\nyquist"> + <UniqueIdentifier>{bcfcf79a-6a8d-4768-8ee1-cf503eaecbf9}</UniqueIdentifier> </Filter> - <Filter Include="includes\audacity"> - <UniqueIdentifier>{2bfa6793-371a-4d2e-b3f4-fb033a0c5729}</UniqueIdentifier> + <Filter Include="src\effects\vamp"> + <UniqueIdentifier>{1cd73294-06e2-42be-b7c0-2d620f621ec2}</UniqueIdentifier> + </Filter> + <Filter Include="src\effects\VST"> + <UniqueIdentifier>{99325e00-3930-4e03-a599-999f275db78e}</UniqueIdentifier> </Filter> </ItemGroup> <ItemGroup> @@ -295,535 +297,535 @@ <Filter>src</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\Amplify.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\AutoDuck.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\BassTreble.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\Biquad.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\ChangePitch.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\ChangeSpeed.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\ChangeTempo.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\ClickRemoval.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\Compressor.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\Contrast.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\DtmfGen.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\Echo.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\Effect.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\EffectManager.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\Equalization.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\Fade.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\FindClipping.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\Generator.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\Invert.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\Leveller.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\LoadEffects.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\Noise.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\NoiseRemoval.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\Normalize.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\Paulstretch.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\Repair.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\Repeat.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\Reverb.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\Reverse.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\SBSMSEffect.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\ScienFilter.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\ScoreAlignDialog.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\Silence.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\SimpleMono.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\SoundTouchEffect.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\StereoToMono.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\TimeScale.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\TimeWarper.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\ToneGen.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\TruncSilence.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\TwoPassSimpleMono.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\Wahwah.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\VST\VSTEffect.cpp"> - <Filter>src/effects/VST</Filter> + <Filter>src\effects\VST</Filter> </ClCompile> <ClCompile Include="..\..\..\src\export\Export.cpp"> - <Filter>src/export</Filter> + <Filter>src\export</Filter> </ClCompile> <ClCompile Include="..\..\..\src\export\ExportCL.cpp"> - <Filter>src/export</Filter> + <Filter>src\export</Filter> </ClCompile> <ClCompile Include="..\..\..\src\export\ExportFFmpeg.cpp"> - <Filter>src/export</Filter> + <Filter>src\export</Filter> </ClCompile> <ClCompile Include="..\..\..\src\export\ExportFFmpegDialogs.cpp"> - <Filter>src/export</Filter> + <Filter>src\export</Filter> </ClCompile> <ClCompile Include="..\..\..\src\export\ExportFLAC.cpp"> - <Filter>src/export</Filter> + <Filter>src\export</Filter> </ClCompile> <ClCompile Include="..\..\..\src\export\ExportMP2.cpp"> - <Filter>src/export</Filter> + <Filter>src\export</Filter> </ClCompile> <ClCompile Include="..\..\..\src\export\ExportMP3.cpp"> - <Filter>src/export</Filter> + <Filter>src\export</Filter> </ClCompile> <ClCompile Include="..\..\..\src\export\ExportMultiple.cpp"> - <Filter>src/export</Filter> + <Filter>src\export</Filter> </ClCompile> <ClCompile Include="..\..\..\src\export\ExportOGG.cpp"> - <Filter>src/export</Filter> + <Filter>src\export</Filter> </ClCompile> <ClCompile Include="..\..\..\src\export\ExportPCM.cpp"> - <Filter>src/export</Filter> + <Filter>src\export</Filter> </ClCompile> <ClCompile Include="..\..\..\src\import\Import.cpp"> - <Filter>src/import</Filter> + <Filter>src\import</Filter> </ClCompile> <ClCompile Include="..\..\..\src\import\ImportFFmpeg.cpp"> - <Filter>src/import</Filter> + <Filter>src\import</Filter> </ClCompile> <ClCompile Include="..\..\..\src\import\ImportFLAC.cpp"> - <Filter>src/import</Filter> + <Filter>src\import</Filter> </ClCompile> <ClCompile Include="..\..\..\src\import\ImportLOF.cpp"> - <Filter>src/import</Filter> + <Filter>src\import</Filter> </ClCompile> <ClCompile Include="..\..\..\src\import\ImportMIDI.cpp"> - <Filter>src/import</Filter> + <Filter>src\import</Filter> </ClCompile> <ClCompile Include="..\..\..\src\import\ImportMP3.cpp"> - <Filter>src/import</Filter> + <Filter>src\import</Filter> </ClCompile> <ClCompile Include="..\..\..\src\import\ImportOGG.cpp"> - <Filter>src/import</Filter> + <Filter>src\import</Filter> </ClCompile> <ClCompile Include="..\..\..\src\import\ImportPCM.cpp"> - <Filter>src/import</Filter> + <Filter>src\import</Filter> </ClCompile> <ClCompile Include="..\..\..\src\import\ImportRaw.cpp"> - <Filter>src/import</Filter> + <Filter>src\import</Filter> </ClCompile> <ClCompile Include="..\..\..\src\import\RawAudioGuess.cpp"> - <Filter>src/import</Filter> + <Filter>src\import</Filter> </ClCompile> <ClCompile Include="..\..\..\src\prefs\BatchPrefs.cpp"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClCompile> <ClCompile Include="..\..\..\src\prefs\DevicePrefs.cpp"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClCompile> <ClCompile Include="..\..\..\src\prefs\DirectoriesPrefs.cpp"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClCompile> <ClCompile Include="..\..\..\src\prefs\EffectsPrefs.cpp"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClCompile> <ClCompile Include="..\..\..\src\prefs\ExtImportPrefs.cpp"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClCompile> <ClCompile Include="..\..\..\src\prefs\GUIPrefs.cpp"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClCompile> <ClCompile Include="..\..\..\src\prefs\ImportExportPrefs.cpp"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClCompile> <ClCompile Include="..\..\..\src\prefs\KeyConfigPrefs.cpp"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClCompile> <ClCompile Include="..\..\..\src\prefs\LibraryPrefs.cpp"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClCompile> <ClCompile Include="..\..\..\src\prefs\MidiIOPrefs.cpp"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClCompile> <ClCompile Include="..\..\..\src\prefs\ModulePrefs.cpp"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClCompile> <ClCompile Include="..\..\..\src\prefs\MousePrefs.cpp"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClCompile> <ClCompile Include="..\..\..\src\prefs\PlaybackPrefs.cpp"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClCompile> <ClCompile Include="..\..\..\src\prefs\PrefsDialog.cpp"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClCompile> <ClCompile Include="..\..\..\src\prefs\ProjectsPrefs.cpp"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClCompile> <ClCompile Include="..\..\..\src\prefs\QualityPrefs.cpp"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClCompile> <ClCompile Include="..\..\..\src\prefs\RecordingPrefs.cpp"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClCompile> <ClCompile Include="..\..\..\src\prefs\SpectrumPrefs.cpp"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClCompile> <ClCompile Include="..\..\..\src\prefs\ThemePrefs.cpp"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClCompile> <ClCompile Include="..\..\..\src\prefs\TracksPrefs.cpp"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClCompile> <ClCompile Include="..\..\..\src\prefs\WarningsPrefs.cpp"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClCompile> <ClCompile Include="..\..\..\src\widgets\AButton.cpp"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClCompile> <ClCompile Include="..\..\..\src\widgets\ASlider.cpp"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClCompile> <ClCompile Include="..\..\..\src\widgets\AttachableScrollBar.cpp"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClCompile> <ClCompile Include="..\..\..\src\widgets\ErrorDialog.cpp"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClCompile> <ClCompile Include="..\..\..\src\widgets\ExpandingToolBar.cpp"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClCompile> <ClCompile Include="..\..\..\src\widgets\FileHistory.cpp"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClCompile> <ClCompile Include="..\..\..\src\widgets\Grabber.cpp"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClCompile> <ClCompile Include="..\..\..\src\widgets\Grid.cpp"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClCompile> <ClCompile Include="..\..\..\src\widgets\HtmlWindow.cpp"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClCompile> <ClCompile Include="..\..\..\src\widgets\ImageRoll.cpp"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClCompile> <ClCompile Include="..\..\..\src\widgets\KeyView.cpp"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClCompile> <ClCompile Include="..\..\..\src\widgets\LinkingHtmlWindow.cpp"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClCompile> <ClCompile Include="..\..\..\src\widgets\Meter.cpp"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClCompile> <ClCompile Include="..\..\..\src\widgets\MultiDialog.cpp"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClCompile> <ClCompile Include="..\..\..\src\widgets\numformatter.cpp"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClCompile> <ClCompile Include="..\..\..\src\widgets\ProgressDialog.cpp"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClCompile> <ClCompile Include="..\..\..\src\widgets\Ruler.cpp"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClCompile> <ClCompile Include="..\..\..\src\widgets\valnum.cpp"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClCompile> <ClCompile Include="..\..\..\src\widgets\Warning.cpp"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClCompile> <ClCompile Include="..\..\..\src\xml\XMLFileReader.cpp"> - <Filter>src/xml</Filter> + <Filter>src\xml</Filter> </ClCompile> <ClCompile Include="..\..\..\src\xml\XMLTagHandler.cpp"> - <Filter>src/xml</Filter> + <Filter>src\xml</Filter> </ClCompile> <ClCompile Include="..\..\..\src\xml\XMLWriter.cpp"> - <Filter>src/xml</Filter> + <Filter>src\xml</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\nyquist\LoadNyquist.cpp"> - <Filter>src/effects/nyquist</Filter> + <Filter>src\effects\nyquist</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\nyquist\Nyquist.cpp"> - <Filter>src/effects/nyquist</Filter> + <Filter>src\effects\nyquist</Filter> </ClCompile> <ClCompile Include="..\..\..\src\commands\AppCommandEvent.cpp"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClCompile> <ClCompile Include="..\..\..\src\commands\BatchEvalCommand.cpp"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClCompile> <ClCompile Include="..\..\..\src\commands\Command.cpp"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClCompile> <ClCompile Include="..\..\..\src\commands\CommandBuilder.cpp"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClCompile> <ClCompile Include="..\..\..\src\commands\CommandDirectory.cpp"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClCompile> <ClCompile Include="..\..\..\src\commands\CommandHandler.cpp"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClCompile> <ClCompile Include="..\..\..\src\commands\CommandManager.cpp"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClCompile> <ClCompile Include="..\..\..\src\commands\CommandSignature.cpp"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClCompile> <ClCompile Include="..\..\..\src\commands\CommandType.cpp"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClCompile> <ClCompile Include="..\..\..\src\commands\CompareAudioCommand.cpp"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClCompile> <ClCompile Include="..\..\..\src\commands\ExecMenuCommand.cpp"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClCompile> <ClCompile Include="..\..\..\src\commands\GetAllMenuCommands.cpp"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClCompile> <ClCompile Include="..\..\..\src\commands\GetProjectInfoCommand.cpp"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClCompile> <ClCompile Include="..\..\..\src\commands\GetTrackInfoCommand.cpp"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClCompile> <ClCompile Include="..\..\..\src\commands\HelpCommand.cpp"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClCompile> <ClCompile Include="..\..\..\src\commands\ImportExportCommands.cpp"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClCompile> <ClCompile Include="..\..\..\src\commands\Keyboard.cpp"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClCompile> <ClCompile Include="..\..\..\src\commands\MessageCommand.cpp"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClCompile> <ClCompile Include="..\..\..\src\commands\PreferenceCommands.cpp"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClCompile> <ClCompile Include="..\..\..\src\commands\ResponseQueue.cpp"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClCompile> <ClCompile Include="..\..\..\src\commands\ScreenshotCommand.cpp"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClCompile> <ClCompile Include="..\..\..\src\commands\ScriptCommandRelay.cpp"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClCompile> <ClCompile Include="..\..\..\src\commands\SelectCommand.cpp"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClCompile> <ClCompile Include="..\..\..\src\commands\SetProjectInfoCommand.cpp"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClCompile> <ClCompile Include="..\..\..\src\commands\SetTrackInfoCommand.cpp"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClCompile> <ClCompile Include="..\..\..\src\blockfile\LegacyAliasBlockFile.cpp"> - <Filter>src/blockfile</Filter> + <Filter>src\blockfile</Filter> </ClCompile> <ClCompile Include="..\..\..\src\blockfile\LegacyBlockFile.cpp"> - <Filter>src/blockfile</Filter> + <Filter>src\blockfile</Filter> </ClCompile> <ClCompile Include="..\..\..\src\blockfile\ODDecodeBlockFile.cpp"> - <Filter>src/blockfile</Filter> + <Filter>src\blockfile</Filter> </ClCompile> <ClCompile Include="..\..\..\src\blockfile\ODPCMAliasBlockFile.cpp"> - <Filter>src/blockfile</Filter> + <Filter>src\blockfile</Filter> </ClCompile> <ClCompile Include="..\..\..\src\blockfile\PCMAliasBlockFile.cpp"> - <Filter>src/blockfile</Filter> + <Filter>src\blockfile</Filter> </ClCompile> <ClCompile Include="..\..\..\src\blockfile\SilentBlockFile.cpp"> - <Filter>src/blockfile</Filter> + <Filter>src\blockfile</Filter> </ClCompile> <ClCompile Include="..\..\..\src\blockfile\SimpleBlockFile.cpp"> - <Filter>src/blockfile</Filter> + <Filter>src\blockfile</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\ladspa\LadspaEffect.cpp"> - <Filter>src/effects/ladspa</Filter> + <Filter>src\effects\ladspa</Filter> </ClCompile> <ClCompile Include="..\..\..\src\toolbars\ControlToolBar.cpp"> - <Filter>src/toolbars</Filter> + <Filter>src\toolbars</Filter> </ClCompile> <ClCompile Include="..\..\..\src\toolbars\DeviceToolBar.cpp"> - <Filter>src/toolbars</Filter> + <Filter>src\toolbars</Filter> </ClCompile> <ClCompile Include="..\..\..\src\toolbars\EditToolBar.cpp"> - <Filter>src/toolbars</Filter> + <Filter>src\toolbars</Filter> </ClCompile> <ClCompile Include="..\..\..\src\toolbars\MeterToolBar.cpp"> - <Filter>src/toolbars</Filter> + <Filter>src\toolbars</Filter> </ClCompile> <ClCompile Include="..\..\..\src\toolbars\MixerToolBar.cpp"> - <Filter>src/toolbars</Filter> + <Filter>src\toolbars</Filter> </ClCompile> <ClCompile Include="..\..\..\src\toolbars\SelectionBar.cpp"> - <Filter>src/toolbars</Filter> + <Filter>src\toolbars</Filter> </ClCompile> <ClCompile Include="..\..\..\src\toolbars\ToolBar.cpp"> - <Filter>src/toolbars</Filter> + <Filter>src\toolbars</Filter> </ClCompile> <ClCompile Include="..\..\..\src\toolbars\ToolDock.cpp"> - <Filter>src/toolbars</Filter> + <Filter>src\toolbars</Filter> </ClCompile> <ClCompile Include="..\..\..\src\toolbars\ToolManager.cpp"> - <Filter>src/toolbars</Filter> + <Filter>src\toolbars</Filter> </ClCompile> <ClCompile Include="..\..\..\src\toolbars\ToolsToolBar.cpp"> - <Filter>src/toolbars</Filter> + <Filter>src\toolbars</Filter> </ClCompile> <ClCompile Include="..\..\..\src\toolbars\TranscriptionToolBar.cpp"> - <Filter>src/toolbars</Filter> + <Filter>src\toolbars</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\vamp\LoadVamp.cpp"> - <Filter>src/effects/vamp</Filter> + <Filter>src\effects\vamp</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\vamp\VampEffect.cpp"> - <Filter>src/effects/vamp</Filter> + <Filter>src\effects\vamp</Filter> </ClCompile> <ClCompile Include="..\..\..\src\ondemand\ODComputeSummaryTask.cpp"> - <Filter>src/ondemand</Filter> + <Filter>src\ondemand</Filter> </ClCompile> <ClCompile Include="..\..\..\src\ondemand\ODDecodeFFmpegTask.cpp"> - <Filter>src/ondemand</Filter> + <Filter>src\ondemand</Filter> </ClCompile> <ClCompile Include="..\..\..\src\ondemand\ODDecodeFlacTask.cpp"> - <Filter>src/ondemand</Filter> + <Filter>src\ondemand</Filter> </ClCompile> <ClCompile Include="..\..\..\src\ondemand\ODDecodeTask.cpp"> - <Filter>src/ondemand</Filter> + <Filter>src\ondemand</Filter> </ClCompile> <ClCompile Include="..\..\..\src\ondemand\ODManager.cpp"> - <Filter>src/ondemand</Filter> + <Filter>src\ondemand</Filter> </ClCompile> <ClCompile Include="..\..\..\src\ondemand\ODTask.cpp"> - <Filter>src/ondemand</Filter> + <Filter>src\ondemand</Filter> </ClCompile> <ClCompile Include="..\..\..\src\ondemand\ODTaskThread.cpp"> - <Filter>src/ondemand</Filter> + <Filter>src\ondemand</Filter> </ClCompile> <ClCompile Include="..\..\..\src\ondemand\ODWaveTrackTaskQueue.cpp"> - <Filter>src/ondemand</Filter> + <Filter>src\ondemand</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\lv2\LoadLV2.cpp"> - <Filter>src/effects/lv2</Filter> + <Filter>src\effects\lv2</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\lv2\LV2Effect.cpp"> - <Filter>src/effects/lv2</Filter> + <Filter>src\effects\lv2</Filter> </ClCompile> <ClCompile Include="..\..\..\src\SseMathFuncs.cpp"> <Filter>src</Filter> </ClCompile> <ClCompile Include="..\..\..\src\commands\OpenSaveCommands.cpp"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClCompile> <ClCompile Include="..\..\..\src\import\ImportGStreamer.cpp"> - <Filter>src/import</Filter> + <Filter>src\import</Filter> </ClCompile> <ClCompile Include="..\..\..\src\widgets\HelpSystem.cpp"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClCompile> <ClCompile Include="..\..\..\src\import\FormatClassifier.cpp"> - <Filter>src/import</Filter> + <Filter>src\import</Filter> </ClCompile> <ClCompile Include="..\..\..\src\import\SpecPowerMeter.cpp"> - <Filter>src/import</Filter> + <Filter>src\import</Filter> </ClCompile> <ClCompile Include="..\..\..\src\import\MultiFormatReader.cpp"> - <Filter>src/import</Filter> + <Filter>src\import</Filter> </ClCompile> <ClCompile Include="..\..\..\src\ModuleManager.cpp"> <Filter>src</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\EffectRack.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\toolbars\SpectralSelectionBar.cpp"> - <Filter>src/toolbars</Filter> + <Filter>src\toolbars</Filter> </ClCompile> <ClCompile Include="..\..\..\src\widgets\NumericTextCtrl.cpp"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\Phaser.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\effects\NoiseReduction.cpp"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClCompile> <ClCompile Include="..\..\..\src\DeviceChange.cpp"> <Filter>src</Filter> @@ -840,6 +842,15 @@ <ClCompile Include="..\..\..\src\effects\VST\VSTControlMSW.cpp"> <Filter>src/effects/VST</Filter> </ClCompile> + <ClCompile Include="..\..\..\src\prefs\SpectrogramSettings.cpp"> + <Filter>src\prefs</Filter> + </ClCompile> + <ClCompile Include="..\..\..\src\prefs\WaveformPrefs.cpp"> + <Filter>src\prefs</Filter> + </ClCompile> + <ClCompile Include="..\..\..\src\prefs\WaveformSettings.cpp"> + <Filter>src\prefs</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="..\..\..\src\AboutDialog.h"> @@ -1083,535 +1094,535 @@ <Filter>src</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\Amplify.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\AutoDuck.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\BassTreble.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\Biquad.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\ChangePitch.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\ChangeSpeed.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\ChangeTempo.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\ClickRemoval.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\Compressor.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\Contrast.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\DtmfGen.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\Echo.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\Effect.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\EffectManager.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\Equalization.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\Fade.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\FindClipping.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\Generator.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\Invert.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\Leveller.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\LoadEffects.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\Noise.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\NoiseRemoval.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\Normalize.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\Paulstretch.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\Repair.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\Repeat.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\Reverb.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\Reverb_libSoX.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\Reverse.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\SBSMSEffect.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\ScienFilter.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\Silence.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\SimpleMono.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\SoundTouchEffect.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\StereoToMono.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\TimeScale.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\TimeWarper.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\ToneGen.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\TruncSilence.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\TwoPassSimpleMono.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\Wahwah.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\VST\VSTEffect.h"> - <Filter>src/effects/VST</Filter> + <Filter>src\effects\VST</Filter> </ClInclude> <ClInclude Include="..\..\..\src\export\Export.h"> - <Filter>src/export</Filter> + <Filter>src\export</Filter> </ClInclude> <ClInclude Include="..\..\..\src\export\ExportCL.h"> - <Filter>src/export</Filter> + <Filter>src\export</Filter> </ClInclude> <ClInclude Include="..\..\..\src\export\ExportFFmpeg.h"> - <Filter>src/export</Filter> + <Filter>src\export</Filter> </ClInclude> <ClInclude Include="..\..\..\src\export\ExportFFmpegDialogs.h"> - <Filter>src/export</Filter> + <Filter>src\export</Filter> </ClInclude> <ClInclude Include="..\..\..\src\export\ExportFLAC.h"> - <Filter>src/export</Filter> + <Filter>src\export</Filter> </ClInclude> <ClInclude Include="..\..\..\src\export\ExportMP2.h"> - <Filter>src/export</Filter> + <Filter>src\export</Filter> </ClInclude> <ClInclude Include="..\..\..\src\export\ExportMP3.h"> - <Filter>src/export</Filter> + <Filter>src\export</Filter> </ClInclude> <ClInclude Include="..\..\..\src\export\ExportMultiple.h"> - <Filter>src/export</Filter> + <Filter>src\export</Filter> </ClInclude> <ClInclude Include="..\..\..\src\export\ExportOGG.h"> - <Filter>src/export</Filter> + <Filter>src\export</Filter> </ClInclude> <ClInclude Include="..\..\..\src\export\ExportPCM.h"> - <Filter>src/export</Filter> + <Filter>src\export</Filter> </ClInclude> <ClInclude Include="..\..\..\src\import\Import.h"> - <Filter>src/import</Filter> + <Filter>src\import</Filter> </ClInclude> <ClInclude Include="..\..\..\src\import\ImportFFmpeg.h"> - <Filter>src/import</Filter> + <Filter>src\import</Filter> </ClInclude> <ClInclude Include="..\..\..\src\import\ImportFLAC.h"> - <Filter>src/import</Filter> + <Filter>src\import</Filter> </ClInclude> <ClInclude Include="..\..\..\src\import\ImportLOF.h"> - <Filter>src/import</Filter> + <Filter>src\import</Filter> </ClInclude> <ClInclude Include="..\..\..\src\import\ImportMIDI.h"> - <Filter>src/import</Filter> + <Filter>src\import</Filter> </ClInclude> <ClInclude Include="..\..\..\src\import\ImportMP3.h"> - <Filter>src/import</Filter> + <Filter>src\import</Filter> </ClInclude> <ClInclude Include="..\..\..\src\import\ImportOGG.h"> - <Filter>src/import</Filter> + <Filter>src\import</Filter> </ClInclude> <ClInclude Include="..\..\..\src\import\ImportPCM.h"> - <Filter>src/import</Filter> + <Filter>src\import</Filter> </ClInclude> <ClInclude Include="..\..\..\src\import\ImportPlugin.h"> - <Filter>src/import</Filter> + <Filter>src\import</Filter> </ClInclude> <ClInclude Include="..\..\..\src\import\ImportRaw.h"> - <Filter>src/import</Filter> + <Filter>src\import</Filter> </ClInclude> <ClInclude Include="..\..\..\src\import\RawAudioGuess.h"> - <Filter>src/import</Filter> + <Filter>src\import</Filter> </ClInclude> <ClInclude Include="..\..\..\src\prefs\BatchPrefs.h"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClInclude> <ClInclude Include="..\..\..\src\prefs\DevicePrefs.h"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClInclude> <ClInclude Include="..\..\..\src\prefs\DirectoriesPrefs.h"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClInclude> <ClInclude Include="..\..\..\src\prefs\EffectsPrefs.h"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClInclude> <ClInclude Include="..\..\..\src\prefs\ExtImportPrefs.h"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClInclude> <ClInclude Include="..\..\..\src\prefs\GUIPrefs.h"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClInclude> <ClInclude Include="..\..\..\src\prefs\ImportExportPrefs.h"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClInclude> <ClInclude Include="..\..\..\src\prefs\KeyConfigPrefs.h"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClInclude> <ClInclude Include="..\..\..\src\prefs\LibraryPrefs.h"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClInclude> <ClInclude Include="..\..\..\src\prefs\MidiIOPrefs.h"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClInclude> <ClInclude Include="..\..\..\src\prefs\ModulePrefs.h"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClInclude> <ClInclude Include="..\..\..\src\prefs\MousePrefs.h"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClInclude> <ClInclude Include="..\..\..\src\prefs\PlaybackPrefs.h"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClInclude> <ClInclude Include="..\..\..\src\prefs\PrefsDialog.h"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClInclude> <ClInclude Include="..\..\..\src\prefs\PrefsPanel.h"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClInclude> <ClInclude Include="..\..\..\src\prefs\ProjectsPrefs.h"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClInclude> <ClInclude Include="..\..\..\src\prefs\QualityPrefs.h"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClInclude> <ClInclude Include="..\..\..\src\prefs\RecordingPrefs.h"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClInclude> <ClInclude Include="..\..\..\src\prefs\SpectrumPrefs.h"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClInclude> <ClInclude Include="..\..\..\src\prefs\ThemePrefs.h"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClInclude> <ClInclude Include="..\..\..\src\prefs\TracksPrefs.h"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClInclude> <ClInclude Include="..\..\..\src\prefs\WarningsPrefs.h"> - <Filter>src/prefs</Filter> + <Filter>src\prefs</Filter> </ClInclude> <ClInclude Include="..\..\..\src\widgets\AButton.h"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClInclude> <ClInclude Include="..\..\..\src\widgets\ASlider.h"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClInclude> <ClInclude Include="..\..\..\src\widgets\AttachableScrollBar.h"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClInclude> <ClInclude Include="..\..\..\src\widgets\ErrorDialog.h"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClInclude> <ClInclude Include="..\..\..\src\widgets\ExpandingToolBar.h"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClInclude> <ClInclude Include="..\..\..\src\widgets\FileHistory.h"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClInclude> <ClInclude Include="..\..\..\src\widgets\Grabber.h"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClInclude> <ClInclude Include="..\..\..\src\widgets\Grid.h"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClInclude> <ClInclude Include="..\..\..\src\widgets\HtmlWindow.h"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClInclude> <ClInclude Include="..\..\..\src\widgets\ImageRoll.h"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClInclude> <ClInclude Include="..\..\..\src\widgets\KeyView.h"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClInclude> <ClInclude Include="..\..\..\src\widgets\LinkingHtmlWindow.h"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClInclude> <ClInclude Include="..\..\..\src\widgets\Meter.h"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClInclude> <ClInclude Include="..\..\..\src\widgets\MultiDialog.h"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClInclude> <ClInclude Include="..\..\..\src\widgets\numformatter.h"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClInclude> <ClInclude Include="..\..\..\src\widgets\ProgressDialog.h"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClInclude> <ClInclude Include="..\..\..\src\widgets\Ruler.h"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClInclude> <ClInclude Include="..\..\..\src\widgets\valnum.h"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClInclude> <ClInclude Include="..\..\..\src\widgets\Warning.h"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClInclude> <ClInclude Include="..\..\..\src\xml\XMLFileReader.h"> - <Filter>src/xml</Filter> + <Filter>src\xml</Filter> </ClInclude> <ClInclude Include="..\..\..\src\xml\XMLTagHandler.h"> - <Filter>src/xml</Filter> + <Filter>src\xml</Filter> </ClInclude> <ClInclude Include="..\..\..\src\xml\XMLWriter.h"> - <Filter>src/xml</Filter> + <Filter>src\xml</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\nyquist\LoadNyquist.h"> - <Filter>src/effects/nyquist</Filter> + <Filter>src\effects\nyquist</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\nyquist\Nyquist.h"> - <Filter>src/effects/nyquist</Filter> + <Filter>src\effects\nyquist</Filter> </ClInclude> <ClInclude Include="..\..\..\src\commands\AppCommandEvent.h"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClInclude> <ClInclude Include="..\..\..\src\commands\BatchEvalCommand.h"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClInclude> <ClInclude Include="..\..\..\src\commands\Command.h"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClInclude> <ClInclude Include="..\..\..\src\commands\CommandBuilder.h"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClInclude> <ClInclude Include="..\..\..\src\commands\CommandDirectory.h"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClInclude> <ClInclude Include="..\..\..\src\commands\CommandHandler.h"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClInclude> <ClInclude Include="..\..\..\src\commands\CommandManager.h"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClInclude> <ClInclude Include="..\..\..\src\commands\CommandMisc.h"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClInclude> <ClInclude Include="..\..\..\src\commands\CommandSignature.h"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClInclude> <ClInclude Include="..\..\..\src\commands\CommandTargets.h"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClInclude> <ClInclude Include="..\..\..\src\commands\CommandType.h"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClInclude> <ClInclude Include="..\..\..\src\commands\CompareAudioCommand.h"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClInclude> <ClInclude Include="..\..\..\src\commands\ExecMenuCommand.h"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClInclude> <ClInclude Include="..\..\..\src\commands\GetAllMenuCommands.h"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClInclude> <ClInclude Include="..\..\..\src\commands\GetProjectInfoCommand.h"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClInclude> <ClInclude Include="..\..\..\src\commands\GetTrackInfoCommand.h"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClInclude> <ClInclude Include="..\..\..\src\commands\HelpCommand.h"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClInclude> <ClInclude Include="..\..\..\src\commands\ImportExportCommands.h"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClInclude> <ClInclude Include="..\..\..\src\commands\Keyboard.h"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClInclude> <ClInclude Include="..\..\..\src\commands\MessageCommand.h"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClInclude> <ClInclude Include="..\..\..\src\commands\PreferenceCommands.h"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClInclude> <ClInclude Include="..\..\..\src\commands\ResponseQueue.h"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClInclude> <ClInclude Include="..\..\..\src\commands\ScreenshotCommand.h"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClInclude> <ClInclude Include="..\..\..\src\commands\ScriptCommandRelay.h"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClInclude> <ClInclude Include="..\..\..\src\commands\SelectCommand.h"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClInclude> <ClInclude Include="..\..\..\src\commands\SetProjectInfoCommand.h"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClInclude> <ClInclude Include="..\..\..\src\commands\SetTrackInfoCommand.h"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClInclude> <ClInclude Include="..\..\..\src\commands\Validators.h"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClInclude> <ClInclude Include="..\..\..\src\blockfile\LegacyAliasBlockFile.h"> - <Filter>src/blockfile</Filter> + <Filter>src\blockfile</Filter> </ClInclude> <ClInclude Include="..\..\..\src\blockfile\LegacyBlockFile.h"> - <Filter>src/blockfile</Filter> + <Filter>src\blockfile</Filter> </ClInclude> <ClInclude Include="..\..\..\src\blockfile\ODDecodeBlockFile.h"> - <Filter>src/blockfile</Filter> + <Filter>src\blockfile</Filter> </ClInclude> <ClInclude Include="..\..\..\src\blockfile\ODPCMAliasBlockFile.h"> - <Filter>src/blockfile</Filter> + <Filter>src\blockfile</Filter> </ClInclude> <ClInclude Include="..\..\..\src\blockfile\PCMAliasBlockFile.h"> - <Filter>src/blockfile</Filter> + <Filter>src\blockfile</Filter> </ClInclude> <ClInclude Include="..\..\..\src\blockfile\SilentBlockFile.h"> - <Filter>src/blockfile</Filter> + <Filter>src\blockfile</Filter> </ClInclude> <ClInclude Include="..\..\..\src\blockfile\SimpleBlockFile.h"> - <Filter>src/blockfile</Filter> + <Filter>src\blockfile</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\ladspa\ladspa.h"> - <Filter>src/effects/ladspa</Filter> + <Filter>src\effects\ladspa</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\ladspa\LadspaEffect.h"> - <Filter>src/effects/ladspa</Filter> + <Filter>src\effects\ladspa</Filter> </ClInclude> <ClInclude Include="..\..\..\src\toolbars\ControlToolBar.h"> - <Filter>src/toolbars</Filter> + <Filter>src\toolbars</Filter> </ClInclude> <ClInclude Include="..\..\..\src\toolbars\DeviceToolBar.h"> - <Filter>src/toolbars</Filter> + <Filter>src\toolbars</Filter> </ClInclude> <ClInclude Include="..\..\..\src\toolbars\EditToolBar.h"> - <Filter>src/toolbars</Filter> + <Filter>src\toolbars</Filter> </ClInclude> <ClInclude Include="..\..\..\src\toolbars\MeterToolBar.h"> - <Filter>src/toolbars</Filter> + <Filter>src\toolbars</Filter> </ClInclude> <ClInclude Include="..\..\..\src\toolbars\MixerToolBar.h"> - <Filter>src/toolbars</Filter> + <Filter>src\toolbars</Filter> </ClInclude> <ClInclude Include="..\..\..\src\toolbars\SelectionBar.h"> - <Filter>src/toolbars</Filter> + <Filter>src\toolbars</Filter> </ClInclude> <ClInclude Include="..\..\..\src\toolbars\ToolBar.h"> - <Filter>src/toolbars</Filter> + <Filter>src\toolbars</Filter> </ClInclude> <ClInclude Include="..\..\..\src\toolbars\ToolDock.h"> - <Filter>src/toolbars</Filter> + <Filter>src\toolbars</Filter> </ClInclude> <ClInclude Include="..\..\..\src\toolbars\ToolManager.h"> - <Filter>src/toolbars</Filter> + <Filter>src\toolbars</Filter> </ClInclude> <ClInclude Include="..\..\..\src\toolbars\ToolsToolBar.h"> - <Filter>src/toolbars</Filter> + <Filter>src\toolbars</Filter> </ClInclude> <ClInclude Include="..\..\..\src\toolbars\TranscriptionToolBar.h"> - <Filter>src/toolbars</Filter> + <Filter>src\toolbars</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\vamp\LoadVamp.h"> - <Filter>src/effects/vamp</Filter> + <Filter>src\effects\vamp</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\vamp\VampEffect.h"> - <Filter>src/effects/vamp</Filter> + <Filter>src\effects\vamp</Filter> </ClInclude> <ClInclude Include="..\..\..\src\ondemand\ODComputeSummaryTask.h"> - <Filter>src/ondemand</Filter> + <Filter>src\ondemand</Filter> </ClInclude> <ClInclude Include="..\..\..\src\ondemand\ODDecodeFFmpegTask.h"> - <Filter>src/ondemand</Filter> + <Filter>src\ondemand</Filter> </ClInclude> <ClInclude Include="..\..\..\src\ondemand\ODDecodeFlacTask.h"> - <Filter>src/ondemand</Filter> + <Filter>src\ondemand</Filter> </ClInclude> <ClInclude Include="..\..\..\src\ondemand\ODDecodeTask.h"> - <Filter>src/ondemand</Filter> + <Filter>src\ondemand</Filter> </ClInclude> <ClInclude Include="..\..\..\src\ondemand\ODManager.h"> - <Filter>src/ondemand</Filter> + <Filter>src\ondemand</Filter> </ClInclude> <ClInclude Include="..\..\..\src\ondemand\ODTask.h"> - <Filter>src/ondemand</Filter> + <Filter>src\ondemand</Filter> </ClInclude> <ClInclude Include="..\..\..\src\ondemand\ODTaskThread.h"> - <Filter>src/ondemand</Filter> + <Filter>src\ondemand</Filter> </ClInclude> <ClInclude Include="..\..\..\src\ondemand\ODWaveTrackTaskQueue.h"> - <Filter>src/ondemand</Filter> + <Filter>src\ondemand</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\lv2\LoadLV2.h"> - <Filter>src/effects/lv2</Filter> + <Filter>src\effects\lv2</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\lv2\LV2Effect.h"> - <Filter>src/effects/lv2</Filter> + <Filter>src\effects\lv2</Filter> </ClInclude> <ClInclude Include="..\..\..\src\SseMathFuncs.h"> <Filter>src</Filter> </ClInclude> <ClInclude Include="..\..\..\src\commands\OpenSaveCommands.h"> - <Filter>src/commands</Filter> + <Filter>src\commands</Filter> </ClInclude> <ClInclude Include="..\..\..\src\import\ImportGStreamer.h"> - <Filter>src/import</Filter> + <Filter>src\import</Filter> </ClInclude> <ClInclude Include="..\..\..\src\widgets\HelpSystem.h"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClInclude> <ClInclude Include="..\..\..\src\import\FormatClassifier.h"> - <Filter>src/import</Filter> + <Filter>src\import</Filter> </ClInclude> <ClInclude Include="..\..\..\src\import\SpecPowerMeter.h"> - <Filter>src/import</Filter> + <Filter>src\import</Filter> </ClInclude> <ClInclude Include="..\..\..\src\import\MultiFormatReader.h"> - <Filter>src/import</Filter> + <Filter>src\import</Filter> </ClInclude> <ClInclude Include="..\..\..\include\audacity\ConfigInterface.h"> <Filter>includes\audacity</Filter> @@ -1638,25 +1649,25 @@ <Filter>src</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\EffectRack.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\toolbars\SpectralSelectionBar.h"> - <Filter>src/toolbars</Filter> + <Filter>src\toolbars</Filter> </ClInclude> <ClInclude Include="..\..\..\src\toolbars\SpectralSelectionBarListener.h"> - <Filter>src/toolbars</Filter> + <Filter>src\toolbars</Filter> </ClInclude> <ClInclude Include="..\..\..\src\widgets\NumericTextCtrl.h"> - <Filter>src/widgets</Filter> + <Filter>src\widgets</Filter> </ClInclude> <ClInclude Include="..\..\..\include\audacity\EffectAutomationParameters.h"> <Filter>includes\audacity</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\Phaser.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\effects\NoiseReduction.h"> - <Filter>src/effects</Filter> + <Filter>src\effects</Filter> </ClInclude> <ClInclude Include="..\..\..\src\DeviceChange.h"> <Filter>src</Filter> @@ -1679,6 +1690,24 @@ <ClInclude Include="..\..\..\src\effects\VST\VSTControlMSW.h"> <Filter>src/effects/VST</Filter> </ClInclude> + <ClInclude Include="..\..\..\src\prefs\SpectrogramSettings.h"> + <Filter>src\prefs</Filter> + </ClInclude> + <ClInclude Include="..\..\..\src\NumberScale.h"> + <Filter>src</Filter> + </ClInclude> + <ClInclude Include="..\..\..\src\prefs\WaveformPrefs.h"> + <Filter>src\prefs</Filter> + </ClInclude> + <ClInclude Include="..\..\..\src\prefs\WaveformSettings.h"> + <Filter>src\prefs</Filter> + </ClInclude> + <ClInclude Include="..\..\..\src\WaveTrackLocation.h"> + <Filter>src</Filter> + </ClInclude> + <ClInclude Include="..\..\..\src\prefs\GUISettings.h"> + <Filter>src\prefs</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <Image Include="..\..\audacity.ico">