From 3a1bc2a7ae9d818ad25b3de6ecc051068b9640cb Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Fri, 9 May 2014 08:41:07 -0700 Subject: [PATCH 01/61] Fix "Use of undeclared identifier 'getpid'" Troubleshooting RemoteZynAddSubFX. --- include/RemotePlugin.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/RemotePlugin.h b/include/RemotePlugin.h index edf09efbe..80a30af3e 100644 --- a/include/RemotePlugin.h +++ b/include/RemotePlugin.h @@ -42,7 +42,9 @@ #endif #ifdef LMMS_BUILD_APPLE +#include #define USE_QT_SEMAPHORES +#define USE_QT_SHMEM #endif From 5aa6779108254af03f34b21d2830438a19bd4ea9 Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Fri, 9 May 2014 08:45:10 -0700 Subject: [PATCH 02/61] Fix incorrect path to libZynAddSubFxCore.dylib --- data/scripts/create_apple_bundle.sh.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/scripts/create_apple_bundle.sh.in b/data/scripts/create_apple_bundle.sh.in index 8b335cb0d..b9364693d 100644 --- a/data/scripts/create_apple_bundle.sh.in +++ b/data/scripts/create_apple_bundle.sh.in @@ -90,7 +90,7 @@ install_name_tool -change libZynAddSubFxCore.dylib \ ${APP}/Contents/lib/lmms/libzynaddsubfx.so install_name_tool -change ${CMAKE_BUILD}/plugins/zynaddsubfx/libZynAddSubFxCore.dylib \ - @loader_path/../../Frameworks/libZynAddSubFxCore.dylib \ + @loader_path/../Frameworks/libZynAddSubFxCore.dylib \ ${APP}/Contents/MacOS/RemoteZynAddSubFx # Build a list of shared objects in target/lib/lmms From 9abfbd6c9448c11c56aed8a13ed44ab1737c789c Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Mon, 12 May 2014 21:37:01 -0700 Subject: [PATCH 03/61] #527 --- data/themes/default/style.css | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/data/themes/default/style.css b/data/themes/default/style.css index 3d6fd84a2..4b4bfc103 100644 --- a/data/themes/default/style.css +++ b/data/themes/default/style.css @@ -1,7 +1,9 @@ /******************** * LMMS style sheet * ********************/ -QLabel { + +/* most foreground text items */ +QLabel, QTreeWidget, QListWidget, QGroupBox { color: #e0e0e0; } From 5bb5ffc152e43db9dcb3b54c36794c2dc658b826 Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Mon, 12 May 2014 22:06:44 -0700 Subject: [PATCH 04/61] Revert changes --- include/RemotePlugin.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/RemotePlugin.h b/include/RemotePlugin.h index 80a30af3e..edf09efbe 100644 --- a/include/RemotePlugin.h +++ b/include/RemotePlugin.h @@ -42,9 +42,7 @@ #endif #ifdef LMMS_BUILD_APPLE -#include #define USE_QT_SEMAPHORES -#define USE_QT_SHMEM #endif From 959db3d7ac1a54cfcf1d05801ce91413060d4c30 Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Mon, 12 May 2014 22:08:34 -0700 Subject: [PATCH 05/61] Revert changes --- data/scripts/create_apple_bundle.sh.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/scripts/create_apple_bundle.sh.in b/data/scripts/create_apple_bundle.sh.in index b9364693d..b799cf12d 100644 --- a/data/scripts/create_apple_bundle.sh.in +++ b/data/scripts/create_apple_bundle.sh.in @@ -86,7 +86,7 @@ mv ${APP}/Contents/lib/lmms/RemoteZynAddSubFx \ # Fix more Zyn Linking issues install_name_tool -change libZynAddSubFxCore.dylib \ - @loader_path/../../Frameworks/libZynAddSubFxCore.dylib \ + @loader_path/../Frameworks/libZynAddSubFxCore.dylib \ ${APP}/Contents/lib/lmms/libzynaddsubfx.so install_name_tool -change ${CMAKE_BUILD}/plugins/zynaddsubfx/libZynAddSubFxCore.dylib \ From e401ac5c9d3376cb176511f718061aa3c4077e80 Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Mon, 12 May 2014 22:09:47 -0700 Subject: [PATCH 06/61] Revert changes --- data/scripts/create_apple_bundle.sh.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/scripts/create_apple_bundle.sh.in b/data/scripts/create_apple_bundle.sh.in index b799cf12d..b9364693d 100644 --- a/data/scripts/create_apple_bundle.sh.in +++ b/data/scripts/create_apple_bundle.sh.in @@ -86,7 +86,7 @@ mv ${APP}/Contents/lib/lmms/RemoteZynAddSubFx \ # Fix more Zyn Linking issues install_name_tool -change libZynAddSubFxCore.dylib \ - @loader_path/../Frameworks/libZynAddSubFxCore.dylib \ + @loader_path/../../Frameworks/libZynAddSubFxCore.dylib \ ${APP}/Contents/lib/lmms/libzynaddsubfx.so install_name_tool -change ${CMAKE_BUILD}/plugins/zynaddsubfx/libZynAddSubFxCore.dylib \ From 7404eef34ad658dbf0f334da9decbc3d3b9b8202 Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Mon, 12 May 2014 22:10:28 -0700 Subject: [PATCH 07/61] Revert changes --- data/scripts/create_apple_bundle.sh.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/scripts/create_apple_bundle.sh.in b/data/scripts/create_apple_bundle.sh.in index b9364693d..8b335cb0d 100644 --- a/data/scripts/create_apple_bundle.sh.in +++ b/data/scripts/create_apple_bundle.sh.in @@ -90,7 +90,7 @@ install_name_tool -change libZynAddSubFxCore.dylib \ ${APP}/Contents/lib/lmms/libzynaddsubfx.so install_name_tool -change ${CMAKE_BUILD}/plugins/zynaddsubfx/libZynAddSubFxCore.dylib \ - @loader_path/../Frameworks/libZynAddSubFxCore.dylib \ + @loader_path/../../Frameworks/libZynAddSubFxCore.dylib \ ${APP}/Contents/MacOS/RemoteZynAddSubFx # Build a list of shared objects in target/lib/lmms From 313977ebfdfa9c5be2e3d49670dda73975fd08d9 Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Fri, 16 May 2014 13:11:26 -0400 Subject: [PATCH 08/61] swh plugins: Fix SWH destructors The constructors had been fixed with commit #83c2019, but I had missed the destructors. This corrects the `_fini()` destructors as well. --- plugins/LadspaEffect/swh/alias_1407.c | 2 +- plugins/LadspaEffect/swh/allpass_1895.c | 2 +- plugins/LadspaEffect/swh/am_pitchshift_1433.c | 2 +- plugins/LadspaEffect/swh/amp_1181.c | 2 +- plugins/LadspaEffect/swh/bandpass_a_iir_1893.c | 2 +- plugins/LadspaEffect/swh/bandpass_iir_1892.c | 2 +- plugins/LadspaEffect/swh/bode_shifter_1431.c | 2 +- plugins/LadspaEffect/swh/bode_shifter_cv_1432.c | 2 +- plugins/LadspaEffect/swh/butterworth_1902.c | 2 +- plugins/LadspaEffect/swh/chebstortion_1430.c | 2 +- plugins/LadspaEffect/swh/comb_1190.c | 2 +- plugins/LadspaEffect/swh/comb_1887.c | 2 +- plugins/LadspaEffect/swh/comb_splitter_1411.c | 2 +- plugins/LadspaEffect/swh/const_1909.c | 2 +- plugins/LadspaEffect/swh/crossover_dist_1404.c | 2 +- plugins/LadspaEffect/swh/dc_remove_1207.c | 2 +- plugins/LadspaEffect/swh/decay_1886.c | 2 +- plugins/LadspaEffect/swh/decimator_1202.c | 2 +- plugins/LadspaEffect/swh/declip_1195.c | 2 +- plugins/LadspaEffect/swh/delay_1898.c | 2 +- plugins/LadspaEffect/swh/delayorama_1402.c | 2 +- plugins/LadspaEffect/swh/diode_1185.c | 2 +- plugins/LadspaEffect/swh/divider_1186.c | 2 +- plugins/LadspaEffect/swh/dj_eq_1901.c | 2 +- plugins/LadspaEffect/swh/dj_flanger_1438.c | 2 +- plugins/LadspaEffect/swh/dyson_compress_1403.c | 2 +- plugins/LadspaEffect/swh/fad_delay_1192.c | 2 +- plugins/LadspaEffect/swh/fast_lookahead_limiter_1913.c | 2 +- plugins/LadspaEffect/swh/flanger_1191.c | 2 +- plugins/LadspaEffect/swh/foldover_1213.c | 2 +- plugins/LadspaEffect/swh/foverdrive_1196.c | 2 +- plugins/LadspaEffect/swh/freq_tracker_1418.c | 2 +- plugins/LadspaEffect/swh/gate_1410.c | 2 +- plugins/LadspaEffect/swh/giant_flange_1437.c | 2 +- plugins/LadspaEffect/swh/gong_1424.c | 2 +- plugins/LadspaEffect/swh/gong_beater_1439.c | 2 +- plugins/LadspaEffect/swh/gsm_1215.c | 2 +- plugins/LadspaEffect/swh/gverb_1216.c | 2 +- plugins/LadspaEffect/swh/hard_limiter_1413.c | 2 +- plugins/LadspaEffect/swh/harmonic_gen_1220.c | 2 +- plugins/LadspaEffect/swh/hermes_filter_1200.c | 2 +- plugins/LadspaEffect/swh/highpass_iir_1890.c | 2 +- plugins/LadspaEffect/swh/hilbert_1440.c | 2 +- plugins/LadspaEffect/swh/imp_1199.c | 2 +- plugins/LadspaEffect/swh/impulse_1885.c | 2 +- plugins/LadspaEffect/swh/inv_1429.c | 2 +- plugins/LadspaEffect/swh/karaoke_1409.c | 2 +- plugins/LadspaEffect/swh/latency_1914.c | 2 +- plugins/LadspaEffect/swh/lcr_delay_1436.c | 2 +- plugins/LadspaEffect/swh/lowpass_iir_1891.c | 2 +- plugins/LadspaEffect/swh/ls_filter_1908.c | 2 +- plugins/LadspaEffect/swh/matrix_ms_st_1421.c | 2 +- plugins/LadspaEffect/swh/matrix_spatialiser_1422.c | 2 +- plugins/LadspaEffect/swh/matrix_st_ms_1420.c | 2 +- plugins/LadspaEffect/swh/mbeq_1197.c | 2 +- plugins/LadspaEffect/swh/mod_delay_1419.c | 2 +- plugins/LadspaEffect/swh/multivoice_chorus_1201.c | 2 +- plugins/LadspaEffect/swh/notch_iir_1894.c | 2 +- plugins/LadspaEffect/swh/phasers_1217.c | 2 +- plugins/LadspaEffect/swh/pitch_scale_1193.c | 2 +- plugins/LadspaEffect/swh/pitch_scale_1194.c | 2 +- plugins/LadspaEffect/swh/plate_1423.c | 2 +- plugins/LadspaEffect/swh/pointer_cast_1910.c | 2 +- plugins/LadspaEffect/swh/rate_shifter_1417.c | 2 +- plugins/LadspaEffect/swh/retro_flange_1208.c | 2 +- plugins/LadspaEffect/swh/revdelay_1605.c | 2 +- plugins/LadspaEffect/swh/ringmod_1188.c | 2 +- plugins/LadspaEffect/swh/satan_maximiser_1408.c | 2 +- plugins/LadspaEffect/swh/sc1_1425.c | 2 +- plugins/LadspaEffect/swh/sc2_1426.c | 2 +- plugins/LadspaEffect/swh/sc3_1427.c | 2 +- plugins/LadspaEffect/swh/sc4_1882.c | 2 +- plugins/LadspaEffect/swh/sc4m_1916.c | 2 +- plugins/LadspaEffect/swh/se4_1883.c | 2 +- plugins/LadspaEffect/swh/shaper_1187.c | 2 +- plugins/LadspaEffect/swh/sifter_1210.c | 2 +- plugins/LadspaEffect/swh/sin_cos_1881.c | 2 +- plugins/LadspaEffect/swh/single_para_1203.c | 2 +- plugins/LadspaEffect/swh/sinus_wavewrapper_1198.c | 2 +- plugins/LadspaEffect/swh/smooth_decimate_1414.c | 2 +- plugins/LadspaEffect/swh/split_1406.c | 2 +- plugins/LadspaEffect/swh/step_muxer_1212.c | 2 +- plugins/LadspaEffect/swh/surround_encoder_1401.c | 2 +- plugins/LadspaEffect/swh/svf_1214.c | 2 +- plugins/LadspaEffect/swh/tape_delay_1211.c | 2 +- plugins/LadspaEffect/swh/transient_1206.c | 2 +- plugins/LadspaEffect/swh/triple_para_1204.c | 2 +- plugins/LadspaEffect/swh/valve_1209.c | 2 +- plugins/LadspaEffect/swh/valve_rect_1405.c | 2 +- plugins/LadspaEffect/swh/vocoder_1337.c | 4 ++-- plugins/LadspaEffect/swh/vynil_1905.c | 2 +- plugins/LadspaEffect/swh/wave_terrain_1412.c | 2 +- plugins/LadspaEffect/swh/xfade_1915.c | 2 +- plugins/LadspaEffect/swh/zm1_1428.c | 2 +- 94 files changed, 95 insertions(+), 95 deletions(-) diff --git a/plugins/LadspaEffect/swh/alias_1407.c b/plugins/LadspaEffect/swh/alias_1407.c index 444d9ed28..c3190e36c 100644 --- a/plugins/LadspaEffect/swh/alias_1407.c +++ b/plugins/LadspaEffect/swh/alias_1407.c @@ -240,7 +240,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (aliasDescriptor) { free((LADSPA_PortDescriptor *)aliasDescriptor->PortDescriptors); free((char **)aliasDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/allpass_1895.c b/plugins/LadspaEffect/swh/allpass_1895.c index 062f4e32f..8bbf534b0 100644 --- a/plugins/LadspaEffect/swh/allpass_1895.c +++ b/plugins/LadspaEffect/swh/allpass_1895.c @@ -1346,7 +1346,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (allpass_nDescriptor) { free((LADSPA_PortDescriptor *)allpass_nDescriptor->PortDescriptors); free((char **)allpass_nDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/am_pitchshift_1433.c b/plugins/LadspaEffect/swh/am_pitchshift_1433.c index adc5f3029..65130c6df 100644 --- a/plugins/LadspaEffect/swh/am_pitchshift_1433.c +++ b/plugins/LadspaEffect/swh/am_pitchshift_1433.c @@ -455,7 +455,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (amPitchshiftDescriptor) { free((LADSPA_PortDescriptor *)amPitchshiftDescriptor->PortDescriptors); free((char **)amPitchshiftDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/amp_1181.c b/plugins/LadspaEffect/swh/amp_1181.c index 2bf8dd3d8..30e870538 100644 --- a/plugins/LadspaEffect/swh/amp_1181.c +++ b/plugins/LadspaEffect/swh/amp_1181.c @@ -233,7 +233,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (ampDescriptor) { free((LADSPA_PortDescriptor *)ampDescriptor->PortDescriptors); free((char **)ampDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/bandpass_a_iir_1893.c b/plugins/LadspaEffect/swh/bandpass_a_iir_1893.c index c477a4b88..e46f06511 100644 --- a/plugins/LadspaEffect/swh/bandpass_a_iir_1893.c +++ b/plugins/LadspaEffect/swh/bandpass_a_iir_1893.c @@ -277,7 +277,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (bandpass_a_iirDescriptor) { free((LADSPA_PortDescriptor *)bandpass_a_iirDescriptor->PortDescriptors); free((char **)bandpass_a_iirDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/bandpass_iir_1892.c b/plugins/LadspaEffect/swh/bandpass_iir_1892.c index 4f160c4f0..b723b8717 100644 --- a/plugins/LadspaEffect/swh/bandpass_iir_1892.c +++ b/plugins/LadspaEffect/swh/bandpass_iir_1892.c @@ -343,7 +343,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (bandpass_iirDescriptor) { free((LADSPA_PortDescriptor *)bandpass_iirDescriptor->PortDescriptors); free((char **)bandpass_iirDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/bode_shifter_1431.c b/plugins/LadspaEffect/swh/bode_shifter_1431.c index 597864a18..4c48355c6 100644 --- a/plugins/LadspaEffect/swh/bode_shifter_1431.c +++ b/plugins/LadspaEffect/swh/bode_shifter_1431.c @@ -458,7 +458,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (bodeShifterDescriptor) { free((LADSPA_PortDescriptor *)bodeShifterDescriptor->PortDescriptors); free((char **)bodeShifterDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/bode_shifter_cv_1432.c b/plugins/LadspaEffect/swh/bode_shifter_cv_1432.c index 067e17c21..41fb4f043 100644 --- a/plugins/LadspaEffect/swh/bode_shifter_cv_1432.c +++ b/plugins/LadspaEffect/swh/bode_shifter_cv_1432.c @@ -523,7 +523,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (bodeShifterCVDescriptor) { free((LADSPA_PortDescriptor *)bodeShifterCVDescriptor->PortDescriptors); free((char **)bodeShifterCVDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/butterworth_1902.c b/plugins/LadspaEffect/swh/butterworth_1902.c index 74bd6d489..0e218babe 100644 --- a/plugins/LadspaEffect/swh/butterworth_1902.c +++ b/plugins/LadspaEffect/swh/butterworth_1902.c @@ -741,7 +741,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (bwxover_iirDescriptor) { free((LADSPA_PortDescriptor *)bwxover_iirDescriptor->PortDescriptors); free((char **)bwxover_iirDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/chebstortion_1430.c b/plugins/LadspaEffect/swh/chebstortion_1430.c index baa5d9694..d7b71afa7 100644 --- a/plugins/LadspaEffect/swh/chebstortion_1430.c +++ b/plugins/LadspaEffect/swh/chebstortion_1430.c @@ -399,7 +399,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (chebstortionDescriptor) { free((LADSPA_PortDescriptor *)chebstortionDescriptor->PortDescriptors); free((char **)chebstortionDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/comb_1190.c b/plugins/LadspaEffect/swh/comb_1190.c index 7f72b8cd7..1e01570ae 100644 --- a/plugins/LadspaEffect/swh/comb_1190.c +++ b/plugins/LadspaEffect/swh/comb_1190.c @@ -340,7 +340,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (combDescriptor) { free((LADSPA_PortDescriptor *)combDescriptor->PortDescriptors); free((char **)combDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/comb_1887.c b/plugins/LadspaEffect/swh/comb_1887.c index 81a7268bd..23dc53400 100644 --- a/plugins/LadspaEffect/swh/comb_1887.c +++ b/plugins/LadspaEffect/swh/comb_1887.c @@ -1352,7 +1352,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (comb_nDescriptor) { free((LADSPA_PortDescriptor *)comb_nDescriptor->PortDescriptors); free((char **)comb_nDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/comb_splitter_1411.c b/plugins/LadspaEffect/swh/comb_splitter_1411.c index 1ffb152d7..70d78e726 100644 --- a/plugins/LadspaEffect/swh/comb_splitter_1411.c +++ b/plugins/LadspaEffect/swh/comb_splitter_1411.c @@ -341,7 +341,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (combSplitterDescriptor) { free((LADSPA_PortDescriptor *)combSplitterDescriptor->PortDescriptors); free((char **)combSplitterDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/const_1909.c b/plugins/LadspaEffect/swh/const_1909.c index 3bfc221ef..31633b276 100644 --- a/plugins/LadspaEffect/swh/const_1909.c +++ b/plugins/LadspaEffect/swh/const_1909.c @@ -250,7 +250,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (constDescriptor) { free((LADSPA_PortDescriptor *)constDescriptor->PortDescriptors); free((char **)constDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/crossover_dist_1404.c b/plugins/LadspaEffect/swh/crossover_dist_1404.c index fdffacf68..7ad6c4d3b 100644 --- a/plugins/LadspaEffect/swh/crossover_dist_1404.c +++ b/plugins/LadspaEffect/swh/crossover_dist_1404.c @@ -276,7 +276,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (crossoverDistDescriptor) { free((LADSPA_PortDescriptor *)crossoverDistDescriptor->PortDescriptors); free((char **)crossoverDistDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/dc_remove_1207.c b/plugins/LadspaEffect/swh/dc_remove_1207.c index 76593f8ca..ff795118f 100644 --- a/plugins/LadspaEffect/swh/dc_remove_1207.c +++ b/plugins/LadspaEffect/swh/dc_remove_1207.c @@ -235,7 +235,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (dcRemoveDescriptor) { free((LADSPA_PortDescriptor *)dcRemoveDescriptor->PortDescriptors); free((char **)dcRemoveDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/decay_1886.c b/plugins/LadspaEffect/swh/decay_1886.c index da878478b..eab8570d3 100644 --- a/plugins/LadspaEffect/swh/decay_1886.c +++ b/plugins/LadspaEffect/swh/decay_1886.c @@ -325,7 +325,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (decayDescriptor) { free((LADSPA_PortDescriptor *)decayDescriptor->PortDescriptors); free((char **)decayDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/decimator_1202.c b/plugins/LadspaEffect/swh/decimator_1202.c index 2975605bd..6765d350e 100644 --- a/plugins/LadspaEffect/swh/decimator_1202.c +++ b/plugins/LadspaEffect/swh/decimator_1202.c @@ -335,7 +335,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (decimatorDescriptor) { free((LADSPA_PortDescriptor *)decimatorDescriptor->PortDescriptors); free((char **)decimatorDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/declip_1195.c b/plugins/LadspaEffect/swh/declip_1195.c index f25417976..bc3db16c2 100644 --- a/plugins/LadspaEffect/swh/declip_1195.c +++ b/plugins/LadspaEffect/swh/declip_1195.c @@ -235,7 +235,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (declipDescriptor) { free((LADSPA_PortDescriptor *)declipDescriptor->PortDescriptors); free((char **)declipDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/delay_1898.c b/plugins/LadspaEffect/swh/delay_1898.c index 998c1bbbd..57c8f0195 100644 --- a/plugins/LadspaEffect/swh/delay_1898.c +++ b/plugins/LadspaEffect/swh/delay_1898.c @@ -1093,7 +1093,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (delay_nDescriptor) { free((LADSPA_PortDescriptor *)delay_nDescriptor->PortDescriptors); free((char **)delay_nDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/delayorama_1402.c b/plugins/LadspaEffect/swh/delayorama_1402.c index a0cb2a861..a5d1bcce8 100644 --- a/plugins/LadspaEffect/swh/delayorama_1402.c +++ b/plugins/LadspaEffect/swh/delayorama_1402.c @@ -847,7 +847,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (delayoramaDescriptor) { free((LADSPA_PortDescriptor *)delayoramaDescriptor->PortDescriptors); free((char **)delayoramaDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/diode_1185.c b/plugins/LadspaEffect/swh/diode_1185.c index cfc2d22d4..bce602ae4 100644 --- a/plugins/LadspaEffect/swh/diode_1185.c +++ b/plugins/LadspaEffect/swh/diode_1185.c @@ -264,7 +264,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (diodeDescriptor) { free((LADSPA_PortDescriptor *)diodeDescriptor->PortDescriptors); free((char **)diodeDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/divider_1186.c b/plugins/LadspaEffect/swh/divider_1186.c index cf9fad685..6c7de0170 100644 --- a/plugins/LadspaEffect/swh/divider_1186.c +++ b/plugins/LadspaEffect/swh/divider_1186.c @@ -331,7 +331,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (dividerDescriptor) { free((LADSPA_PortDescriptor *)dividerDescriptor->PortDescriptors); free((char **)dividerDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/dj_eq_1901.c b/plugins/LadspaEffect/swh/dj_eq_1901.c index 950eedad4..a4baa9602 100644 --- a/plugins/LadspaEffect/swh/dj_eq_1901.c +++ b/plugins/LadspaEffect/swh/dj_eq_1901.c @@ -674,7 +674,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (dj_eq_monoDescriptor) { free((LADSPA_PortDescriptor *)dj_eq_monoDescriptor->PortDescriptors); free((char **)dj_eq_monoDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/dj_flanger_1438.c b/plugins/LadspaEffect/swh/dj_flanger_1438.c index b970886a9..1c7a9ce2d 100644 --- a/plugins/LadspaEffect/swh/dj_flanger_1438.c +++ b/plugins/LadspaEffect/swh/dj_flanger_1438.c @@ -472,7 +472,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (djFlangerDescriptor) { free((LADSPA_PortDescriptor *)djFlangerDescriptor->PortDescriptors); free((char **)djFlangerDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/dyson_compress_1403.c b/plugins/LadspaEffect/swh/dyson_compress_1403.c index 22cc0fa94..552edb7b0 100644 --- a/plugins/LadspaEffect/swh/dyson_compress_1403.c +++ b/plugins/LadspaEffect/swh/dyson_compress_1403.c @@ -885,7 +885,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (dysonCompressDescriptor) { free((LADSPA_PortDescriptor *)dysonCompressDescriptor->PortDescriptors); free((char **)dysonCompressDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/fad_delay_1192.c b/plugins/LadspaEffect/swh/fad_delay_1192.c index 85d0c3dee..9d4ec77b3 100644 --- a/plugins/LadspaEffect/swh/fad_delay_1192.c +++ b/plugins/LadspaEffect/swh/fad_delay_1192.c @@ -388,7 +388,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (fadDelayDescriptor) { free((LADSPA_PortDescriptor *)fadDelayDescriptor->PortDescriptors); free((char **)fadDelayDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/fast_lookahead_limiter_1913.c b/plugins/LadspaEffect/swh/fast_lookahead_limiter_1913.c index 8295e2298..8589caf3a 100644 --- a/plugins/LadspaEffect/swh/fast_lookahead_limiter_1913.c +++ b/plugins/LadspaEffect/swh/fast_lookahead_limiter_1913.c @@ -703,7 +703,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (fastLookaheadLimiterDescriptor) { free((LADSPA_PortDescriptor *)fastLookaheadLimiterDescriptor->PortDescriptors); free((char **)fastLookaheadLimiterDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/flanger_1191.c b/plugins/LadspaEffect/swh/flanger_1191.c index e542316fd..e5741f2e5 100644 --- a/plugins/LadspaEffect/swh/flanger_1191.c +++ b/plugins/LadspaEffect/swh/flanger_1191.c @@ -544,7 +544,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (flangerDescriptor) { free((LADSPA_PortDescriptor *)flangerDescriptor->PortDescriptors); free((char **)flangerDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/foldover_1213.c b/plugins/LadspaEffect/swh/foldover_1213.c index 8f2ad857e..5f4884476 100644 --- a/plugins/LadspaEffect/swh/foldover_1213.c +++ b/plugins/LadspaEffect/swh/foldover_1213.c @@ -255,7 +255,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (foldoverDescriptor) { free((LADSPA_PortDescriptor *)foldoverDescriptor->PortDescriptors); free((char **)foldoverDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/foverdrive_1196.c b/plugins/LadspaEffect/swh/foverdrive_1196.c index 94306d01e..f608e3ade 100644 --- a/plugins/LadspaEffect/swh/foverdrive_1196.c +++ b/plugins/LadspaEffect/swh/foverdrive_1196.c @@ -234,7 +234,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (foverdriveDescriptor) { free((LADSPA_PortDescriptor *)foverdriveDescriptor->PortDescriptors); free((char **)foverdriveDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/freq_tracker_1418.c b/plugins/LadspaEffect/swh/freq_tracker_1418.c index 831c6de15..73a7111ea 100644 --- a/plugins/LadspaEffect/swh/freq_tracker_1418.c +++ b/plugins/LadspaEffect/swh/freq_tracker_1418.c @@ -319,7 +319,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (freqTrackerDescriptor) { free((LADSPA_PortDescriptor *)freqTrackerDescriptor->PortDescriptors); free((char **)freqTrackerDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/gate_1410.c b/plugins/LadspaEffect/swh/gate_1410.c index d6fdf7da8..71527ace2 100644 --- a/plugins/LadspaEffect/swh/gate_1410.c +++ b/plugins/LadspaEffect/swh/gate_1410.c @@ -582,7 +582,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (gateDescriptor) { free((LADSPA_PortDescriptor *)gateDescriptor->PortDescriptors); free((char **)gateDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/giant_flange_1437.c b/plugins/LadspaEffect/swh/giant_flange_1437.c index dd2031806..fd022d7b1 100644 --- a/plugins/LadspaEffect/swh/giant_flange_1437.c +++ b/plugins/LadspaEffect/swh/giant_flange_1437.c @@ -637,7 +637,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (giantFlangeDescriptor) { free((LADSPA_PortDescriptor *)giantFlangeDescriptor->PortDescriptors); free((char **)giantFlangeDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/gong_1424.c b/plugins/LadspaEffect/swh/gong_1424.c index ea2f4161d..b7e0656b2 100644 --- a/plugins/LadspaEffect/swh/gong_1424.c +++ b/plugins/LadspaEffect/swh/gong_1424.c @@ -947,7 +947,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (gongDescriptor) { free((LADSPA_PortDescriptor *)gongDescriptor->PortDescriptors); free((char **)gongDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/gong_beater_1439.c b/plugins/LadspaEffect/swh/gong_beater_1439.c index 26f967a11..b80e164d3 100644 --- a/plugins/LadspaEffect/swh/gong_beater_1439.c +++ b/plugins/LadspaEffect/swh/gong_beater_1439.c @@ -400,7 +400,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (gongBeaterDescriptor) { free((LADSPA_PortDescriptor *)gongBeaterDescriptor->PortDescriptors); free((char **)gongBeaterDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/gsm_1215.c b/plugins/LadspaEffect/swh/gsm_1215.c index 279e2b1c1..55c0f2628 100644 --- a/plugins/LadspaEffect/swh/gsm_1215.c +++ b/plugins/LadspaEffect/swh/gsm_1215.c @@ -493,7 +493,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (gsmDescriptor) { free((LADSPA_PortDescriptor *)gsmDescriptor->PortDescriptors); free((char **)gsmDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/gverb_1216.c b/plugins/LadspaEffect/swh/gverb_1216.c index d7e5a9214..e9bdac87d 100644 --- a/plugins/LadspaEffect/swh/gverb_1216.c +++ b/plugins/LadspaEffect/swh/gverb_1216.c @@ -429,7 +429,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (gverbDescriptor) { free((LADSPA_PortDescriptor *)gverbDescriptor->PortDescriptors); free((char **)gverbDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/hard_limiter_1413.c b/plugins/LadspaEffect/swh/hard_limiter_1413.c index ab1ab0f62..bf41e6acd 100644 --- a/plugins/LadspaEffect/swh/hard_limiter_1413.c +++ b/plugins/LadspaEffect/swh/hard_limiter_1413.c @@ -286,7 +286,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (hardLimiterDescriptor) { free((LADSPA_PortDescriptor *)hardLimiterDescriptor->PortDescriptors); free((char **)hardLimiterDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/harmonic_gen_1220.c b/plugins/LadspaEffect/swh/harmonic_gen_1220.c index 26c19630f..bbd2324c7 100644 --- a/plugins/LadspaEffect/swh/harmonic_gen_1220.c +++ b/plugins/LadspaEffect/swh/harmonic_gen_1220.c @@ -542,7 +542,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (harmonicGenDescriptor) { free((LADSPA_PortDescriptor *)harmonicGenDescriptor->PortDescriptors); free((char **)harmonicGenDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/hermes_filter_1200.c b/plugins/LadspaEffect/swh/hermes_filter_1200.c index a15d7c9e8..d313d376e 100644 --- a/plugins/LadspaEffect/swh/hermes_filter_1200.c +++ b/plugins/LadspaEffect/swh/hermes_filter_1200.c @@ -1998,7 +1998,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (hermesFilterDescriptor) { free((LADSPA_PortDescriptor *)hermesFilterDescriptor->PortDescriptors); free((char **)hermesFilterDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/highpass_iir_1890.c b/plugins/LadspaEffect/swh/highpass_iir_1890.c index e0bca2a14..d00ddd159 100644 --- a/plugins/LadspaEffect/swh/highpass_iir_1890.c +++ b/plugins/LadspaEffect/swh/highpass_iir_1890.c @@ -278,7 +278,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (highpass_iirDescriptor) { free((LADSPA_PortDescriptor *)highpass_iirDescriptor->PortDescriptors); free((char **)highpass_iirDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/hilbert_1440.c b/plugins/LadspaEffect/swh/hilbert_1440.c index 4a6546b27..a52b21390 100644 --- a/plugins/LadspaEffect/swh/hilbert_1440.c +++ b/plugins/LadspaEffect/swh/hilbert_1440.c @@ -316,7 +316,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (hilbertDescriptor) { free((LADSPA_PortDescriptor *)hilbertDescriptor->PortDescriptors); free((char **)hilbertDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/imp_1199.c b/plugins/LadspaEffect/swh/imp_1199.c index 62c2deff3..ec1b35028 100644 --- a/plugins/LadspaEffect/swh/imp_1199.c +++ b/plugins/LadspaEffect/swh/imp_1199.c @@ -628,7 +628,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (impDescriptor) { free((LADSPA_PortDescriptor *)impDescriptor->PortDescriptors); free((char **)impDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/impulse_1885.c b/plugins/LadspaEffect/swh/impulse_1885.c index e4ebd2d41..cc53506b7 100644 --- a/plugins/LadspaEffect/swh/impulse_1885.c +++ b/plugins/LadspaEffect/swh/impulse_1885.c @@ -257,7 +257,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (impulse_fcDescriptor) { free((LADSPA_PortDescriptor *)impulse_fcDescriptor->PortDescriptors); free((char **)impulse_fcDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/inv_1429.c b/plugins/LadspaEffect/swh/inv_1429.c index 1a38faff6..e0a6f7715 100644 --- a/plugins/LadspaEffect/swh/inv_1429.c +++ b/plugins/LadspaEffect/swh/inv_1429.c @@ -207,7 +207,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (invDescriptor) { free((LADSPA_PortDescriptor *)invDescriptor->PortDescriptors); free((char **)invDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/karaoke_1409.c b/plugins/LadspaEffect/swh/karaoke_1409.c index 4c3091f77..9dd09c336 100644 --- a/plugins/LadspaEffect/swh/karaoke_1409.c +++ b/plugins/LadspaEffect/swh/karaoke_1409.c @@ -274,7 +274,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (karaokeDescriptor) { free((LADSPA_PortDescriptor *)karaokeDescriptor->PortDescriptors); free((char **)karaokeDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/latency_1914.c b/plugins/LadspaEffect/swh/latency_1914.c index 5744a2086..202b65baa 100644 --- a/plugins/LadspaEffect/swh/latency_1914.c +++ b/plugins/LadspaEffect/swh/latency_1914.c @@ -259,7 +259,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (artificialLatencyDescriptor) { free((LADSPA_PortDescriptor *)artificialLatencyDescriptor->PortDescriptors); free((char **)artificialLatencyDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/lcr_delay_1436.c b/plugins/LadspaEffect/swh/lcr_delay_1436.c index 5ae8db3bc..f9d4df7b6 100644 --- a/plugins/LadspaEffect/swh/lcr_delay_1436.c +++ b/plugins/LadspaEffect/swh/lcr_delay_1436.c @@ -733,7 +733,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (lcrDelayDescriptor) { free((LADSPA_PortDescriptor *)lcrDelayDescriptor->PortDescriptors); free((char **)lcrDelayDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/lowpass_iir_1891.c b/plugins/LadspaEffect/swh/lowpass_iir_1891.c index be1c806c1..a8ecb9ad4 100644 --- a/plugins/LadspaEffect/swh/lowpass_iir_1891.c +++ b/plugins/LadspaEffect/swh/lowpass_iir_1891.c @@ -280,7 +280,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (lowpass_iirDescriptor) { free((LADSPA_PortDescriptor *)lowpass_iirDescriptor->PortDescriptors); free((char **)lowpass_iirDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/ls_filter_1908.c b/plugins/LadspaEffect/swh/ls_filter_1908.c index 97c366a40..e67177bcd 100644 --- a/plugins/LadspaEffect/swh/ls_filter_1908.c +++ b/plugins/LadspaEffect/swh/ls_filter_1908.c @@ -308,7 +308,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (lsFilterDescriptor) { free((LADSPA_PortDescriptor *)lsFilterDescriptor->PortDescriptors); free((char **)lsFilterDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/matrix_ms_st_1421.c b/plugins/LadspaEffect/swh/matrix_ms_st_1421.c index 2fddf9311..e1c81d8d2 100644 --- a/plugins/LadspaEffect/swh/matrix_ms_st_1421.c +++ b/plugins/LadspaEffect/swh/matrix_ms_st_1421.c @@ -266,7 +266,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (matrixMSStDescriptor) { free((LADSPA_PortDescriptor *)matrixMSStDescriptor->PortDescriptors); free((char **)matrixMSStDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/matrix_spatialiser_1422.c b/plugins/LadspaEffect/swh/matrix_spatialiser_1422.c index 7812ddfff..74b3f1cfd 100644 --- a/plugins/LadspaEffect/swh/matrix_spatialiser_1422.c +++ b/plugins/LadspaEffect/swh/matrix_spatialiser_1422.c @@ -424,7 +424,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (matrixSpatialiserDescriptor) { free((LADSPA_PortDescriptor *)matrixSpatialiserDescriptor->PortDescriptors); free((char **)matrixSpatialiserDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/matrix_st_ms_1420.c b/plugins/LadspaEffect/swh/matrix_st_ms_1420.c index 8c97c7cb9..0d18f98b2 100644 --- a/plugins/LadspaEffect/swh/matrix_st_ms_1420.c +++ b/plugins/LadspaEffect/swh/matrix_st_ms_1420.c @@ -245,7 +245,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (matrixStMSDescriptor) { free((LADSPA_PortDescriptor *)matrixStMSDescriptor->PortDescriptors); free((char **)matrixStMSDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/mbeq_1197.c b/plugins/LadspaEffect/swh/mbeq_1197.c index a9bea01fe..e1c88d33e 100644 --- a/plugins/LadspaEffect/swh/mbeq_1197.c +++ b/plugins/LadspaEffect/swh/mbeq_1197.c @@ -885,7 +885,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (mbeqDescriptor) { free((LADSPA_PortDescriptor *)mbeqDescriptor->PortDescriptors); free((char **)mbeqDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/mod_delay_1419.c b/plugins/LadspaEffect/swh/mod_delay_1419.c index b27a7612e..30ae3e553 100644 --- a/plugins/LadspaEffect/swh/mod_delay_1419.c +++ b/plugins/LadspaEffect/swh/mod_delay_1419.c @@ -318,7 +318,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (modDelayDescriptor) { free((LADSPA_PortDescriptor *)modDelayDescriptor->PortDescriptors); free((char **)modDelayDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/multivoice_chorus_1201.c b/plugins/LadspaEffect/swh/multivoice_chorus_1201.c index 5f69bf04e..24c100dd4 100644 --- a/plugins/LadspaEffect/swh/multivoice_chorus_1201.c +++ b/plugins/LadspaEffect/swh/multivoice_chorus_1201.c @@ -656,7 +656,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (multivoiceChorusDescriptor) { free((LADSPA_PortDescriptor *)multivoiceChorusDescriptor->PortDescriptors); free((char **)multivoiceChorusDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/notch_iir_1894.c b/plugins/LadspaEffect/swh/notch_iir_1894.c index 396e44fa2..69009967b 100644 --- a/plugins/LadspaEffect/swh/notch_iir_1894.c +++ b/plugins/LadspaEffect/swh/notch_iir_1894.c @@ -343,7 +343,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (notch_iirDescriptor) { free((LADSPA_PortDescriptor *)notch_iirDescriptor->PortDescriptors); free((char **)notch_iirDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/phasers_1217.c b/plugins/LadspaEffect/swh/phasers_1217.c index 14673e360..da50e11e8 100644 --- a/plugins/LadspaEffect/swh/phasers_1217.c +++ b/plugins/LadspaEffect/swh/phasers_1217.c @@ -1377,7 +1377,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (lfoPhaserDescriptor) { free((LADSPA_PortDescriptor *)lfoPhaserDescriptor->PortDescriptors); free((char **)lfoPhaserDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/pitch_scale_1193.c b/plugins/LadspaEffect/swh/pitch_scale_1193.c index c811a84bc..ce3f81163 100644 --- a/plugins/LadspaEffect/swh/pitch_scale_1193.c +++ b/plugins/LadspaEffect/swh/pitch_scale_1193.c @@ -327,7 +327,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (pitchScaleDescriptor) { free((LADSPA_PortDescriptor *)pitchScaleDescriptor->PortDescriptors); free((char **)pitchScaleDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/pitch_scale_1194.c b/plugins/LadspaEffect/swh/pitch_scale_1194.c index 747c16ea6..62d6be129 100644 --- a/plugins/LadspaEffect/swh/pitch_scale_1194.c +++ b/plugins/LadspaEffect/swh/pitch_scale_1194.c @@ -311,7 +311,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (pitchScaleHQDescriptor) { free((LADSPA_PortDescriptor *)pitchScaleHQDescriptor->PortDescriptors); free((char **)pitchScaleHQDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/plate_1423.c b/plugins/LadspaEffect/swh/plate_1423.c index 0127bb6f0..f73e8f138 100644 --- a/plugins/LadspaEffect/swh/plate_1423.c +++ b/plugins/LadspaEffect/swh/plate_1423.c @@ -401,7 +401,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (plateDescriptor) { free((LADSPA_PortDescriptor *)plateDescriptor->PortDescriptors); free((char **)plateDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/pointer_cast_1910.c b/plugins/LadspaEffect/swh/pointer_cast_1910.c index 464fb1b64..7465bd145 100644 --- a/plugins/LadspaEffect/swh/pointer_cast_1910.c +++ b/plugins/LadspaEffect/swh/pointer_cast_1910.c @@ -310,7 +310,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (pointerCastDistortionDescriptor) { free((LADSPA_PortDescriptor *)pointerCastDistortionDescriptor->PortDescriptors); free((char **)pointerCastDistortionDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/rate_shifter_1417.c b/plugins/LadspaEffect/swh/rate_shifter_1417.c index 750f82972..21e03cbc3 100644 --- a/plugins/LadspaEffect/swh/rate_shifter_1417.c +++ b/plugins/LadspaEffect/swh/rate_shifter_1417.c @@ -314,7 +314,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (rateShifterDescriptor) { free((LADSPA_PortDescriptor *)rateShifterDescriptor->PortDescriptors); free((char **)rateShifterDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/retro_flange_1208.c b/plugins/LadspaEffect/swh/retro_flange_1208.c index 5df5cc338..c96dff58e 100644 --- a/plugins/LadspaEffect/swh/retro_flange_1208.c +++ b/plugins/LadspaEffect/swh/retro_flange_1208.c @@ -581,7 +581,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (retroFlangeDescriptor) { free((LADSPA_PortDescriptor *)retroFlangeDescriptor->PortDescriptors); free((char **)retroFlangeDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/revdelay_1605.c b/plugins/LadspaEffect/swh/revdelay_1605.c index 1b014b902..e714ee5e2 100644 --- a/plugins/LadspaEffect/swh/revdelay_1605.c +++ b/plugins/LadspaEffect/swh/revdelay_1605.c @@ -540,7 +540,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (revdelayDescriptor) { free((LADSPA_PortDescriptor *)revdelayDescriptor->PortDescriptors); free((char **)revdelayDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/ringmod_1188.c b/plugins/LadspaEffect/swh/ringmod_1188.c index 5c4c16b39..393ad86b2 100644 --- a/plugins/LadspaEffect/swh/ringmod_1188.c +++ b/plugins/LadspaEffect/swh/ringmod_1188.c @@ -632,7 +632,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (ringmod_2i1oDescriptor) { free((LADSPA_PortDescriptor *)ringmod_2i1oDescriptor->PortDescriptors); free((char **)ringmod_2i1oDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/satan_maximiser_1408.c b/plugins/LadspaEffect/swh/satan_maximiser_1408.c index 913711574..acf99ac3c 100644 --- a/plugins/LadspaEffect/swh/satan_maximiser_1408.c +++ b/plugins/LadspaEffect/swh/satan_maximiser_1408.c @@ -344,7 +344,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (satanMaximiserDescriptor) { free((LADSPA_PortDescriptor *)satanMaximiserDescriptor->PortDescriptors); free((char **)satanMaximiserDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/sc1_1425.c b/plugins/LadspaEffect/swh/sc1_1425.c index 8a5e143ef..4b2ce94f1 100644 --- a/plugins/LadspaEffect/swh/sc1_1425.c +++ b/plugins/LadspaEffect/swh/sc1_1425.c @@ -473,7 +473,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (sc1Descriptor) { free((LADSPA_PortDescriptor *)sc1Descriptor->PortDescriptors); free((char **)sc1Descriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/sc2_1426.c b/plugins/LadspaEffect/swh/sc2_1426.c index a95abd777..dcad834bc 100644 --- a/plugins/LadspaEffect/swh/sc2_1426.c +++ b/plugins/LadspaEffect/swh/sc2_1426.c @@ -491,7 +491,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (sc2Descriptor) { free((LADSPA_PortDescriptor *)sc2Descriptor->PortDescriptors); free((char **)sc2Descriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/sc3_1427.c b/plugins/LadspaEffect/swh/sc3_1427.c index e89609bf5..27edde705 100644 --- a/plugins/LadspaEffect/swh/sc3_1427.c +++ b/plugins/LadspaEffect/swh/sc3_1427.c @@ -562,7 +562,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (sc3Descriptor) { free((LADSPA_PortDescriptor *)sc3Descriptor->PortDescriptors); free((char **)sc3Descriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/sc4_1882.c b/plugins/LadspaEffect/swh/sc4_1882.c index 5ac873302..3ff1fd002 100644 --- a/plugins/LadspaEffect/swh/sc4_1882.c +++ b/plugins/LadspaEffect/swh/sc4_1882.c @@ -618,7 +618,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (sc4Descriptor) { free((LADSPA_PortDescriptor *)sc4Descriptor->PortDescriptors); free((char **)sc4Descriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/sc4m_1916.c b/plugins/LadspaEffect/swh/sc4m_1916.c index ee9a952a5..4d92a213e 100644 --- a/plugins/LadspaEffect/swh/sc4m_1916.c +++ b/plugins/LadspaEffect/swh/sc4m_1916.c @@ -568,7 +568,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (sc4mDescriptor) { free((LADSPA_PortDescriptor *)sc4mDescriptor->PortDescriptors); free((char **)sc4mDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/se4_1883.c b/plugins/LadspaEffect/swh/se4_1883.c index 585d474e0..2c1ddce6e 100644 --- a/plugins/LadspaEffect/swh/se4_1883.c +++ b/plugins/LadspaEffect/swh/se4_1883.c @@ -614,7 +614,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (se4Descriptor) { free((LADSPA_PortDescriptor *)se4Descriptor->PortDescriptors); free((char **)se4Descriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/shaper_1187.c b/plugins/LadspaEffect/swh/shaper_1187.c index f036a57fb..89fc699b4 100644 --- a/plugins/LadspaEffect/swh/shaper_1187.c +++ b/plugins/LadspaEffect/swh/shaper_1187.c @@ -260,7 +260,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (shaperDescriptor) { free((LADSPA_PortDescriptor *)shaperDescriptor->PortDescriptors); free((char **)shaperDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/sifter_1210.c b/plugins/LadspaEffect/swh/sifter_1210.c index 8adcdbd27..1c05217b8 100644 --- a/plugins/LadspaEffect/swh/sifter_1210.c +++ b/plugins/LadspaEffect/swh/sifter_1210.c @@ -438,7 +438,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (sifterDescriptor) { free((LADSPA_PortDescriptor *)sifterDescriptor->PortDescriptors); free((char **)sifterDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/sin_cos_1881.c b/plugins/LadspaEffect/swh/sin_cos_1881.c index 500b6808b..d12977141 100644 --- a/plugins/LadspaEffect/swh/sin_cos_1881.c +++ b/plugins/LadspaEffect/swh/sin_cos_1881.c @@ -296,7 +296,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (sinCosDescriptor) { free((LADSPA_PortDescriptor *)sinCosDescriptor->PortDescriptors); free((char **)sinCosDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/single_para_1203.c b/plugins/LadspaEffect/swh/single_para_1203.c index d189c2682..ef322fe36 100644 --- a/plugins/LadspaEffect/swh/single_para_1203.c +++ b/plugins/LadspaEffect/swh/single_para_1203.c @@ -312,7 +312,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (singleParaDescriptor) { free((LADSPA_PortDescriptor *)singleParaDescriptor->PortDescriptors); free((char **)singleParaDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/sinus_wavewrapper_1198.c b/plugins/LadspaEffect/swh/sinus_wavewrapper_1198.c index 02be6d68a..d8dc7b2cc 100644 --- a/plugins/LadspaEffect/swh/sinus_wavewrapper_1198.c +++ b/plugins/LadspaEffect/swh/sinus_wavewrapper_1198.c @@ -244,7 +244,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (sinusWavewrapperDescriptor) { free((LADSPA_PortDescriptor *)sinusWavewrapperDescriptor->PortDescriptors); free((char **)sinusWavewrapperDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/smooth_decimate_1414.c b/plugins/LadspaEffect/swh/smooth_decimate_1414.c index 532b84b0a..c63e6ce6f 100644 --- a/plugins/LadspaEffect/swh/smooth_decimate_1414.c +++ b/plugins/LadspaEffect/swh/smooth_decimate_1414.c @@ -329,7 +329,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (smoothDecimateDescriptor) { free((LADSPA_PortDescriptor *)smoothDecimateDescriptor->PortDescriptors); free((char **)smoothDecimateDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/split_1406.c b/plugins/LadspaEffect/swh/split_1406.c index 48c9f7117..2fa1bee7b 100644 --- a/plugins/LadspaEffect/swh/split_1406.c +++ b/plugins/LadspaEffect/swh/split_1406.c @@ -240,7 +240,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (splitDescriptor) { free((LADSPA_PortDescriptor *)splitDescriptor->PortDescriptors); free((char **)splitDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/step_muxer_1212.c b/plugins/LadspaEffect/swh/step_muxer_1212.c index 94dc51e73..9c27b84e1 100644 --- a/plugins/LadspaEffect/swh/step_muxer_1212.c +++ b/plugins/LadspaEffect/swh/step_muxer_1212.c @@ -532,7 +532,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (stepMuxerDescriptor) { free((LADSPA_PortDescriptor *)stepMuxerDescriptor->PortDescriptors); free((char **)stepMuxerDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/surround_encoder_1401.c b/plugins/LadspaEffect/swh/surround_encoder_1401.c index c0f970e7e..d4b6ace01 100644 --- a/plugins/LadspaEffect/swh/surround_encoder_1401.c +++ b/plugins/LadspaEffect/swh/surround_encoder_1401.c @@ -414,7 +414,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (surroundEncoderDescriptor) { free((LADSPA_PortDescriptor *)surroundEncoderDescriptor->PortDescriptors); free((char **)surroundEncoderDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/svf_1214.c b/plugins/LadspaEffect/swh/svf_1214.c index 24117d757..c1a74aa0b 100644 --- a/plugins/LadspaEffect/swh/svf_1214.c +++ b/plugins/LadspaEffect/swh/svf_1214.c @@ -408,7 +408,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (svfDescriptor) { free((LADSPA_PortDescriptor *)svfDescriptor->PortDescriptors); free((char **)svfDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/tape_delay_1211.c b/plugins/LadspaEffect/swh/tape_delay_1211.c index 5338dadfa..0b680ccf2 100644 --- a/plugins/LadspaEffect/swh/tape_delay_1211.c +++ b/plugins/LadspaEffect/swh/tape_delay_1211.c @@ -645,7 +645,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (tapeDelayDescriptor) { free((LADSPA_PortDescriptor *)tapeDelayDescriptor->PortDescriptors); free((char **)tapeDelayDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/transient_1206.c b/plugins/LadspaEffect/swh/transient_1206.c index 6e63fd526..782593e5e 100644 --- a/plugins/LadspaEffect/swh/transient_1206.c +++ b/plugins/LadspaEffect/swh/transient_1206.c @@ -465,7 +465,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (transientDescriptor) { free((LADSPA_PortDescriptor *)transientDescriptor->PortDescriptors); free((char **)transientDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/triple_para_1204.c b/plugins/LadspaEffect/swh/triple_para_1204.c index 8d3e63f3f..ef7a26b7c 100644 --- a/plugins/LadspaEffect/swh/triple_para_1204.c +++ b/plugins/LadspaEffect/swh/triple_para_1204.c @@ -593,7 +593,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (tripleParaDescriptor) { free((LADSPA_PortDescriptor *)tripleParaDescriptor->PortDescriptors); free((char **)tripleParaDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/valve_1209.c b/plugins/LadspaEffect/swh/valve_1209.c index 2ab03dd17..8f10428a0 100644 --- a/plugins/LadspaEffect/swh/valve_1209.c +++ b/plugins/LadspaEffect/swh/valve_1209.c @@ -332,7 +332,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (valveDescriptor) { free((LADSPA_PortDescriptor *)valveDescriptor->PortDescriptors); free((char **)valveDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/valve_rect_1405.c b/plugins/LadspaEffect/swh/valve_rect_1405.c index 9a87af2fa..a4191a4fd 100644 --- a/plugins/LadspaEffect/swh/valve_rect_1405.c +++ b/plugins/LadspaEffect/swh/valve_rect_1405.c @@ -401,7 +401,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (valveRectDescriptor) { free((LADSPA_PortDescriptor *)valveRectDescriptor->PortDescriptors); free((char **)valveRectDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/vocoder_1337.c b/plugins/LadspaEffect/swh/vocoder_1337.c index 0fb51688a..1ac1048df 100644 --- a/plugins/LadspaEffect/swh/vocoder_1337.c +++ b/plugins/LadspaEffect/swh/vocoder_1337.c @@ -420,9 +420,9 @@ void __attribute__((constructor)) swh_init() { /*****************************************************************************/ -/* _fini() is called automatically when the library is unloaded. */ +/* __attribute__((destructor)) swh_fini() is called automatically when the library is unloaded. */ void -_fini() { + __attribute__((destructor)) swh_fini() { long lIndex; if (g_psDescriptor) { free((char *)g_psDescriptor->Label); diff --git a/plugins/LadspaEffect/swh/vynil_1905.c b/plugins/LadspaEffect/swh/vynil_1905.c index 03112ac8e..187aa0f8f 100644 --- a/plugins/LadspaEffect/swh/vynil_1905.c +++ b/plugins/LadspaEffect/swh/vynil_1905.c @@ -712,7 +712,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (vynilDescriptor) { free((LADSPA_PortDescriptor *)vynilDescriptor->PortDescriptors); free((char **)vynilDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/wave_terrain_1412.c b/plugins/LadspaEffect/swh/wave_terrain_1412.c index 46791bdc1..bb77bd825 100644 --- a/plugins/LadspaEffect/swh/wave_terrain_1412.c +++ b/plugins/LadspaEffect/swh/wave_terrain_1412.c @@ -231,7 +231,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (waveTerrainDescriptor) { free((LADSPA_PortDescriptor *)waveTerrainDescriptor->PortDescriptors); free((char **)waveTerrainDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/xfade_1915.c b/plugins/LadspaEffect/swh/xfade_1915.c index 3d0d01d01..3a4ca2345 100644 --- a/plugins/LadspaEffect/swh/xfade_1915.c +++ b/plugins/LadspaEffect/swh/xfade_1915.c @@ -598,7 +598,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (xfadeDescriptor) { free((LADSPA_PortDescriptor *)xfadeDescriptor->PortDescriptors); free((char **)xfadeDescriptor->PortNames); diff --git a/plugins/LadspaEffect/swh/zm1_1428.c b/plugins/LadspaEffect/swh/zm1_1428.c index 5c3c19b5d..baf063bfc 100644 --- a/plugins/LadspaEffect/swh/zm1_1428.c +++ b/plugins/LadspaEffect/swh/zm1_1428.c @@ -232,7 +232,7 @@ void __attribute__((constructor)) swh_init() { } } -void _fini() { +void __attribute__((destructor)) swh_fini() { if (zm1Descriptor) { free((LADSPA_PortDescriptor *)zm1Descriptor->PortDescriptors); free((char **)zm1Descriptor->PortNames); From 6a5e7b18de0de1949c21d2bdf43f70801e8d75f7 Mon Sep 17 00:00:00 2001 From: Yann Collette Date: Wed, 14 May 2014 11:07:09 +0200 Subject: [PATCH 09/61] add lib64 directories to search for ladspa plugins --- src/core/ladspa_manager.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/core/ladspa_manager.cpp b/src/core/ladspa_manager.cpp index 4d78ebc5d..bd533fb87 100644 --- a/src/core/ladspa_manager.cpp +++ b/src/core/ladspa_manager.cpp @@ -46,10 +46,11 @@ ladspaManager::ladspaManager() ladspaDirectories.push_back( configManager::inst()->pluginDir() + "ladspa" ); #ifndef LMMS_BUILD_WIN32 ladspaDirectories.push_back( qApp->applicationDirPath() + '/' + LIB_DIR + "ladspa" ); - ladspaDirectories.push_back( "/usr/lib/lmms/ladspa" ); - ladspaDirectories.push_back( "/usr/local/lib/lmms/ladspa" ); ladspaDirectories.push_back( "/usr/lib/ladspa" ); + ladspaDirectories.push_back( "/usr/lib64/ladspa" ); ladspaDirectories.push_back( "/usr/local/lib/ladspa" ); + ladspaDirectories.push_back( "/usr/local/lib64/ladspa" ); + ladspaDirectories.push_back( "/Library/Audio/Plug-Ins/LADSPA" ); #endif for( QStringList::iterator it = ladspaDirectories.begin(); From a309ba077cb583e1e44ea0ed0b7f0404330a597a Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Fri, 30 May 2014 15:24:07 +0200 Subject: [PATCH 10/61] Bumped version number to 1.0.91 We can now distinguish between the new stable 1.1 branch and the master branch. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dac61e2f3..f4b1b2a8f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ INCLUDE(FindPkgConfig) SET(VERSION_MAJOR "1") SET(VERSION_MINOR "0") -SET(VERSION_PATCH "90") +SET(VERSION_PATCH "91") #SET(VERSION_SUFFIX "") SET(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}") IF(VERSION_SUFFIX) From f43678cbaef88cc62ea58f10e25126b042d82359 Mon Sep 17 00:00:00 2001 From: Vesa Date: Fri, 30 May 2014 23:00:20 +0300 Subject: [PATCH 11/61] PianoRoll: CSS stylability Most parts of piano roll are now stylable: - background color - note color - bar color (for volume bars) - grid color --- data/themes/default/style.css | 4 ++ include/PianoRoll.h | 22 ++++++- src/gui/PianoRoll.cpp | 111 ++++++++++++++++++++++------------ 3 files changed, 97 insertions(+), 40 deletions(-) diff --git a/data/themes/default/style.css b/data/themes/default/style.css index d5c973e87..3edb993bb 100644 --- a/data/themes/default/style.css +++ b/data/themes/default/style.css @@ -95,6 +95,10 @@ QMenu::indicator:selected { PianoRoll { background-color: rgb(0, 0, 0); + qproperty-gridColor: rgb( 128, 128, 128 ); + qproperty-noteModeColor: rgb( 255, 255, 255 ); + qproperty-noteColor: rgb( 119, 199, 216 ); + qproperty-barColor: #4afd85; } /* main toolbar oscilloscope - can have transparent bg now */ diff --git a/include/PianoRoll.h b/include/PianoRoll.h index ea6758214..157f3b051 100644 --- a/include/PianoRoll.h +++ b/include/PianoRoll.h @@ -53,6 +53,10 @@ class toolButton; class PianoRoll : public QWidget, public SerializingObject { Q_OBJECT + Q_PROPERTY( QColor gridColor READ gridColor WRITE setGridColor ) + Q_PROPERTY( QColor noteModeColor READ noteModeColor WRITE setNoteModeColor ) + Q_PROPERTY( QColor noteColor READ noteColor WRITE setNoteColor ) + Q_PROPERTY( QColor barColor READ barColor WRITE setBarColor ) public: /*! \brief Resets settings to default when e.g. creating a new project */ void reset(); @@ -93,7 +97,16 @@ public: } void setPauseIcon( bool pause ); - + + // qproperty acces functions + QColor gridColor() const; + void setGridColor( const QColor & _c ); + QColor noteModeColor() const; + void setNoteModeColor( const QColor & _c ); + QColor noteColor() const; + void setNoteColor( const QColor & _c ); + QColor barColor() const; + void setBarColor( const QColor & _c ); protected: virtual void closeEvent( QCloseEvent * _ce ); @@ -110,7 +123,7 @@ protected: int getKey( int _y ) const; static inline void drawNoteRect( QPainter & _p, int _x, int _y, - int _width, note * _n ); + int _width, note * _n, const QColor & noteCol ); void removeSelection(); void selectAll(); void getSelectedNotes( NoteVector & _selected_notes ); @@ -352,6 +365,11 @@ private: friend class engine; + // qproperty fields + QColor m_gridColor; + QColor m_noteModeColor; + QColor m_noteColor; + QColor m_barColor; signals: void positionChanged( const MidiTime & ); diff --git a/src/gui/PianoRoll.cpp b/src/gui/PianoRoll.cpp index a4f3847a5..f807beeb6 100644 --- a/src/gui/PianoRoll.cpp +++ b/src/gui/PianoRoll.cpp @@ -172,7 +172,11 @@ PianoRoll::PianoRoll() : m_editMode( ModeDraw ), m_mouseDownLeft( false ), m_mouseDownRight( false ), - m_scrollBack( false ) + m_scrollBack( false ), + m_gridColor( 0, 0, 0 ), + m_noteModeColor( 0, 0, 0 ), + m_noteColor( 0, 0, 0 ), + m_barColor( 0, 0, 0 ) { // gui names of edit modes m_nemStr.push_back( tr( "Note Volume" ) ); @@ -832,10 +836,36 @@ void PianoRoll::setPauseIcon( bool pause ) } +/** \brief qproperty access implementation */ + +QColor PianoRoll::gridColor() const +{ return m_gridColor; } + +void PianoRoll::setGridColor( const QColor & c ) +{ m_gridColor = c; } + +QColor PianoRoll::noteModeColor() const +{ return m_noteModeColor; } + +void PianoRoll::setNoteModeColor( const QColor & c ) +{ m_noteModeColor = c; } + +QColor PianoRoll::noteColor() const +{ return m_noteColor; } + +void PianoRoll::setNoteColor( const QColor & c ) +{ m_noteColor = c; } + +QColor PianoRoll::barColor() const +{ return m_barColor; } + +void PianoRoll::setBarColor( const QColor & c ) +{ m_barColor = c; } + inline void PianoRoll::drawNoteRect( QPainter & _p, int _x, int _y, - int _width, note * _n ) + int _width, note * _n, const QColor & noteCol ) { ++_x; ++_y; @@ -846,9 +876,8 @@ inline void PianoRoll::drawNoteRect( QPainter & _p, int _x, int _y, _width = 2; } - int volVal = qMin( 255, (int) ( - ( (float)( _n->getVolume() - MinVolume ) ) / - ( (float)( MaxVolume - MinVolume ) ) * 255.0f) ); + int volVal = qMin( 255, 25 + (int) ( ( (float)( _n->getVolume() - MinVolume ) ) / + ( (float)( MaxVolume - MinVolume ) ) * 230.0f) ); float rightPercent = qMin( 1.0f, ( (float)( _n->getPanning() - PanningLeft ) ) / ( (float)( PanningRight - PanningLeft ) ) * 2.0f ); @@ -857,8 +886,7 @@ inline void PianoRoll::drawNoteRect( QPainter & _p, int _x, int _y, ( (float)( PanningRight - _n->getPanning() ) ) / ( (float)( PanningRight - PanningLeft ) ) * 2.0f ); - const QColor defaultNoteColor( 0x77, 0xC7, 0xD8 ); - QColor col = defaultNoteColor; + QColor col = QColor( noteCol ); if( _n->length() < 0 ) { @@ -894,13 +922,13 @@ inline void PianoRoll::drawNoteRect( QPainter & _p, int _x, int _y, _p.setPen( Qt::SolidLine ); _p.setBrush( Qt::NoBrush ); - col = defaultNoteColor; + col = QColor( noteCol ); _p.setPen( QColor::fromHsv( col.hue(), col.saturation(), qMin( 255, volVal*1.7f ) ) ); _p.drawLine( _x, _y, _x + _width, _y ); _p.drawLine( _x, _y, _x, _y + KEY_LINE_HEIGHT - 2 ); - col = defaultNoteColor; + col = QColor( noteCol ); _p.setPen( QColor::fromHsv( col.hue(), col.saturation(), volVal/1.7 ) ); _p.drawLine( _x + _width, _y, _x + _width, _y + KEY_LINE_HEIGHT - 2 ); _p.drawLine( _x, _y + KEY_LINE_HEIGHT - 2, _x + _width, @@ -908,7 +936,7 @@ inline void PianoRoll::drawNoteRect( QPainter & _p, int _x, int _y, // that little tab thing on the end hinting at the user // to resize the note - _p.setPen( defaultNoteColor.lighter( 200 ) ); + _p.setPen( noteCol.lighter( 200 ) ); if( _width > 2 ) { _p.drawLine( _x + _width - 3, _y + 2, _x + _width - 3, @@ -927,7 +955,7 @@ inline void PianoRoll::drawDetuningInfo( QPainter & _p, note * _n, int _x, int _y ) { int middle_y = _y + KEY_LINE_HEIGHT / 2; - _p.setPen( QColor( 0x99, 0xAF, 0xFF ) ); + _p.setPen( noteColor() ); int old_x = 0; int old_y = 0; @@ -2851,11 +2879,19 @@ static void printNoteHeights(QPainter& p, int bottom, int width, int startKey) void PianoRoll::paintEvent( QPaintEvent * _pe ) { + QColor horizCol = QColor( gridColor() ); + QColor vertCol = QColor( gridColor() ); + QStyleOption opt; opt.initFrom( this ); QPainter p( this ); style()->drawPrimitive( QStyle::PE_Widget, &opt, &p, this ); + QColor bgColor = p.background().color(); + + // fill with bg color + p.fillRect( 0,0, width(), height(), bgColor ); + // set font-size to 8 p.setFont( pointSize<8>( p.font() ) ); @@ -2965,21 +3001,19 @@ void PianoRoll::paintEvent( QPaintEvent * _pe ) // label C-keys... if( static_cast( key % KeysPerOctave ) == Key_C ) { + const QString cLabel = "C" + QString::number( static_cast( key / KeysPerOctave ) ); p.setPen( QColor( 240, 240, 240 ) ); - p.drawText( C_KEY_LABEL_X + 1, y+14, "C" + - QString::number( static_cast( key / - KeysPerOctave ) ) ); + p.drawText( C_KEY_LABEL_X + 1, y+14, cLabel ); p.setPen( QColor( 0, 0, 0 ) ); - p.drawText( C_KEY_LABEL_X, y + 13, "C" + - QString::number( static_cast( key / - KeysPerOctave ) ) ); - p.setPen( QColor( 0x4F, 0x4F, 0x4F ) ); + p.drawText( C_KEY_LABEL_X, y + 13, cLabel ); + horizCol.setAlpha( 192 ); } else { - p.setPen( QColor( 0x3F, 0x3F, 0x3F ) ); + horizCol.setAlpha( 128 ); } // draw key-line + p.setPen( horizCol ); p.drawLine( WHITE_KEY_WIDTH, key_line_y, width(), key_line_y ); ++key; } @@ -3057,14 +3091,13 @@ void PianoRoll::paintEvent( QPaintEvent * _pe ) // erase the area below the piano, because there might be keys that // should be only half-visible p.fillRect( QRect( 0, keyAreaBottom(), - WHITE_KEY_WIDTH, noteEditBottom()-keyAreaBottom() ), - QColor( 0, 0, 0 ) ); + WHITE_KEY_WIDTH, noteEditBottom()-keyAreaBottom() ), bgColor ); // display note editing info QFont f = p.font(); f.setBold( false ); p.setFont( pointSize<10>( f ) ); - p.setPen( QColor( 255, 255, 255) ); + p.setPen( noteModeColor() ); p.drawText( QRect( 0, keyAreaBottom(), WHITE_KEY_WIDTH, noteEditBottom() - keyAreaBottom() ), Qt::AlignCenter | Qt::TextWordWrap, @@ -3107,17 +3140,19 @@ void PianoRoll::paintEvent( QPaintEvent * _pe ) // every tact-start needs to be a bright line if( tact_16th % spt == 0 ) { - p.setPen( QColor( 0x7F, 0x7F, 0x7F ) ); + p.setPen( gridColor() ); } // normal line else if( tact_16th % 4 == 0 ) { - p.setPen( QColor( 0x5F, 0x5F, 0x5F ) ); + vertCol.setAlpha( 160 ); + p.setPen( vertCol ); } // weak line else { - p.setPen( QColor( 0x3F, 0x3F, 0x3F ) ); + vertCol.setAlpha( 128 ); + p.setPen( vertCol ); } p.drawLine( (int)x, PR_TOP_MARGIN, (int)x, height() - @@ -3126,7 +3161,8 @@ void PianoRoll::paintEvent( QPaintEvent * _pe ) // extra 32nd's line if( show32nds ) { - p.setPen( QColor( 0x22, 0x22, 0x22 ) ); + vertCol.setAlpha( 80 ); + p.setPen( vertCol ); p.drawLine( (int)(x + pp16th/2) , PR_TOP_MARGIN, (int)(x + pp16th/2), height() - PR_BOTTOM_MARGIN ); @@ -3205,15 +3241,14 @@ void PianoRoll::paintEvent( QPaintEvent * _pe ) // note drawNoteRect( p, x + WHITE_KEY_WIDTH, y_base - key * KEY_LINE_HEIGHT, - note_width, *it ); + note_width, *it, noteColor() ); } // draw note editing stuff int editHandleTop = 0; if( m_noteEditMode == NoteEditVolume ) { - QColor color = QColor::fromHsv( 140, 221, - qMin(255, 60 + ( *it )->getVolume() ) ); + QColor color = barColor().lighter( 30 + ( ( *it )->getVolume() * 90 / MaxVolume ) ); if( ( *it )->selected() ) { color.setRgb( 0x00, 0x40, 0xC0 ); @@ -3231,7 +3266,7 @@ void PianoRoll::paintEvent( QPaintEvent * _pe ) } else if( m_noteEditMode == NoteEditPanning ) { - QColor color( 0x99, 0xAF, 0xFF ); + QColor color( noteColor() ); if( ( *it )->selected() ) { color.setRgb( 0x00, 0x40, 0xC0 ); @@ -3259,8 +3294,7 @@ void PianoRoll::paintEvent( QPaintEvent * _pe ) } } - p.setPen( QPen( QColor( 0x99, 0xAF, 0xFF ), - NE_LINE_WIDTH+2 ) ); + p.setPen( QPen( noteColor(), NE_LINE_WIDTH+2 ) ); p.drawPoints( editHandles ); } @@ -3269,7 +3303,8 @@ void PianoRoll::paintEvent( QPaintEvent * _pe ) QFont f = p.font(); f.setBold( true ); p.setFont( pointSize<14>( f ) ); - p.setPen( QColor( 0x4A, 0xFD, 0x85 ) ); + p.setPen( QApplication::palette().color( QPalette::Active, + QPalette::BrightText ) ); p.drawText( WHITE_KEY_WIDTH + 20, PR_TOP_MARGIN + 40, tr( "Please open a pattern by double-clicking " "on it!" ) ); @@ -3299,21 +3334,21 @@ void PianoRoll::paintEvent( QPaintEvent * _pe ) m_leftRightScroll->setPageStep( l ); } + // set alpha for horizontal lines + horizCol.setAlpha( 64 ); + // horizontal line for the key under the cursor if( validPattern() == true ) { int key_num = getKey( mapFromGlobal( QCursor::pos() ).y() ); p.fillRect( 10, keyAreaBottom() + 3 - KEY_LINE_HEIGHT * - ( key_num - m_startKey + 1 ), - width() - 10, KEY_LINE_HEIGHT - 7, - QColor( 64, 64, 64 ) ); + ( key_num - m_startKey + 1 ), width() - 10, KEY_LINE_HEIGHT - 7, horizCol ); } // bar to resize note edit area p.setClipRect( 0, 0, width(), height() ); p.fillRect( QRect( 0, keyAreaBottom(), - width()-PR_RIGHT_MARGIN, NOTE_EDIT_RESIZE_BAR ), - QColor( 64, 64, 64 ) ); + width()-PR_RIGHT_MARGIN, NOTE_EDIT_RESIZE_BAR ), horizCol ); const QPixmap * cursor = NULL; // draw current edit-mode-icon below the cursor From 56520431850cdb55a7e0347e497ea2d60536fe80 Mon Sep 17 00:00:00 2001 From: Vesa Date: Sat, 31 May 2014 01:47:59 +0300 Subject: [PATCH 12/61] AutomationEditor: improve zoom functionality - entire wheelevent code was written very... weirdly, I simplified it - fix bug with x zoom with mousewheel, no more getting stuck between 25/50 - ctrl+shift+mousewheel now zooms y-axis - ctrl+alt+mousewheel now changes quantization --- include/AutomationEditor.h | 22 +++++-- src/gui/AutomationEditor.cpp | 109 ++++++++++++++++++++++++----------- 2 files changed, 92 insertions(+), 39 deletions(-) diff --git a/include/AutomationEditor.h b/include/AutomationEditor.h index 9ff61bf25..2a39be6ff 100644 --- a/include/AutomationEditor.h +++ b/include/AutomationEditor.h @@ -1,9 +1,9 @@ /* * AutomationEditor.h - declaration of class AutomationEditor which is a window - * where you can edit dynamic values in an easy way + * where you can edit dynamic values in an easy way * * Copyright (c) 2006-2008 Javier Serrano Polo - * + * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * * This program is free software; you can redistribute it and/or @@ -23,8 +23,8 @@ * */ -#ifndef _AUTOMATION_EDITOR_H -#define _AUTOMATION_EDITOR_H +#ifndef AUTOMATION_EDITOR_H +#define AUTOMATION_EDITOR_H #include #include @@ -50,6 +50,9 @@ class toolButton; class AutomationEditor : public QWidget, public JournallingObject { Q_OBJECT + Q_PROPERTY( QColor gridColor READ gridColor WRITE setGridColor ) + Q_PROPERTY( QColor graphColor READ graphColor WRITE setGraphColor ) + Q_PROPERTY( QColor vertexColor READ vertexColor WRITE setVertexColor ) public: void setCurrentPattern( AutomationPattern * _new_pattern ); @@ -75,6 +78,13 @@ public: void setPauseIcon( bool pause ); + // qproperty access methods + QColor gridColor() const; + QColor graphColor() const; + QColor vertexColor() const; + void setGridColor( const QColor & c ); + void setGraphColor( const QColor & c ); + void setVertexColor( const QColor & c ); public slots: void update(); @@ -252,7 +262,9 @@ private: void drawAutomationPoint( QPainter & p, timeMap::iterator it ); bool inBBEditor(); - + QColor m_gridColor; + QColor m_graphColor; + QColor m_vertexColor; friend class engine; diff --git a/src/gui/AutomationEditor.cpp b/src/gui/AutomationEditor.cpp index 9c4536ca2..ab4c31457 100644 --- a/src/gui/AutomationEditor.cpp +++ b/src/gui/AutomationEditor.cpp @@ -1,6 +1,6 @@ /* * AutomationEditor.cpp - implementation of AutomationEditor which is used for - * actual setting of dynamic values + * actual setting of dynamic values * * Copyright (c) 2008-2014 Tobias Doerffel * Copyright (c) 2008-2013 Paul Giblock @@ -98,7 +98,10 @@ AutomationEditor::AutomationEditor() : m_y_delta( DEFAULT_Y_DELTA ), m_y_auto( TRUE ), m_editMode( DRAW ), - m_scrollBack( FALSE ) + m_scrollBack( FALSE ), + m_gridColor( 0,0,0 ), + m_graphColor( 0,0,0 ), + m_vertexColor( 0,0,0 ) { connect( this, SIGNAL( currentPatternChanged() ), this, SLOT( updateAfterPatternChange() ), @@ -358,7 +361,7 @@ AutomationEditor::AutomationEditor() : m_zoomingYComboBox->setFixedSize( 80, 22 ); m_zoomingYModel.addItem( "Auto" ); - for( int i = 0; i < 6; ++i ) + for( int i = 0; i < 7; ++i ) { m_zoomingYModel.addItem( QString::number( 25 << i ) + "%" ); } @@ -377,15 +380,13 @@ AutomationEditor::AutomationEditor() : m_quantizeComboBox = new comboBox( m_toolBar ); m_quantizeComboBox->setFixedSize( 60, 22 ); - // TODO: leak - ComboBoxModel * quantize_model = new ComboBoxModel( /* this */ ); for( int i = 0; i < 7; ++i ) { - quantize_model->addItem( "1/" + QString::number( 1 << i ) ); + m_quantizeModel.addItem( "1/" + QString::number( 1 << i ) ); } - quantize_model->setValue( quantize_model->findText( "1/16" ) ); + m_quantizeModel.setValue( m_quantizeModel.findText( "1/16" ) ); - m_quantizeComboBox->setModel( quantize_model ); + m_quantizeComboBox->setModel( &m_quantizeModel ); tb_layout->addSpacing( 5 ); @@ -456,6 +457,7 @@ AutomationEditor::~AutomationEditor() { m_zoomingXModel.disconnect(); m_zoomingYModel.disconnect(); + m_quantizeModel.disconnect(); m_tensionModel->disconnect(); } @@ -502,6 +504,20 @@ void AutomationEditor::setPauseIcon( bool pause ) } } +// qproperty access methods + +QColor AutomationEditor::gridColor() const +{ return m_gridColor; } +QColor AutomationEditor::graphColor() const +{ return m_graphColor; } +QColor AutomationEditor::vertexColor() const +{ return m_vertexColor; } +void AutomationEditor::setGridColor( const QColor & c ) +{ m_gridColor = c; } +void AutomationEditor::setGraphColor( const QColor & c ) +{ m_graphColor = c; } +void AutomationEditor::setVertexColor( const QColor & c ) +{ m_vertexColor = c; } @@ -1454,34 +1470,34 @@ void AutomationEditor::paintEvent( QPaintEvent * _pe ) // exotic denominators (e.g. 7/11 time), which are allowed ATM. // First quantization grid... for( tick = m_currentPosition - m_currentPosition % quantization(), - x = xCoordOfTick( tick ); - x<=width(); - tick += quantization(), x = xCoordOfTick( tick ) ) - { + x = xCoordOfTick( tick ); + x<=width(); + tick += quantization(), x = xCoordOfTick( tick ) ) + { p.setPen( QColor( 0x2F, 0x2F, 0x2F ) ); p.drawLine( x, grid_bottom, x, x_line_end ); } - // Then beat grid - int ticksPerBeat = DefaultTicksPerTact / + // Then beat grid + int ticksPerBeat = DefaultTicksPerTact / engine::getSong()->getTimeSigModel().getDenominator(); for( tick = m_currentPosition - m_currentPosition % ticksPerBeat, - x = xCoordOfTick( tick ); - x<=width(); - tick += ticksPerBeat, x = xCoordOfTick( tick ) ) - { + x = xCoordOfTick( tick ); + x<=width(); + tick += ticksPerBeat, x = xCoordOfTick( tick ) ) + { p.setPen( QColor( 0x5F, 0x5F, 0x5F ) ); p.drawLine( x, grid_bottom, x, x_line_end ); } // and finally bars for( tick = m_currentPosition - m_currentPosition % MidiTime::ticksPerTact(), - x = xCoordOfTick( tick ); - x<=width(); - tick += MidiTime::ticksPerTact(), x = xCoordOfTick( tick ) ) + x = xCoordOfTick( tick ); + x<=width(); + tick += MidiTime::ticksPerTact(), x = xCoordOfTick( tick ) ) { p.setPen( QColor( 0x7F, 0x7F, 0x7F ) ); p.drawLine( x, grid_bottom, x, x_line_end ); } - + /// \todo move this horizontal line drawing code into the same loop as the value ticks? if( m_y_auto ) { @@ -1743,10 +1759,12 @@ void AutomationEditor::drawLevelTick( QPainter & _p, int _tick, float _level, } _p.fillRect( x, y_start, rect_width, rect_height, current_color ); } + else { printf("not in range\n"); } + } @@ -1798,26 +1816,49 @@ void AutomationEditor::resizeEvent( QResizeEvent * ) void AutomationEditor::wheelEvent( QWheelEvent * _we ) { _we->accept(); - if( _we->modifiers() & Qt::ControlModifier ) + if( _we->modifiers() & Qt::ControlModifier && _we->modifiers() & Qt::ShiftModifier ) { + int y = m_zoomingYModel.value(); if( _we->delta() > 0 ) { - m_ppt = qMin( m_ppt * 2, m_y_delta * - DEFAULT_STEPS_PER_TACT * 8 ); + y++; } - else if( m_ppt >= 72 ) + if( _we->delta() < 0 ) { - m_ppt /= 2; + y--; } - // update combobox with zooming-factor - m_zoomingXComboBox->model()->setValue( - m_zoomingXComboBox->model()->findText( QString::number( - qRound( m_ppt * 100 / - DEFAULT_PPT ) ) +"%" ) ); - // update timeline - m_timeLine->setPixelsPerTact( m_ppt ); + y = qBound( 0, y, m_zoomingYModel.size() - 1 ); + m_zoomingYModel.setValue( y ); + } + else if( _we->modifiers() & Qt::ControlModifier && _we->modifiers() & Qt::AltModifier ) + { + int q = m_quantizeModel.value(); + if( _we->delta() > 0 ) + { + q--; + } + if( _we->delta() < 0 ) + { + q++; + } + q = qBound( 0, q, m_quantizeModel.size() - 1 ); + m_quantizeModel.setValue( q ); update(); } + else if( _we->modifiers() & Qt::ControlModifier ) + { + int x = m_zoomingXModel.value(); + if( _we->delta() > 0 ) + { + x++; + } + if( _we->delta() < 0 ) + { + x--; + } + x = qBound( 0, x, m_zoomingXModel.size() - 1 ); + m_zoomingXModel.setValue( x ); + } else if( _we->modifiers() & Qt::ShiftModifier || _we->orientation() == Qt::Horizontal ) { From 310ac280091b6b330f7579bd81b6624381827536 Mon Sep 17 00:00:00 2001 From: Vesa Date: Sat, 31 May 2014 03:32:55 +0300 Subject: [PATCH 13/61] AutomationEditor: CSS stylability --- data/themes/default/style.css | 5 +++ include/AutomationEditor.h | 4 +++ src/gui/AutomationEditor.cpp | 64 ++++++++++++++++++++++------------- 3 files changed, 50 insertions(+), 23 deletions(-) diff --git a/data/themes/default/style.css b/data/themes/default/style.css index d5c973e87..1794895b6 100644 --- a/data/themes/default/style.css +++ b/data/themes/default/style.css @@ -15,6 +15,11 @@ QMdiArea { AutomationEditor { background-color: rgb(0, 0, 0); + color: #e0e0e0; + qproperty-vertexColor: #ff77af; + qproperty-gridColor: #808080; + qproperty-graphColor: #cfd9ff; + qproperty-scaleColor: rgb( 32, 32, 32 ); } /* text box */ diff --git a/include/AutomationEditor.h b/include/AutomationEditor.h index 2a39be6ff..17d966037 100644 --- a/include/AutomationEditor.h +++ b/include/AutomationEditor.h @@ -53,6 +53,7 @@ class AutomationEditor : public QWidget, public JournallingObject Q_PROPERTY( QColor gridColor READ gridColor WRITE setGridColor ) Q_PROPERTY( QColor graphColor READ graphColor WRITE setGraphColor ) Q_PROPERTY( QColor vertexColor READ vertexColor WRITE setVertexColor ) + Q_PROPERTY( QColor scaleColor READ scaleColor WRITE setScaleColor ) public: void setCurrentPattern( AutomationPattern * _new_pattern ); @@ -82,9 +83,11 @@ public: QColor gridColor() const; QColor graphColor() const; QColor vertexColor() const; + QColor scaleColor() const; void setGridColor( const QColor & c ); void setGraphColor( const QColor & c ); void setVertexColor( const QColor & c ); + void setScaleColor( const QColor & c ); public slots: void update(); @@ -265,6 +268,7 @@ private: QColor m_gridColor; QColor m_graphColor; QColor m_vertexColor; + QColor m_scaleColor; friend class engine; diff --git a/src/gui/AutomationEditor.cpp b/src/gui/AutomationEditor.cpp index ab4c31457..17e8ba6e3 100644 --- a/src/gui/AutomationEditor.cpp +++ b/src/gui/AutomationEditor.cpp @@ -71,8 +71,6 @@ QPixmap * AutomationEditor::s_toolSelect = NULL; QPixmap * AutomationEditor::s_toolMove = NULL; -const QColor DRAGGABLE_PIN_COLOR = QColor( 0xFF, 0x00, 0x00 ); -const QColor DRAGGABLE_PIN_BORDER_COLOR = QColor( 0xFF, 0xFF, 0xFF ); AutomationEditor::AutomationEditor() : @@ -101,7 +99,8 @@ AutomationEditor::AutomationEditor() : m_scrollBack( FALSE ), m_gridColor( 0,0,0 ), m_graphColor( 0,0,0 ), - m_vertexColor( 0,0,0 ) + m_vertexColor( 0,0,0 ), + m_scaleColor( 0,0,0 ) { connect( this, SIGNAL( currentPatternChanged() ), this, SLOT( updateAfterPatternChange() ), @@ -512,12 +511,16 @@ QColor AutomationEditor::graphColor() const { return m_graphColor; } QColor AutomationEditor::vertexColor() const { return m_vertexColor; } +QColor AutomationEditor::scaleColor() const +{ return m_scaleColor; } void AutomationEditor::setGridColor( const QColor & c ) { m_gridColor = c; } void AutomationEditor::setGraphColor( const QColor & c ) { m_graphColor = c; } void AutomationEditor::setVertexColor( const QColor & c ) { m_vertexColor = c; } +void AutomationEditor::setScaleColor( const QColor & c ) +{ m_scaleColor = c; } @@ -1366,13 +1369,12 @@ inline void AutomationEditor::drawAutomationPoint( QPainter & p, timeMap::iterat { int x = xCoordOfTick( it.key() ); int y = yCoordOfLevel( it.value() ); - int outerRadius = qMin( 8, m_ppt/quantization() ); - int innerRadius = qMax( 0, outerRadius-2 ); - p.setBrush( QBrush( DRAGGABLE_PIN_BORDER_COLOR ) ); - p.drawEllipse( x-outerRadius/2, y-outerRadius/2, outerRadius, outerRadius ); - p.setBrush( QBrush( DRAGGABLE_PIN_COLOR ) ); - p.drawEllipse( x-innerRadius/2, y-innerRadius/2, innerRadius, innerRadius ); - p.setBrush( QBrush() ); + const int outerRadius = qBound( 2, ( m_ppt * quantization() ) / 576, 5 ); // man, getting this calculation right took forever + const int innerRadius = outerRadius - 1; + p.setBrush( QBrush( vertexColor().lighter( 200 ) ) ); + p.drawEllipse( x - outerRadius, y - outerRadius, outerRadius * 2, outerRadius * 2 ); + p.setBrush( QBrush( vertexColor() ) ); + p.drawEllipse( x - innerRadius, y - innerRadius, innerRadius * 2, innerRadius * 2 ); } @@ -1387,6 +1389,12 @@ void AutomationEditor::paintEvent( QPaintEvent * _pe ) QPainter p( this ); style()->drawPrimitive( QStyle::PE_Widget, &opt, &p, this ); + // get foregrounf color + QColor fgColor = p.pen().brush().color(); + // get background color and fill background + QColor bgColor = p.background().color(); + p.fillRect( 0, 0, width(), height(), bgColor ); + // set font-size to 8 p.setFont( pointSize<8>( p.font() ) ); @@ -1396,7 +1404,7 @@ void AutomationEditor::paintEvent( QPaintEvent * _pe ) int grid_bottom = height() - SCROLLBAR_SIZE - 1; p.fillRect( 0, TOP_MARGIN, VALUES_WIDTH, height() - TOP_MARGIN, - QColor( 0x33, 0x33, 0x33 ) ); + scaleColor() ); // print value numbers int font_height = p.fontMetrics().height(); @@ -1413,11 +1421,12 @@ void AutomationEditor::paintEvent( QPaintEvent * _pe ) { const QString & label = m_pattern->firstObject() ->displayValue( level[i] ); - p.setPen( QColor( 240, 240, 240 ) ); + p.setPen( QApplication::palette().color( QPalette::Active, + QPalette::Shadow ) ); p.drawText( 1, y[i] - font_height + 1, VALUES_WIDTH - 10, 2 * font_height, text_flags, label ); - p.setPen( QColor( 0, 0, 0 ) ); + p.setPen( fgColor ); p.drawText( 0, y[i] - font_height, VALUES_WIDTH - 10, 2 * font_height, text_flags, label ); @@ -1441,11 +1450,12 @@ void AutomationEditor::paintEvent( QPaintEvent * _pe ) const QString & label = m_pattern->firstObject() ->displayValue( level ); y = yCoordOfLevel( level ); - p.setPen( QColor( 240, 240, 240 ) ); + p.setPen( QApplication::palette().color( QPalette::Active, + QPalette::Shadow ) ); p.drawText( 1, y - font_height + 1, VALUES_WIDTH - 10, 2 * font_height, text_flags, label ); - p.setPen( QColor( 0, 0, 0 ) ); + p.setPen( fgColor ); p.drawText( 0, y - font_height, VALUES_WIDTH - 10, 2 * font_height, text_flags, label ); @@ -1459,6 +1469,7 @@ void AutomationEditor::paintEvent( QPaintEvent * _pe ) grid_height ); // draw vertical raster + QColor lineColor = QColor( gridColor() ); if( m_pattern ) { int tick, x; @@ -1474,7 +1485,8 @@ void AutomationEditor::paintEvent( QPaintEvent * _pe ) x<=width(); tick += quantization(), x = xCoordOfTick( tick ) ) { - p.setPen( QColor( 0x2F, 0x2F, 0x2F ) ); + lineColor.setAlpha( 80 ); + p.setPen( lineColor ); p.drawLine( x, grid_bottom, x, x_line_end ); } // Then beat grid @@ -1485,7 +1497,8 @@ void AutomationEditor::paintEvent( QPaintEvent * _pe ) x<=width(); tick += ticksPerBeat, x = xCoordOfTick( tick ) ) { - p.setPen( QColor( 0x5F, 0x5F, 0x5F ) ); + lineColor.setAlpha( 160 ); + p.setPen( lineColor ); p.drawLine( x, grid_bottom, x, x_line_end ); } // and finally bars @@ -1494,14 +1507,16 @@ void AutomationEditor::paintEvent( QPaintEvent * _pe ) x<=width(); tick += MidiTime::ticksPerTact(), x = xCoordOfTick( tick ) ) { - p.setPen( QColor( 0x7F, 0x7F, 0x7F ) ); + lineColor.setAlpha( 255 ); + p.setPen( lineColor ); p.drawLine( x, grid_bottom, x, x_line_end ); } /// \todo move this horizontal line drawing code into the same loop as the value ticks? if( m_y_auto ) { - QPen pen( QColor( 0x4F, 0x4F, 0x4F ) ); + lineColor.setAlpha( 160 ); + QPen pen( lineColor ); p.setPen( pen ); p.drawLine( VALUES_WIDTH, grid_bottom, width(), grid_bottom ); @@ -1522,11 +1537,13 @@ void AutomationEditor::paintEvent( QPaintEvent * _pe ) y = yCoordOfLevel( (float)level ); if( level % 5 == 0 ) { - p.setPen( QColor( 0x4F, 0x4F, 0x4F ) ); + lineColor.setAlpha( 160 ); + p.setPen( lineColor ); } else { - p.setPen( QColor( 0x3F, 0x3F, 0x3F ) ); + lineColor.setAlpha( 80 ); + p.setPen( lineColor ); } // draw level line @@ -1564,7 +1581,7 @@ void AutomationEditor::paintEvent( QPaintEvent * _pe ) if( time_map.size() > 0 ) { timeMap::iterator it = time_map.begin(); - p.setPen( QColor( 0xCF, 0xD9, 0xFF ) ); + p.setPen( graphColor() ); while( it+1 != time_map.end() ) { // skip this section if it occurs completely before the @@ -1633,7 +1650,8 @@ void AutomationEditor::paintEvent( QPaintEvent * _pe ) QFont f = p.font(); f.setBold( TRUE ); p.setFont( pointSize<14>( f ) ); - p.setPen( QColor( 74, 253, 133 ) ); + p.setPen( QApplication::palette().color( QPalette::Active, + QPalette::BrightText ) ); p.drawText( VALUES_WIDTH + 20, TOP_MARGIN + 40, width() - VALUES_WIDTH - 20 - SCROLLBAR_SIZE, grid_height - 40, Qt::TextWordWrap, From 7a19654ab9bb3cf962a86cf0218dfdb2ed07a948 Mon Sep 17 00:00:00 2001 From: Vesa Date: Sat, 31 May 2014 04:05:58 +0300 Subject: [PATCH 14/61] AutomationEditor - fix previous --- data/themes/default/style.css | 2 +- src/gui/AutomationEditor.cpp | 14 ++++++-------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/data/themes/default/style.css b/data/themes/default/style.css index 1794895b6..239f08f97 100644 --- a/data/themes/default/style.css +++ b/data/themes/default/style.css @@ -18,7 +18,7 @@ AutomationEditor { color: #e0e0e0; qproperty-vertexColor: #ff77af; qproperty-gridColor: #808080; - qproperty-graphColor: #cfd9ff; + qproperty-graphColor: #99afff; qproperty-scaleColor: rgb( 32, 32, 32 ); } diff --git a/src/gui/AutomationEditor.cpp b/src/gui/AutomationEditor.cpp index 17e8ba6e3..2f1577793 100644 --- a/src/gui/AutomationEditor.cpp +++ b/src/gui/AutomationEditor.cpp @@ -1370,11 +1370,9 @@ inline void AutomationEditor::drawAutomationPoint( QPainter & p, timeMap::iterat int x = xCoordOfTick( it.key() ); int y = yCoordOfLevel( it.value() ); const int outerRadius = qBound( 2, ( m_ppt * quantization() ) / 576, 5 ); // man, getting this calculation right took forever - const int innerRadius = outerRadius - 1; - p.setBrush( QBrush( vertexColor().lighter( 200 ) ) ); - p.drawEllipse( x - outerRadius, y - outerRadius, outerRadius * 2, outerRadius * 2 ); + p.setPen( QPen( vertexColor().lighter( 200 ) ) ); p.setBrush( QBrush( vertexColor() ) ); - p.drawEllipse( x - innerRadius, y - innerRadius, innerRadius * 2, innerRadius * 2 ); + p.drawEllipse( x - outerRadius, y - outerRadius, outerRadius * 2, outerRadius * 2 ); } @@ -1580,8 +1578,7 @@ void AutomationEditor::paintEvent( QPaintEvent * _pe ) //Don't bother doing/rendering anything if there is no automation points if( time_map.size() > 0 ) { - timeMap::iterator it = time_map.begin(); - p.setPen( graphColor() ); + timeMap::iterator it = time_map.begin(); while( it+1 != time_map.end() ) { // skip this section if it occurs completely before the @@ -1618,10 +1615,11 @@ void AutomationEditor::paintEvent( QPaintEvent * _pe ) { is_selected = TRUE; } - + float *values = m_pattern->valuesAfter( it.key() ); for( int i = 0; i < (it+1).key() - it.key(); i++ ) { + drawLevelTick( p, it.key() + i, values[i], is_selected ); } @@ -1770,7 +1768,7 @@ void AutomationEditor::drawLevelTick( QPainter & _p, int _tick, float _level, rect_height = (int)( _level * m_y_delta ); } - QColor current_color( 0x9F, 0xAF, 0xFF ); + QColor current_color( graphColor() ); if( _is_selected == TRUE ) { current_color.setRgb( 0x00, 0x40, 0xC0 ); From 3a1e447d7b9fdae8637ca3d17f83edbc151fcd4b Mon Sep 17 00:00:00 2001 From: Vesa Date: Sat, 31 May 2014 07:06:58 +0300 Subject: [PATCH 15/61] PianoRoll: wheelevent improvements, similar to AutomationEditor - ctrl+alt+wheel changes q (as in auto) - ctrl+shift+wheel changes note length - changed note lock functionality slightly, it no longer changes itself to 1/16 because this would cause annoying infinite scrolling with the wheel, instead it just acts like 1/16 when notelength is last note --- src/gui/PianoRoll.cpp | 65 +++++++++++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 21 deletions(-) diff --git a/src/gui/PianoRoll.cpp b/src/gui/PianoRoll.cpp index f807beeb6..dd9178ed1 100644 --- a/src/gui/PianoRoll.cpp +++ b/src/gui/PianoRoll.cpp @@ -3494,27 +3494,50 @@ void PianoRoll::wheelEvent( QWheelEvent * _we ) } } - // not in note edit area, so handle scrolling/zooming + // not in note edit area, so handle scrolling/zooming and quantization change else - if( _we->modifiers() & Qt::ControlModifier ) + if( _we->modifiers() & Qt::ControlModifier && _we->modifiers() & Qt::AltModifier ) { + int q = m_quantizeModel.value(); if( _we->delta() > 0 ) { - m_ppt = qMin( m_ppt * 2, KEY_LINE_HEIGHT * - DefaultStepsPerTact * 8 ); + q--; } - else if( m_ppt >= 72 ) + if( _we->delta() < 0 ) { - m_ppt /= 2; + q++; } + q = qBound( 0, q, m_quantizeModel.size() - 1 ); + m_quantizeModel.setValue( q ); + } + else if( _we->modifiers() & Qt::ControlModifier && _we->modifiers() & Qt::ShiftModifier ) + { + int l = m_noteLenModel.value(); + if( _we->delta() > 0 ) + { + l--; + } + if( _we->delta() < 0 ) + { + l++; + } + l = qBound( 0, l, m_noteLenModel.size() - 1 ); + m_noteLenModel.setValue( l ); + } + else if( _we->modifiers() & Qt::ControlModifier ) + { + int z = m_zoomingModel.value(); + if( _we->delta() > 0 ) + { + z++; + } + if( _we->delta() < 0 ) + { + z--; + } + z = qBound( 0, z, m_zoomingModel.size() - 1 ); // update combobox with zooming-factor - m_zoomingModel.setValue( - m_zoomingModel.findText( QString::number( - static_cast( m_ppt * 100 / - DEFAULT_PR_PPT ) ) +"%" ) ); - // update timeline - m_timeLine->setPixelsPerTact( m_ppt ); - update(); + m_zoomingModel.setValue( z ); } else if( _we->modifiers() & Qt::ShiftModifier || _we->orientation() == Qt::Horizontal ) @@ -4123,13 +4146,6 @@ void PianoRoll::zoomingChanged() void PianoRoll::quantizeChanged() { - if( m_quantizeModel.value() == 0 && - m_noteLenModel.value() == 0 ) - { - m_quantizeModel.setValue( m_quantizeModel.findText( "1/16" ) ); - return; - } - // Could be smarter update(); } @@ -4138,7 +4154,14 @@ int PianoRoll::quantization() const { if( m_quantizeModel.value() == 0 ) { - return newNoteLen(); + if( m_noteLenModel.value() > 0 ) + { + return newNoteLen(); + } + else + { + return DefaultTicksPerTact / 16; + } } return DefaultTicksPerTact / m_quantizeModel.currentText().right( m_quantizeModel.currentText().length() - From f0556cbc3b13cbe753dfb0804ade4e387ea6ce75 Mon Sep 17 00:00:00 2001 From: "Raine M. Ekman" Date: Sat, 31 May 2014 20:41:50 +0300 Subject: [PATCH 16/61] InstrumentTrack: Fix issue #780 by showing the m_pitchRangeSpinBox too, in case it's been hidden. --- src/tracks/InstrumentTrack.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 1b30c56c6..d14728e05 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -1323,6 +1323,7 @@ void InstrumentTrackWindow::modelChanged() m_pitchKnob->setModel( &m_track->m_pitchModel ); m_pitchRangeSpinBox->setModel( &m_track->m_pitchRangeModel ); m_pitchKnob->show(); + m_pitchRangeSpinBox->show(); } else { From a61d0284f2c41d5081b05c565fa9ef22c2a0b6e3 Mon Sep 17 00:00:00 2001 From: Oskar Wallgren Date: Mon, 2 Jun 2014 03:51:28 +0200 Subject: [PATCH 17/61] Fix Instrument LFO, random wave icon --- data/themes/default/random_wave_active.png | Bin 533 -> 587 bytes data/themes/default/random_wave_inactive.png | Bin 461 -> 370 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/data/themes/default/random_wave_active.png b/data/themes/default/random_wave_active.png index 38b089c63d7ff48ee786656a620cae7281a88d3d..b65a9a0c3aa5e53123dc736f6a3e8dc23ea293f0 100644 GIT binary patch delta 573 zcmV-D0>b^31j_`F8Gi-<0019IEztk~00DDSM?wIu&K&6g000JJOGiWi{{a60|De66 zlK=n!32;bRa{vGf6951U69E94oEQKA00(qQO+^RZ1_A*c06z!p{{R309dt!lbVF}# zZDnqB07G(RVRU6=Aa`kWXdqN*WgtgMO;GP-C2jx!0isDnL4Q;z&z+L7ZWBQehQHa{ z*pBa<05&*^Tv(A1$_rR-XpwjWNjNQl+kE}bB-VgHo9n+qaQwc z8UCaQL5yG%Pj}`?V!^Lk$cG#;;O<)%S;>Ii8k|QNr!NC+r?m-x^x}dlF{t+WlOzCm zxy3SD0=pQ1q9>rxe>0>1b`C%hf~o^*bzZTZ7OO)G(0_o3I{>u4M=lHOWkG8%fTQL{dy-Ewl delta 491 zcmVDfMF&=%a`Cox`cYNXsep5f0F1}uG)=YEQc5BMKt#;U z%pnBlTu~I(S_!~=Z>3*<_QFx2^NXSVN9ii5G_O0Zb($aq?>ztkpmp!s_SnC_pIcvk zx^0^CTKsT}%jV64v*x#2EJ|yw5F!Ea@d+<_d6D{+D9n+cbvJYWd)Cd&1%Ha|*Y09b$+ zOrU^Ak9D#O{_6!sIa!G;9KOxTMPWkgg%KtmzC7!ktoMG+`|81m zT>YvWQzuMpKVPP=G71dKYU+}b8&fB;06+pzll=Ip4_zg1rHx4eK&(9S3V_)7#^=2E zE(2~5fWcq@;@A{MRbT6Q4WPQJ^t@({zTZ@{GO=+u97+Ho1OPBmO=<=Js7bX0`Nc30 hb_`%N8lC4Z{{YuJ=_nVDUkm^M002ovPDHLkV1m60-IxFX diff --git a/data/themes/default/random_wave_inactive.png b/data/themes/default/random_wave_inactive.png index 9a35c9d1667eaa5ef6db365314bae1ca263700ea..47184549a45cf537324ec42d3a58bcbfc0fd68af 100644 GIT binary patch delta 354 zcmX@h{E2CTWIYQ51H)Fwr%^zPu{g-xiDBJ2nU_EgQ z0^-XbJ$du&X~}o3IjpYXj;ze8s;?A0_gS!5-z>K+cwpOk?G$UD@0F&g3)@v+{0{SA zEqkM%_$*|#=-n!jh!fKb6n0%MRw=us-y7op^6-KF>Q3fV_UkcT2e-y3v(JCAQE}Ex zMNz?M*Oi6r$16VdxV3sUZuYBgZsl34(RD9Yl9TCq+r2f(;oTW|c~1f!IJPl~F9`Tt yzVzaQqgT|t)=PzWY^iShUvk$>&>~XupZI})EXlZF`X=-Y0Y;13DZ*+Bac6N4pdV76+ zeSv|2f`WpEhK7!gj*pLzk&uy-larK{l$Ms2mzS5BnVFoNoPVC4o}{FtrlqB+si~@} zs;#Z9uCA`Iu&}bSva_?Zw6wLfwY0Xjwzs#pxw*Nzy1Kl*yuH4?zP`P_zP`Y~z{0}A z)6>(`)YRbM;O6G$=jZ3>=;-U~>+J08?(XjI@9*&N@bU5S@$&NW^78rl`TP6({QUg= z{r&#_{{R2~rhkr4i2wiqn@L1LR0tha!7)z5KoCIDKeMxmy~s2)L2hZd|2^pFXb@E} z$cYfxCObQnz_$4xBk3T+t5PKtkK;wcNVKbY??-!@uTR~xGB<5+>*I^pk2) From 06be5bba82d8f9103e151d4fecab865ac1eb3b0f Mon Sep 17 00:00:00 2001 From: Vesa Date: Wed, 4 Jun 2014 04:23:16 +0300 Subject: [PATCH 18/61] Make MIDI timing sample-accurate - currently only affects Vestige - no idea whether this can also be used for Zyn and OpulenZ, I'm not sure if Zyn has any kind of mechanism for communicating frame offset to the synth, as for OpulenZ, @softrabbit would know the answer better - basically, I made it happen by simply adding an extra parameter in the processMidi{In|Out} functions, which is 0 by default, and made the necessary changes in instrumentTrack and nph to utilize it - I based this against 1.1 because I didn't think it's a very big change, and I don't see much possibility for things going wrong here, since we're basically just using the existing functionality in Vestige (there already was a frame offset being communicated to the remote plugin, just that it was always set to 0). However, if @tobydox thinks this is better to bump up to 1.2, I can rebase it for master... --- include/Instrument.h | 6 +++--- include/InstrumentTrack.h | 8 ++++---- include/MidiController.h | 8 ++++---- include/MidiEventProcessor.h | 8 ++++---- plugins/opl2/opl2instrument.cpp | 2 +- plugins/opl2/opl2instrument.h | 2 +- plugins/vestige/vestige.cpp | 4 ++-- plugins/vestige/vestige.h | 2 +- plugins/zynaddsubfx/ZynAddSubFx.cpp | 2 +- plugins/zynaddsubfx/ZynAddSubFx.h | 2 +- src/core/NotePlayHandle.cpp | 6 ++++-- src/core/midi/MidiController.cpp | 2 +- src/tracks/InstrumentTrack.cpp | 14 +++++++------- 13 files changed, 34 insertions(+), 32 deletions(-) diff --git a/include/Instrument.h b/include/Instrument.h index 987d1429f..3db88b980 100644 --- a/include/Instrument.h +++ b/include/Instrument.h @@ -23,8 +23,8 @@ * */ -#ifndef _INSTRUMENT_H -#define _INSTRUMENT_H +#ifndef INSTRUMENT_H +#define INSTRUMENT_H #include @@ -101,7 +101,7 @@ public: // sub-classes can re-implement this for receiving all incoming // MIDI-events - inline virtual bool handleMidiEvent( const MidiEvent&, const MidiTime& = MidiTime() ) + inline virtual bool handleMidiEvent( const MidiEvent&, const MidiTime& = MidiTime(), f_cnt_t offset = 0 ) { return true; } diff --git a/include/InstrumentTrack.h b/include/InstrumentTrack.h index 6f9a0c6cf..b09ecaa6f 100644 --- a/include/InstrumentTrack.h +++ b/include/InstrumentTrack.h @@ -23,8 +23,8 @@ * */ -#ifndef _INSTRUMENT_TRACK_H -#define _INSTRUMENT_TRACK_H +#ifndef INSTRUMENT_TRACK_H +#define INSTRUMENT_TRACK_H #include "AudioPort.h" #include "InstrumentFunctions.h" @@ -71,8 +71,8 @@ public: MidiEvent applyMasterKey( const MidiEvent& event ); - virtual void processInEvent( const MidiEvent& event, const MidiTime& time = MidiTime() ); - virtual void processOutEvent( const MidiEvent& event, const MidiTime& time = MidiTime() ); + virtual void processInEvent( const MidiEvent& event, const MidiTime& time = MidiTime(), f_cnt_t offset = 0 ); + virtual void processOutEvent( const MidiEvent& event, const MidiTime& time = MidiTime(), f_cnt_t offset = 0 ); // silence all running notes played by this track void silenceAllNotes(); diff --git a/include/MidiController.h b/include/MidiController.h index 2271e8659..4ffb460ce 100644 --- a/include/MidiController.h +++ b/include/MidiController.h @@ -22,8 +22,8 @@ * */ -#ifndef _MIDI_CONTROLLER_H -#define _MIDI_CONTROLLER_H +#ifndef MIDI_CONTROLLER_H +#define MIDI_CONTROLLER_H #include @@ -44,10 +44,10 @@ public: virtual ~MidiController(); virtual void processInEvent( const MidiEvent & _me, - const MidiTime & _time ); + const MidiTime & _time, f_cnt_t offset = 0 ); virtual void processOutEvent( const MidiEvent& _me, - const MidiTime & _time) + const MidiTime & _time, f_cnt_t offset = 0 ) { // No output yet } diff --git a/include/MidiEventProcessor.h b/include/MidiEventProcessor.h index dafcfb6cd..0ca6ce59e 100644 --- a/include/MidiEventProcessor.h +++ b/include/MidiEventProcessor.h @@ -22,8 +22,8 @@ * */ -#ifndef _MIDI_EVENT_PROCESSOR_H -#define _MIDI_EVENT_PROCESSOR_H +#ifndef MIDI_EVENT_PROCESSOR_H +#define MIDI_EVENT_PROCESSOR_H #include "MidiEvent.h" #include "MidiTime.h" @@ -42,8 +42,8 @@ public: } // to be implemented by inheriting classes - virtual void processInEvent( const MidiEvent& event, const MidiTime& time = MidiTime() ) = 0; - virtual void processOutEvent( const MidiEvent& event, const MidiTime& time = MidiTime() ) = 0; + virtual void processInEvent( const MidiEvent& event, const MidiTime& time = MidiTime(), f_cnt_t offset = 0 ) = 0; + virtual void processOutEvent( const MidiEvent& event, const MidiTime& time = MidiTime(), f_cnt_t offset = 0 ) = 0; } ; diff --git a/plugins/opl2/opl2instrument.cpp b/plugins/opl2/opl2instrument.cpp index 4704f0147..6a169c964 100644 --- a/plugins/opl2/opl2instrument.cpp +++ b/plugins/opl2/opl2instrument.cpp @@ -283,7 +283,7 @@ int opl2instrument::pushVoice(int v) { return i; } -bool opl2instrument::handleMidiEvent( const MidiEvent& event, const MidiTime& time ) +bool opl2instrument::handleMidiEvent( const MidiEvent& event, const MidiTime& time, f_cnt_t offset ) { emulatorMutex.lock(); int key, vel, voice, tmp_pb; diff --git a/plugins/opl2/opl2instrument.h b/plugins/opl2/opl2instrument.h index e95357807..e388b0672 100644 --- a/plugins/opl2/opl2instrument.h +++ b/plugins/opl2/opl2instrument.h @@ -53,7 +53,7 @@ public: return IsSingleStreamed | IsMidiBased; } - virtual bool handleMidiEvent( const MidiEvent& event, const MidiTime& time ); + virtual bool handleMidiEvent( const MidiEvent& event, const MidiTime& time, f_cnt_t offset = 0 ); virtual void play( sampleFrame * _working_buffer ); void saveSettings( QDomDocument & _doc, QDomElement & _this ); diff --git a/plugins/vestige/vestige.cpp b/plugins/vestige/vestige.cpp index 31a262771..4c907c9a2 100644 --- a/plugins/vestige/vestige.cpp +++ b/plugins/vestige/vestige.cpp @@ -310,12 +310,12 @@ void vestigeInstrument::play( sampleFrame * _buf ) -bool vestigeInstrument::handleMidiEvent( const MidiEvent& event, const MidiTime& time ) +bool vestigeInstrument::handleMidiEvent( const MidiEvent& event, const MidiTime& time, f_cnt_t offset ) { m_pluginMutex.lock(); if( m_plugin != NULL ) { - m_plugin->processMidiEvent( event, time ); + m_plugin->processMidiEvent( event, offset ); } m_pluginMutex.unlock(); diff --git a/plugins/vestige/vestige.h b/plugins/vestige/vestige.h index 8a5ce639e..8854e4369 100644 --- a/plugins/vestige/vestige.h +++ b/plugins/vestige/vestige.h @@ -68,7 +68,7 @@ public: return IsSingleStreamed | IsMidiBased; } - virtual bool handleMidiEvent( const MidiEvent& event, const MidiTime& time ); + virtual bool handleMidiEvent( const MidiEvent& event, const MidiTime& time, f_cnt_t offset = 0 ); virtual PluginView * instantiateView( QWidget * _parent ); diff --git a/plugins/zynaddsubfx/ZynAddSubFx.cpp b/plugins/zynaddsubfx/ZynAddSubFx.cpp index 8eca9fdae..40c2737c7 100644 --- a/plugins/zynaddsubfx/ZynAddSubFx.cpp +++ b/plugins/zynaddsubfx/ZynAddSubFx.cpp @@ -343,7 +343,7 @@ void ZynAddSubFxInstrument::play( sampleFrame * _buf ) -bool ZynAddSubFxInstrument::handleMidiEvent( const MidiEvent& event, const MidiTime& time ) +bool ZynAddSubFxInstrument::handleMidiEvent( const MidiEvent& event, const MidiTime& time, f_cnt_t offset ) { // do not forward external MIDI Control Change events if the according // LED is not checked diff --git a/plugins/zynaddsubfx/ZynAddSubFx.h b/plugins/zynaddsubfx/ZynAddSubFx.h index ad78b95b4..ac9cdf3cc 100644 --- a/plugins/zynaddsubfx/ZynAddSubFx.h +++ b/plugins/zynaddsubfx/ZynAddSubFx.h @@ -70,7 +70,7 @@ public: virtual void play( sampleFrame * _working_buffer ); - virtual bool handleMidiEvent( const MidiEvent& event, const MidiTime& time = MidiTime() ); + virtual bool handleMidiEvent( const MidiEvent& event, const MidiTime& time = MidiTime(), f_cnt_t offset = 0 ); virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent ); virtual void loadSettings( const QDomElement & _this ); diff --git a/src/core/NotePlayHandle.cpp b/src/core/NotePlayHandle.cpp index 9ad49de41..db535474a 100644 --- a/src/core/NotePlayHandle.cpp +++ b/src/core/NotePlayHandle.cpp @@ -107,7 +107,8 @@ NotePlayHandle::NotePlayHandle( InstrumentTrack* instrumentTrack, // send MidiNoteOn event m_instrumentTrack->processOutEvent( MidiEvent( MidiNoteOn, midiChannel(), midiKey(), midiVelocity( baseVelocity ) ), - MidiTime::fromFrames( offset(), engine::framesPerTick() ) ); + MidiTime::fromFrames( offset(), engine::framesPerTick() ), + offset() ); } } @@ -336,7 +337,8 @@ void NotePlayHandle::noteOff( const f_cnt_t _s ) // send MidiNoteOff event m_instrumentTrack->processOutEvent( MidiEvent( MidiNoteOff, midiChannel(), midiKey(), 0 ), - MidiTime::fromFrames( m_framesBeforeRelease, engine::framesPerTick() ) ); + MidiTime::fromFrames( m_framesBeforeRelease, engine::framesPerTick() ), + _s ); } // inform attached components about MIDI finished (used for recording in Piano Roll) diff --git a/src/core/midi/MidiController.cpp b/src/core/midi/MidiController.cpp index 5e65b5cd0..b7e78f10e 100644 --- a/src/core/midi/MidiController.cpp +++ b/src/core/midi/MidiController.cpp @@ -73,7 +73,7 @@ void MidiController::updateName() -void MidiController::processInEvent( const MidiEvent& event, const MidiTime& time ) +void MidiController::processInEvent( const MidiEvent& event, const MidiTime& time, f_cnt_t offset ) { unsigned char controllerNum; switch( event.type() ) diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index d14728e05..532431e6c 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -232,7 +232,7 @@ MidiEvent InstrumentTrack::applyMasterKey( const MidiEvent& event ) -void InstrumentTrack::processInEvent( const MidiEvent& event, const MidiTime& time ) +void InstrumentTrack::processInEvent( const MidiEvent& event, const MidiTime& time, f_cnt_t offset ) { engine::mixer()->lock(); @@ -335,7 +335,7 @@ void InstrumentTrack::processInEvent( const MidiEvent& event, const MidiTime& ti break; } - if( eventHandled == false && instrument()->handleMidiEvent( event, time ) == false ) + if( eventHandled == false && instrument()->handleMidiEvent( event, time, offset ) == false ) { qWarning( "InstrumentTrack: unhandled MIDI event %d", event.type() ); } @@ -346,7 +346,7 @@ void InstrumentTrack::processInEvent( const MidiEvent& event, const MidiTime& ti -void InstrumentTrack::processOutEvent( const MidiEvent& event, const MidiTime& time ) +void InstrumentTrack::processOutEvent( const MidiEvent& event, const MidiTime& time, f_cnt_t offset ) { // do nothing if we do not have an instrument instance (e.g. when loading settings) if( m_instrument == NULL ) @@ -366,10 +366,10 @@ void InstrumentTrack::processOutEvent( const MidiEvent& event, const MidiTime& t { if( m_runningMidiNotes[key] > 0 ) { - m_instrument->handleMidiEvent( MidiEvent( MidiNoteOff, midiPort()->realOutputChannel(), key, 0 ), time ); + m_instrument->handleMidiEvent( MidiEvent( MidiNoteOff, midiPort()->realOutputChannel(), key, 0 ), time, offset ); } ++m_runningMidiNotes[key]; - m_instrument->handleMidiEvent( MidiEvent( MidiNoteOn, midiPort()->realOutputChannel(), key, event.velocity() ), time ); + m_instrument->handleMidiEvent( MidiEvent( MidiNoteOn, midiPort()->realOutputChannel(), key, event.velocity() ), time, offset ); emit newNote(); } @@ -381,12 +381,12 @@ void InstrumentTrack::processOutEvent( const MidiEvent& event, const MidiTime& t if( key >= 0 && key < NumKeys && --m_runningMidiNotes[key] <= 0 ) { m_runningMidiNotes[key] = qMax( 0, m_runningMidiNotes[key] ); - m_instrument->handleMidiEvent( MidiEvent( MidiNoteOff, midiPort()->realOutputChannel(), key, 0 ), time ); + m_instrument->handleMidiEvent( MidiEvent( MidiNoteOff, midiPort()->realOutputChannel(), key, 0 ), time, offset ); } break; default: - m_instrument->handleMidiEvent( transposedEvent, time ); + m_instrument->handleMidiEvent( transposedEvent, time, offset ); break; } From f42196315c8c65148e8c65f435b885433fb36021 Mon Sep 17 00:00:00 2001 From: tresf Date: Wed, 4 Jun 2014 08:52:12 -0400 Subject: [PATCH 19/61] SF2/VST title rename #462 w/ #774 recommendations --- plugins/sf2_player/sf2_player.cpp | 4 ++-- plugins/vestige/vestige.cpp | 11 ++++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/plugins/sf2_player/sf2_player.cpp b/plugins/sf2_player/sf2_player.cpp index 4fba5c648..2647ca1f3 100644 --- a/plugins/sf2_player/sf2_player.cpp +++ b/plugins/sf2_player/sf2_player.cpp @@ -352,9 +352,9 @@ void sf2Instrument::openFile( const QString & _sf2File, bool updateTrackName ) delete[] sf2Ascii; - if( updateTrackName ) + if( updateTrackName || instrumentTrack()->displayName() == displayName()) { - instrumentTrack()->setName( QFileInfo( _sf2File ).baseName() ); + instrumentTrack()->setName( QFileInfo( _sf2File ).baseName() ); } } diff --git a/plugins/vestige/vestige.cpp b/plugins/vestige/vestige.cpp index 4c907c9a2..8413f3ebd 100644 --- a/plugins/vestige/vestige.cpp +++ b/plugins/vestige/vestige.cpp @@ -237,9 +237,10 @@ void vestigeInstrument::loadFile( const QString & _file ) { m_pluginMutex.lock(); const bool set_ch_name = ( m_plugin != NULL && - instrumentTrack()->name() == m_plugin->name() ) || - instrumentTrack()->name() == - InstrumentTrack::tr( "Default preset" ); + instrumentTrack()->name() == m_plugin->name() ) || + instrumentTrack()->name() == InstrumentTrack::tr( "Default preset" ) || + instrumentTrack()->name() == displayName(); + m_pluginMutex.unlock(); if ( m_plugin != NULL ) @@ -310,12 +311,12 @@ void vestigeInstrument::play( sampleFrame * _buf ) -bool vestigeInstrument::handleMidiEvent( const MidiEvent& event, const MidiTime& time, f_cnt_t offset ) +bool vestigeInstrument::handleMidiEvent( const MidiEvent& event, const MidiTime& time ) { m_pluginMutex.lock(); if( m_plugin != NULL ) { - m_plugin->processMidiEvent( event, offset ); + m_plugin->processMidiEvent( event, time ); } m_pluginMutex.unlock(); From 7a03353fb6b6d3f9091ae32d3b9e1d90f093271e Mon Sep 17 00:00:00 2001 From: tresf Date: Wed, 4 Jun 2014 08:55:30 -0400 Subject: [PATCH 20/61] Export dialog append wav/ogg #764 w/ #779 recommendations --- src/core/song.cpp | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/core/song.cpp b/src/core/song.cpp index 5f3719a8a..0d8eaac44 100644 --- a/src/core/song.cpp +++ b/src/core/song.cpp @@ -1195,12 +1195,28 @@ void song::exportProject(bool multiExport) efd.setAcceptMode( FileDialog::AcceptSave ); - if( efd.exec() == QDialog::Accepted && - !efd.selectedFiles().isEmpty() && !efd.selectedFiles()[0].isEmpty() ) + if( efd.exec() == QDialog::Accepted && !efd.selectedFiles().isEmpty() && !efd.selectedFiles()[0].isEmpty() ) { - const QString export_file_name = efd.selectedFiles()[0]; - exportProjectDialog epd( export_file_name, - engine::mainWindow(), multiExport ); + QString suffix = ""; + if ( !multiExport ) + { + int stx = efd.selectedNameFilter().indexOf( "(*." ); + int etx = efd.selectedNameFilter().indexOf( ")" ); + + if ( stx > 0 && etx > stx ) + { + // Get first extension from selected dropdown. + // i.e. ".wav" from "WAV-File (*.wav), Dummy-File (*.dum)" + suffix = efd.selectedNameFilter().mid( stx + 2, etx - stx - 2 ).split( " " )[0].trimmed(); + if ( efd.selectedFiles()[0].endsWith( suffix ) ) + { + suffix = ""; + } + } + } + + const QString export_file_name = efd.selectedFiles()[0] + suffix; + exportProjectDialog epd( export_file_name, engine::mainWindow(), multiExport ); epd.exec(); } } From e06759d0d8084f5527104d75adb76b8cd0722cb3 Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Wed, 4 Jun 2014 08:58:06 -0400 Subject: [PATCH 21/61] Formatting fixes --- plugins/sf2_player/sf2_player.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/sf2_player/sf2_player.cpp b/plugins/sf2_player/sf2_player.cpp index 2647ca1f3..55c199ca0 100644 --- a/plugins/sf2_player/sf2_player.cpp +++ b/plugins/sf2_player/sf2_player.cpp @@ -352,7 +352,7 @@ void sf2Instrument::openFile( const QString & _sf2File, bool updateTrackName ) delete[] sf2Ascii; - if( updateTrackName || instrumentTrack()->displayName() == displayName()) + if( updateTrackName || instrumentTrack()->displayName() == displayName() ) { instrumentTrack()->setName( QFileInfo( _sf2File ).baseName() ); } From 922ab25217fc93aa57a3e6b0d48ac46a3fb11419 Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Wed, 4 Jun 2014 09:03:19 -0400 Subject: [PATCH 22/61] Fast forward vesa's sample-accurate changes --- plugins/vestige/vestige.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/vestige/vestige.cpp b/plugins/vestige/vestige.cpp index 8413f3ebd..7ae8dbcdd 100644 --- a/plugins/vestige/vestige.cpp +++ b/plugins/vestige/vestige.cpp @@ -311,12 +311,12 @@ void vestigeInstrument::play( sampleFrame * _buf ) -bool vestigeInstrument::handleMidiEvent( const MidiEvent& event, const MidiTime& time ) +bool vestigeInstrument::handleMidiEvent( const MidiEvent& event, const MidiTime& time, f_cnt_t offset ) { m_pluginMutex.lock(); if( m_plugin != NULL ) { - m_plugin->processMidiEvent( event, time ); + m_plugin->processMidiEvent( event, offset ); } m_pluginMutex.unlock(); From 910f89a5d33a6a7d65c9b2bc5e04a8741a76628c Mon Sep 17 00:00:00 2001 From: Vesa Date: Fri, 6 Jun 2014 11:06:12 +0300 Subject: [PATCH 23/61] Make BB-tracks themeable - This allows defining a default colour for BB-track patterns in the CSS - The default colour is used for all bb-patterns which don't have a custom colour set by the user: in other words, the colour of a pattern can be any rgb-value OR "style colour" - By default, all created bb-patterns use the style colour - You can also reset colourized patterns to use style colour again - Backwards compatibility: old projects will be loaded so that any pattern using either of the old default colours will be converted to use style colour TODO: add a settings option that can disable custom colours (ie. always use style colour), and/or an option to reset all patterns in a project to style colour. This is needed, since themes can now change the song editor background, which can lead to unfortunate colour combinations with custom colours... --- data/themes/default/style.css | 1 + include/bb_track.h | 46 ++++++++++-- src/core/DataFile.cpp | 12 ---- src/tracks/bb_track.cpp | 129 +++++++++++++++++++++++----------- 4 files changed, 129 insertions(+), 59 deletions(-) diff --git a/data/themes/default/style.css b/data/themes/default/style.css index 24b2f25b2..74f8641c8 100644 --- a/data/themes/default/style.css +++ b/data/themes/default/style.css @@ -516,6 +516,7 @@ AutomationPatternView { /* bb-pattern */ bbTCOView { + color: rgb( 128, 182, 175 ); /* default colour for bb-tracks, used when the colour hasn't been defined by the user */ qproperty-textColor: rgb( 255, 255, 255 ); } diff --git a/include/bb_track.h b/include/bb_track.h index f9001f61e..dac1cd5f5 100644 --- a/include/bb_track.h +++ b/include/bb_track.h @@ -39,7 +39,7 @@ class TrackContainer; class bbTCO : public trackContentObject { public: - bbTCO( track * _track, unsigned int _color = 0 ); + bbTCO( track * _track ); virtual ~bbTCO(); virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent ); @@ -49,13 +49,24 @@ public: return( "bbtco" ); } - inline unsigned int color() const + unsigned int color() const { - return( m_color ); + return( m_color.rgb() ); } - inline static unsigned int defaultColor() + + QColor colorObj() const { - return qRgb( 128, 182, 175 ); + return m_color; + } + + void setColor( const QColor & c ) + { + m_color = QColor( c ); + } + + void setUseStyleColor( bool b ) + { + m_useStyleColor = b; } int bbTrackIndex(); @@ -63,7 +74,8 @@ public: virtual trackContentObjectView * createView( trackView * _tv ); private: - unsigned int m_color; + QColor m_color; + bool m_useStyleColor; friend class bbTCOView; @@ -91,6 +103,7 @@ protected slots: void resetName(); void changeName(); void changeColor(); + void resetColor(); protected: @@ -144,6 +157,26 @@ public: m_disabledTracks.removeAll( _track ); } + static void setLastTCOColor( const QColor & c ) + { + if( ! s_lastTCOColor ) + { + s_lastTCOColor = new QColor( c ); + } + else + { + *s_lastTCOColor = QColor( c ); + } + } + + static void clearLastTCOColor() + { + if( s_lastTCOColor ) + { + delete s_lastTCOColor; + } + s_lastTCOColor = NULL; + } protected: inline virtual QString nodeName() const @@ -158,6 +191,7 @@ private: typedef QMap infoMap; static infoMap s_infoMap; + static QColor * s_lastTCOColor; friend class bbTrackView; diff --git a/src/core/DataFile.cpp b/src/core/DataFile.cpp index 28e1697aa..8992d592a 100644 --- a/src/core/DataFile.cpp +++ b/src/core/DataFile.cpp @@ -683,18 +683,6 @@ void DataFile::upgrade() } - // new default colour for B&B tracks - QDomNodeList list = elementsByTagName( "bbtco" ); - for( int i = 0; !list.item( i ).isNull(); ++i ) - { - QDomElement el = list.item( i ).toElement(); - unsigned int rgb = el.attribute( "color" ).toUInt(); - if( rgb == qRgb( 64, 128, 255 ) ) - { - el.setAttribute( "color", bbTCO::defaultColor() ); - } - } - // Time-signature if ( !m_head.hasAttribute( "timesig_numerator" ) ) { diff --git a/src/tracks/bb_track.cpp b/src/tracks/bb_track.cpp index 15bace3fc..01703b990 100644 --- a/src/tracks/bb_track.cpp +++ b/src/tracks/bb_track.cpp @@ -46,9 +46,10 @@ bbTrack::infoMap bbTrack::s_infoMap; -bbTCO::bbTCO( track * _track, unsigned int _color ) : +bbTCO::bbTCO( track * _track ) : trackContentObject( _track ), - m_color( _color > 0 ? _color : defaultColor() ) + m_color( 128, 128, 128 ), + m_useStyleColor( true ) { tact_t t = engine::getBBTrackContainer()->lengthOfBB( bbTrackIndex() ); if( t > 0 ) @@ -69,41 +70,73 @@ bbTCO::~bbTCO() -void bbTCO::saveSettings( QDomDocument & _doc, QDomElement & _this ) +void bbTCO::saveSettings( QDomDocument & doc, QDomElement & element ) { - _this.setAttribute( "name", name() ); - if( _this.parentNode().nodeName() == "clipboard" ) + element.setAttribute( "name", name() ); + if( element.parentNode().nodeName() == "clipboard" ) { - _this.setAttribute( "pos", -1 ); + element.setAttribute( "pos", -1 ); } else { - _this.setAttribute( "pos", startPosition() ); + element.setAttribute( "pos", startPosition() ); + } + element.setAttribute( "len", length() ); + element.setAttribute( "muted", isMuted() ); + element.setAttribute( "color", color() ); + + if( m_useStyleColor ) + { + element.setAttribute( "usestyle", 1 ); + } + else + { + element.setAttribute( "usestyle", 0 ); } - _this.setAttribute( "len", length() ); - _this.setAttribute( "muted", isMuted() ); - _this.setAttribute( "color", m_color ); } -void bbTCO::loadSettings( const QDomElement & _this ) +void bbTCO::loadSettings( const QDomElement & element ) { - setName( _this.attribute( "name" ) ); - if( _this.attribute( "pos" ).toInt() >= 0 ) + setName( element.attribute( "name" ) ); + if( element.attribute( "pos" ).toInt() >= 0 ) { - movePosition( _this.attribute( "pos" ).toInt() ); + movePosition( element.attribute( "pos" ).toInt() ); } - changeLength( _this.attribute( "len" ).toInt() ); - if( _this.attribute( "muted" ).toInt() != isMuted() ) + changeLength( element.attribute( "len" ).toInt() ); + if( element.attribute( "muted" ).toInt() != isMuted() ) { toggleMute(); } - if( _this.attribute( "color" ).toUInt() != 0 ) + if( element.hasAttribute( "color" ) ) { - m_color = _this.attribute( "color" ).toUInt(); + setColor( QColor( element.attribute( "color" ).toUInt() ) ); + } + + if( element.hasAttribute( "usestyle" ) ) + { + if( element.attribute( "usestyle" ).toUInt() == 1 ) + { + m_useStyleColor = true; + } + else + { + m_useStyleColor = false; + } + } + else + { + if( m_color.rgb() == qRgb( 128, 182, 175 ) || m_color.rgb() == qRgb( 64, 128, 255 ) ) // old or older default color + { + m_useStyleColor = true; + } + else + { + m_useStyleColor = false; + } } } @@ -163,6 +196,8 @@ void bbTCOView::constructContextMenu( QMenu * _cm ) this, SLOT( changeName() ) ); _cm->addAction( embed::getIconPixmap( "colorize" ), tr( "Change color" ), this, SLOT( changeColor() ) ); + _cm->addAction( embed::getIconPixmap( "colorize" ), + tr( "Reset color to default" ), this, SLOT( resetColor() ) ); } @@ -178,7 +213,12 @@ void bbTCOView::mouseDoubleClickEvent( QMouseEvent * ) void bbTCOView::paintEvent( QPaintEvent * ) { - QColor col( m_bbTCO->m_color ); + QPainter p( this ); + + QColor col = m_bbTCO->m_useStyleColor + ? p.pen().brush().color() + : m_bbTCO->colorObj(); + if( m_bbTCO->getTrack()->isMuted() || m_bbTCO->isMuted() ) { col = QColor( 160, 160, 160 ); @@ -188,7 +228,6 @@ void bbTCOView::paintEvent( QPaintEvent * ) col = QColor( qMax( col.red() - 128, 0 ), qMax( col.green() - 128, 0 ), 255 ); } - QPainter p( this ); QLinearGradient lingrad( 0, 0, 0, height() ); lingrad.setColorAt( 0, col.light( 130 ) ); @@ -263,8 +302,8 @@ void bbTCOView::changeName() void bbTCOView::changeColor() { - QColor _new_color = QColorDialog::getColor( m_bbTCO->m_color ); - if( !_new_color.isValid() ) + QColor new_color = QColorDialog::getColor( m_bbTCO->m_color ); + if( ! new_color.isValid() ) { return; } @@ -279,34 +318,48 @@ void bbTCOView::changeColor() bbTCOView * bb_tcov = dynamic_cast( *it ); if( bb_tcov ) { - bb_tcov->setColor( _new_color ); + bb_tcov->setColor( new_color ); } } } else { - setColor( _new_color ); + setColor( new_color ); } } - - -void bbTCOView::setColor( QColor _new_color ) +/** \brief Makes the BB pattern use the colour defined in the stylesheet */ +void bbTCOView::resetColor() { - if( _new_color.rgb() != m_bbTCO->m_color ) + if( ! m_bbTCO->m_useStyleColor ) { - m_bbTCO->m_color = _new_color.rgb(); + m_bbTCO->m_useStyleColor = true; engine::getSong()->setModified(); update(); } + bbTrack::clearLastTCOColor(); +} + + + +void bbTCOView::setColor( QColor new_color ) +{ + if( new_color.rgb() != m_bbTCO->color() ) + { + m_bbTCO->setColor( new_color ); + m_bbTCO->m_useStyleColor = false; + engine::getSong()->setModified(); + update(); + } + bbTrack::setLastTCOColor( new_color ); } - +QColor * bbTrack::s_lastTCOColor = NULL; bbTrack::bbTrack( TrackContainer* tc ) : track( BBTrack, tc ) @@ -404,24 +457,18 @@ trackView * bbTrack::createView( TrackContainerView* tcv ) trackContentObject * bbTrack::createTCO( const MidiTime & _pos ) { - // if we're creating a new bbTCO, we colorize it according to the - // previous bbTCO, so we have to get all TCOs from 0 to _pos and - // pickup the last and take the color if it - tcoVector tcos; - getTCOsInRange( tcos, 0, _pos ); - if( tcos.size() > 0 && dynamic_cast( tcos.back() ) != NULL ) + bbTCO * bbtco = new bbTCO( this ); + if( s_lastTCOColor ) { - return new bbTCO( this, dynamic_cast( tcos.back() )->color() ); - + bbtco->setColor( *s_lastTCOColor ); + bbtco->setUseStyleColor( false ); } - return new bbTCO( this ); + return bbtco; } - - void bbTrack::saveTrackSpecificSettings( QDomDocument & _doc, QDomElement & _this ) { From bad08a26323534d638ecd2fed854edc40b33d36b Mon Sep 17 00:00:00 2001 From: Vesa Date: Fri, 6 Jun 2014 14:24:51 +0300 Subject: [PATCH 24/61] Ensure that NotePlayHandles get processed before the InstrumentPlayHandle on instruments that use both NotePlayHandles and InstrumentPlayHandle, such as LB302 and SF2-Player Issue: Currently, we use threads to process all PlayHandles, so there's no guarantee of the order they are processed in. This causes timing inaccuracy and jitter: notes of instruments that use both NPH's and IPH's can get randomly delayed by one entire period. The issue is solved thusly: - When processing an IPH, we check if the instrument is midi-based. If yes, we just process it normally (no NPH's to worry about). - If it's not, then it also uses NPH's, so we'll have the IPH wait until all NPH's belonging to same instrument have been processed. There's some similar code in the new FX mixer, I pretty much just copied how we do it there. --- include/Instrument.h | 4 ++-- include/InstrumentPlayHandle.h | 24 ++++++++++++++++++++++-- plugins/sf2_player/sf2_player.h | 2 +- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/include/Instrument.h b/include/Instrument.h index 3db88b980..88c8e9a19 100644 --- a/include/Instrument.h +++ b/include/Instrument.h @@ -119,13 +119,13 @@ public: virtual bool isFromTrack( const track * _track ) const; - -protected: inline InstrumentTrack * instrumentTrack() const { return m_instrumentTrack; } + +protected: // instruments may use this to apply a soft fade out at the end of // notes - method does this only if really less or equal // desiredReleaseFrames() frames are left diff --git a/include/InstrumentPlayHandle.h b/include/InstrumentPlayHandle.h index cf472db9e..c2fd5c918 100644 --- a/include/InstrumentPlayHandle.h +++ b/include/InstrumentPlayHandle.h @@ -22,11 +22,12 @@ * */ -#ifndef _INSTRUMENT_PLAY_HANDLE_H -#define _INSTRUMENT_PLAY_HANDLE_H +#ifndef INSTRUMENT_PLAY_HANDLE_H +#define INSTRUMENT_PLAY_HANDLE_H #include "PlayHandle.h" #include "Instrument.h" +#include "NotePlayHandle.h" class InstrumentPlayHandle : public PlayHandle @@ -45,6 +46,25 @@ public: virtual void play( sampleFrame * _working_buffer ) { + // if the instrument is midi-based, we can safely render right away + if( m_instrument->flags() & Instrument::IsMidiBased ) + { + m_instrument->play( _working_buffer ); + return; + } + + // if not, we need to ensure that all our nph's have been processed first + ConstNotePlayHandleList nphv = NotePlayHandle::nphsOfInstrumentTrack( m_instrument->instrumentTrack(), true ); + + foreach( const NotePlayHandle * cnph, nphv ) + { + NotePlayHandle * nph = const_cast( cnph ); + while( nph->state() != ThreadableJob::Done ) + { + nph->process(); + } + } + m_instrument->play( _working_buffer ); } diff --git a/plugins/sf2_player/sf2_player.h b/plugins/sf2_player/sf2_player.h index e27aa8a8a..5c2f5beb8 100644 --- a/plugins/sf2_player/sf2_player.h +++ b/plugins/sf2_player/sf2_player.h @@ -79,7 +79,7 @@ public: virtual Flags flags() const { - return IsSingleStreamed | IsMidiBased; + return IsSingleStreamed; } virtual PluginView * instantiateView( QWidget * _parent ); From 40407f6ce647028a79e86456895ec48f1cc09fe3 Mon Sep 17 00:00:00 2001 From: Vesa Date: Sat, 7 Jun 2014 14:33:10 +0300 Subject: [PATCH 25/61] LB302: Fix playback bugs (sticking pitch), add bandlimited waves --- plugins/lb302/lb302.cpp | 169 ++++++++++++++++++++++++++++++---------- plugins/lb302/lb302.h | 55 +++++++------ 2 files changed, 158 insertions(+), 66 deletions(-) diff --git a/plugins/lb302/lb302.cpp b/plugins/lb302/lb302.cpp index 83b824d52..331dec240 100644 --- a/plugins/lb302/lb302.cpp +++ b/plugins/lb302/lb302.cpp @@ -1,14 +1,14 @@ /* - * lb302.cpp - implementation of class lb302 which is a bass synth attempting + * lb302.cpp - implementation of class lb302 which is a bass synth attempting * to emulate the Roland TB303 bass synth * * Copyright (c) 2006-2008 Paul Giblock - * + * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * * lb302FilterIIR2 is based on the gsyn filter code by Andy Sloane. - * - * lb302Filter3Pole is based on the TB303 instrument written by + * + * lb302Filter3Pole is based on the TB303 instrument written by * Josep M Comajuncosas for the CSounds library * * This program is free software; you can redistribute it and/or @@ -39,6 +39,7 @@ #include "pixmap_button.h" #include "templates.h" #include "tooltip.h" +#include "BandLimitedWave.h" #include "embed.cpp" #include "moc_lb302.cxx" @@ -49,10 +50,10 @@ // // New config // -#define LB_24_IGNORE_ENVELOPE -#define LB_FILTERED +#define LB_24_IGNORE_ENVELOPE +#define LB_FILTERED //#define LB_DECAY -//#define LB_24_RES_TRICK +//#define LB_24_RES_TRICK #define LB_DIST_RATIO 4.0 #define LB_24_VOL_ADJUST 3.0 @@ -143,7 +144,7 @@ lb302FilterIIR2::lb302FilterIIR2(lb302FilterKnobState* p_fs) : { m_dist = new DspEffectLibrary::Distortion( 1.0, 1.0f); - + }; @@ -183,7 +184,7 @@ float lb302FilterIIR2::process(const float& samp) vcf_d2 = vcf_d1; vcf_d1 = ret; - if(fs->dist > 0) + if(fs->dist > 0) ret=m_dist->nextSample(ret); // output = IIR2 + dry @@ -200,7 +201,7 @@ lb302Filter3Pole::lb302Filter3Pole(lb302FilterKnobState *p_fs) : ay1(0), ay2(0), aout(0), - lastin(0) + lastin(0) { }; @@ -225,7 +226,7 @@ void lb302Filter3Pole::envRecalc() w = vcf_e0 + vcf_c0; k = (fs->cutoff > 0.975)?0.975:fs->cutoff; kfco = 50.f + (k)*((2300.f-1600.f*(fs->envmod))+(w) * - (700.f+1500.f*(k)+(1500.f+(k)*(engine::mixer()->processingSampleRate()/2.f-6000.f)) * + (700.f+1500.f*(k)+(1500.f+(k)*(engine::mixer()->processingSampleRate()/2.f-6000.f)) * (fs->envmod)) ); //+iacc*(.3+.7*kfco*kenvmod)*kaccent*kaccurve*2000 @@ -249,7 +250,7 @@ void lb302Filter3Pole::envRecalc() } -float lb302Filter3Pole::process(const float& samp) +float lb302Filter3Pole::process(const float& samp) { float ax1 = lastin; float ay11 = ay1; @@ -274,12 +275,12 @@ lb302Synth::lb302Synth( InstrumentTrack * _instrumentTrack ) : vcf_mod_knob( 0.1f, 0.0f, 1.0f, 0.005f, this, tr( "VCF Envelope Mod" ) ), vcf_dec_knob( 0.1f, 0.0f, 1.0f, 0.005f, this, tr( "VCF Envelope Decay" ) ), dist_knob( 0.0f, 0.0f, 1.0f, 0.01f, this, tr( "Distortion" ) ), - wave_shape( 0.0f, 0.0f, 7.0f, this, tr( "Waveform" ) ), + wave_shape( 8.0f, 0.0f, 11.0f, this, tr( "Waveform" ) ), slide_dec_knob( 0.6f, 0.0f, 1.0f, 0.005f, this, tr( "Slide Decay" ) ), slideToggle( false, this, tr( "Slide" ) ), accentToggle( false, this, tr( "Accent" ) ), deadToggle( false, this, tr( "Dead" ) ), - db24Toggle( false, this, tr( "24dB/oct Filter" ) ) + db24Toggle( false, this, tr( "24dB/oct Filter" ) ) { @@ -330,7 +331,7 @@ lb302Synth::lb302Synth( InstrumentTrack * _instrumentTrack ) : vca_attack = 1.0 - 0.96406088; vca_decay = 0.99897516; - vco_shape = SAWTOOTH; + vco_shape = SAWTOOTH; // Experimenting with a0 between original (0.5) and 1.0 vca_a0 = 0.5; @@ -425,7 +426,7 @@ void lb302Synth::filterChanged() void lb302Synth::db24Toggled() { vcf = vcfs[db24Toggle.value()]; - // These recalcFilter calls might suck + // These recalcFilter calls might suck recalcFilter(); } @@ -487,14 +488,14 @@ int lb302Synth::process(sampleFrame *outbuf, const int size) note.dead = deadToggle.value(); initNote(¬e); //printf("%f %f, ", vco_inc, vco_c); - - current_freq = new_freq; + + current_freq = new_freq; new_freq = -1.0f; //printf("GOT_INC %f %f %d\n\n", note.vco_inc, new_freq, vca_mode ); - } + } + - // TODO: NORMAL RELEASE // vca_mode = 1; @@ -543,6 +544,10 @@ int lb302Synth::process(sampleFrame *outbuf, const int size) case 5: vco_shape = SINE; break; case 6: vco_shape = EXPONENTIAL; break; case 7: vco_shape = WHITE_NOISE; break; + case 8: vco_shape = BL_SAWTOOTH; break; + case 9: vco_shape = BL_SQUARE; break; + case 10: vco_shape = BL_TRIANGLE; break; + case 11: vco_shape = BL_MOOG; break; default: vco_shape = SAWTOOTH; break; } @@ -568,7 +573,7 @@ int lb302Synth::process(sampleFrame *outbuf, const int size) break; case MOOG: // Maybe the fall should be exponential/sinsoidal instead of quadric. - // [-0.5, 0]: Rise, [0,0.25]: Slope down, [0.25,0.5]: Low + // [-0.5, 0]: Rise, [0,0.25]: Slope down, [0.25,0.5]: Low vco_k = (vco_c*2.0)+0.5; if (vco_k>1.0) { vco_k = -0.5 ; @@ -577,7 +582,7 @@ int lb302Synth::process(sampleFrame *outbuf, const int size) w = 2.0*(vco_k-0.5)-1.0; vco_k = 0.5 - sqrtf(1.0-(w*w)); } - vco_k *= 2.0; // MOOG wave gets filtered away + vco_k *= 2.0; // MOOG wave gets filtered away break; case SINE: @@ -592,6 +597,22 @@ int lb302Synth::process(sampleFrame *outbuf, const int size) case WHITE_NOISE: vco_k = 0.5 * Oscillator::noiseSample( vco_c ); break; + + case BL_SAWTOOTH: + vco_k = BandLimitedWave::oscillate( vco_c + 0.5f, BandLimitedWave::pdToLen( vco_inc ), BandLimitedWave::BLSaw ) * 0.5f; + break; + + case BL_SQUARE: + vco_k = BandLimitedWave::oscillate( vco_c + 0.5f, BandLimitedWave::pdToLen( vco_inc ), BandLimitedWave::BLSquare ) * 0.5f; + break; + + case BL_TRIANGLE: + vco_k = BandLimitedWave::oscillate( vco_c + 0.5f, BandLimitedWave::pdToLen( vco_inc ), BandLimitedWave::BLTriangle ) * 0.5f; + break; + + case BL_MOOG: + vco_k = BandLimitedWave::oscillate( vco_c + 0.5f, BandLimitedWave::pdToLen( vco_inc ), BandLimitedWave::BLMoog ); + break; } //vca_a = 0.5; @@ -600,8 +621,8 @@ int lb302Synth::process(sampleFrame *outbuf, const int size) //samp = vcf->process(vco_k)*2.0*vca_a; //samp = vcf->process(vco_k)*2.0; samp = filter->process(vco_k) * vca_a; - //printf("%f %d\n", vco_c, sample_cnt); - + //printf("%f %d\n", vco_c, sample_cnt); + //samp = vco_k * vca_a; @@ -609,7 +630,7 @@ int lb302Synth::process(sampleFrame *outbuf, const int size) { // vca_a = 0; } - + #else //samp = vco_k*vca_a; #endif @@ -633,7 +654,7 @@ int lb302Synth::process(sampleFrame *outbuf, const int size) // Handle Envelope if(vca_mode==0) { vca_a+=(vca_a0-vca_a)*vca_attack; - if(sample_cnt>=0.5*engine::mixer()->processingSampleRate()) + if(sample_cnt>=0.5*engine::mixer()->processingSampleRate()) vca_mode = 2; } else if(vca_mode == 1) { @@ -661,7 +682,7 @@ void lb302Synth::initNote( lb302Note *n) catch_decay = 0; vco_inc = n->vco_inc; - + // Always reset vca on non-dead notes, and // Only reset vca on decaying(decayed) and never-played if(n->dead == 0 || (vca_mode==1 || vca_mode==3)) { @@ -695,14 +716,14 @@ void lb302Synth::initNote( lb302Note *n) recalcFilter(); - + if(n->dead ==0){ // Swap next two blocks?? vcf->playNote(); // Ensure envelope is recalculated vcf_envpos = ENVINC; - // Double Check + // Double Check //vca_mode = 0; //vca_a = 0.0; } @@ -711,13 +732,30 @@ void lb302Synth::initNote( lb302Note *n) void lb302Synth::playNote( NotePlayHandle * _n, sampleFrame * _working_buffer ) { - //fpp_t framesPerPeriod = engine::mixer()->framesPerPeriod(); - if( _n->isMasterNote() ) { return; } + // sort notes: new notes to the end + m_notesMutex.lock(); + if( _n->totalFramesPlayed() == 0 ) + { + m_notes.append( _n ); + } + else + { + m_notes.prepend( _n ); + } + m_notesMutex.unlock(); +} + + + +void lb302Synth::processNote( NotePlayHandle * _n ) +{ + //fpp_t framesPerPeriod = engine::mixer()->framesPerPeriod(); + // Currently have release/decay disabled // Start the release decay if this is the first release period. //if (_n->released() && catch_decay == 0) @@ -731,7 +769,7 @@ void lb302Synth::playNote( NotePlayHandle * _n, sampleFrame * _working_buffer ) //LB303 if ( _n->totalFramesPlayed() <= 0 ) { // This code is obsolete, hence the "if false" - // Existing note. Allow it to decay. + // Existing note. Allow it to decay. if(deadToggle.value() == 0 && decay_note) { /* lb302Note note; @@ -743,7 +781,7 @@ void lb302Synth::playNote( NotePlayHandle * _n, sampleFrame * _working_buffer ) } /// Start a new note. - else if( _n->totalFramesPlayed() == 0 ) { + else if( _n->m_pluginData == NULL ) { new_freq = _n->unpitchedFrequency(); true_freq = _n->frequency(); _n->m_pluginData = this; @@ -770,10 +808,14 @@ void lb302Synth::playNote( NotePlayHandle * _n, sampleFrame * _working_buffer ) void lb302Synth::play( sampleFrame * _working_buffer ) { - //printf("."); + while( ! m_notes.isEmpty() ) + { + processNote( m_notes.takeFirst() ); + }; + const fpp_t frames = engine::mixer()->framesPerPeriod(); - process( _working_buffer, frames); + process( _working_buffer, frames); instrumentTrack()->processAudioBuffer( _working_buffer, frames, NULL ); } @@ -783,7 +825,7 @@ void lb302Synth::play( sampleFrame * _working_buffer ) void lb302Synth::deleteNotePluginData( NotePlayHandle * _n ) { //printf("GONE\n"); - if( _n->unpitchedFrequency() == current_freq ) + if( _n->unpitchedFrequency() == current_freq ) { delete_freq = current_freq; } @@ -831,7 +873,7 @@ lb302SynthView::lb302SynthView( Instrument * _instrument, QWidget * _parent ) : m_deadToggle->move( 10, 220 ); m_db24Toggle = new ledCheckBox( "", this ); - m_db24Toggle->setWhatsThis( + m_db24Toggle->setWhatsThis( tr( "303-es-que, 24dB/octave, 3 pole filter" ) ); m_db24Toggle->move( 10, 150); @@ -888,8 +930,8 @@ lb302SynthView::lb302SynthView( Instrument * _instrument, QWidget * _parent ) : "round_square_wave_inactive" ) ); toolTip::add( roundSqrWaveBtn, tr( "Click here for a square-wave with a rounded end." ) ); - - pixmapButton * moogWaveBtn = + + pixmapButton * moogWaveBtn = new pixmapButton( this, tr( "Moog wave" ) ); moogWaveBtn->move( waveBtnX+(16*4), waveBtnY ); moogWaveBtn->setActiveGraphic( @@ -929,6 +971,47 @@ lb302SynthView::lb302SynthView( Instrument * _instrument, QWidget * _parent ) : toolTip::add( whiteNoiseWaveBtn, tr( "Click here for white-noise." ) ); + pixmapButton * blSawWaveBtn = + new pixmapButton( this, tr( "Bandlimited saw wave" ) ); + blSawWaveBtn->move( waveBtnX+(16*9)-8, waveBtnY ); + blSawWaveBtn->setActiveGraphic( + embed::getIconPixmap( "saw_wave_active" ) ); + blSawWaveBtn->setInactiveGraphic( + embed::getIconPixmap( "saw_wave_inactive" ) ); + toolTip::add( blSawWaveBtn, + tr( "Click here for bandlimited saw wave." ) ); + + pixmapButton * blSquareWaveBtn = + new pixmapButton( this, tr( "Bandlimited square wave" ) ); + blSquareWaveBtn->move( waveBtnX+(16*10)-8, waveBtnY ); + blSquareWaveBtn->setActiveGraphic( + embed::getIconPixmap( "square_wave_active" ) ); + blSquareWaveBtn->setInactiveGraphic( + embed::getIconPixmap( "square_wave_inactive" ) ); + toolTip::add( blSquareWaveBtn, + tr( "Click here for bandlimited square wave." ) ); + + pixmapButton * blTriangleWaveBtn = + new pixmapButton( this, tr( "Bandlimited triangle wave" ) ); + blTriangleWaveBtn->move( waveBtnX+(16*11)-8, waveBtnY ); + blTriangleWaveBtn->setActiveGraphic( + embed::getIconPixmap( "triangle_wave_active" ) ); + blTriangleWaveBtn->setInactiveGraphic( + embed::getIconPixmap( "triangle_wave_inactive" ) ); + toolTip::add( blTriangleWaveBtn, + tr( "Click here for bandlimited triangle wave." ) ); + + pixmapButton * blMoogWaveBtn = + new pixmapButton( this, tr( "Bandlimited moog saw wave" ) ); + blMoogWaveBtn->move( waveBtnX+(16*12)-8, waveBtnY ); + blMoogWaveBtn->setActiveGraphic( + embed::getIconPixmap( "moog_saw_wave_active" ) ); + blMoogWaveBtn->setInactiveGraphic( + embed::getIconPixmap( "moog_saw_wave_inactive" ) ); + toolTip::add( blMoogWaveBtn, + tr( "Click here for bandlimited moog saw wave." ) ); + + m_waveBtnGrp = new automatableButtonGroup( this ); m_waveBtnGrp->addButton( sawWaveBtn ); m_waveBtnGrp->addButton( triangleWaveBtn ); @@ -938,6 +1021,10 @@ lb302SynthView::lb302SynthView( Instrument * _instrument, QWidget * _parent ) : m_waveBtnGrp->addButton( sinWaveBtn ); m_waveBtnGrp->addButton( exponentialWaveBtn ); m_waveBtnGrp->addButton( whiteNoiseWaveBtn ); + m_waveBtnGrp->addButton( blSawWaveBtn ); + m_waveBtnGrp->addButton( blSquareWaveBtn ); + m_waveBtnGrp->addButton( blTriangleWaveBtn ); + m_waveBtnGrp->addButton( blMoogWaveBtn ); setAutoFillBackground( true ); QPalette pal; @@ -955,7 +1042,7 @@ lb302SynthView::~lb302SynthView() void lb302SynthView::modelChanged() { lb302Synth * syn = castModel(); - + m_vcfCutKnob->setModel( &syn->vcf_cut_knob ); m_vcfResKnob->setModel( &syn->vcf_res_knob ); m_vcfDecKnob->setModel( &syn->vcf_dec_knob ); @@ -964,7 +1051,7 @@ void lb302SynthView::modelChanged() m_distKnob->setModel( &syn->dist_knob ); m_waveBtnGrp->setModel( &syn->wave_shape ); - + m_slideToggle->setModel( &syn->slideToggle ); m_accentToggle->setModel( &syn->accentToggle ); m_deadToggle->setModel( &syn->deadToggle ); diff --git a/plugins/lb302/lb302.h b/plugins/lb302/lb302.h index b909b2710..b3bfb2100 100644 --- a/plugins/lb302/lb302.h +++ b/plugins/lb302/lb302.h @@ -3,12 +3,12 @@ * emulate the Roland TB303 bass synth * * Copyright (c) 2006-2008 Paul Giblock - * + * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * * lb302FilterIIR2 is based on the gsyn filter code by Andy Sloane. - * - * lb302Filter3Pole is based on the TB303 instrument written by + * + * lb302Filter3Pole is based on the TB303 instrument written by * Josep M Comajuncosas for the CSounds library * * This program is free software; you can redistribute it and/or @@ -29,8 +29,8 @@ */ -#ifndef _LB302_H_ -#define _LB302_H_ +#ifndef LB302_H_ +#define LB302_H_ #include "DspEffectLibrary.h" #include "Instrument.h" @@ -38,6 +38,8 @@ #include "led_checkbox.h" #include "knob.h" #include "Mixer.h" +#include "NotePlayHandle.h" +#include static const int NUM_FILTERS = 2; @@ -67,12 +69,12 @@ class lb302Filter virtual void playNote(); protected: - lb302FilterKnobState *fs; + lb302FilterKnobState *fs; // Filter Decay float vcf_c0; // c0=e1 on retrigger; c0*=ed every sample; cutoff=e0+c0 float vcf_e0, // e0 and e1 for interpolation - vcf_e1; + vcf_e1; float vcf_rescoeff; // Resonance coefficient [0.30,9.54] }; @@ -87,13 +89,13 @@ class lb302FilterIIR2 : public lb302Filter virtual float process(const float& samp); protected: - float vcf_d1, // d1 and d2 are added back into the sample with + float vcf_d1, // d1 and d2 are added back into the sample with vcf_d2; // vcf_a and b as coefficients. IIR2 resonance // loop. // IIR2 Coefficients for mixing dry and delay. - float vcf_a, // Mixing coefficients for the final sound. - vcf_b, // + float vcf_a, // Mixing coefficients for the final sound. + vcf_b, // vcf_c; DspEffectLibrary::Distortion * m_dist; @@ -111,15 +113,15 @@ class lb302Filter3Pole : public lb302Filter virtual float process(const float& samp); protected: - float kfcn, - kp, - kp1, - kp1h, + float kfcn, + kp, + kp1, + kp1h, kres; - float ay1, - ay2, - aout, - lastin, + float ay1, + ay2, + aout, + lastin, value; }; @@ -164,10 +166,10 @@ public: virtual PluginView * instantiateView( QWidget * _parent ); private: + void processNote( NotePlayHandle * n ); void initNote(lb302Note *note); - private: FloatModel vcf_cut_knob; FloatModel vcf_res_knob; @@ -179,7 +181,7 @@ private: FloatModel dist_knob; IntModel wave_shape; FloatModel slide_dec_knob; - + BoolModel slideToggle; BoolModel accentToggle; BoolModel deadToggle; @@ -200,7 +202,8 @@ private: vco_slideinc, //* Slide base to use in next node. Nonzero=slide next note vco_slidebase; //* The base vco_inc while sliding. - enum vco_shape_t { SAWTOOTH, SQUARE, TRIANGLE, MOOG, ROUND_SQUARE, SINE, EXPONENTIAL, WHITE_NOISE }; + enum vco_shape_t { SAWTOOTH, SQUARE, TRIANGLE, MOOG, ROUND_SQUARE, SINE, EXPONENTIAL, WHITE_NOISE, + BL_SAWTOOTH, BL_SQUARE, BL_TRIANGLE, BL_MOOG }; vco_shape_t vco_shape; // Filters (just keep both loaded and switch) @@ -215,9 +218,9 @@ private: // More States int vcf_envpos; // Update counter. Updates when >= ENVINC - float vca_attack, // Amp attack + float vca_attack, // Amp attack vca_decay, // Amp decay - vca_a0, // Initial amplifier coefficient + vca_a0, // Initial amplifier coefficient vca_a; // Amplifier coefficient. // Envelope State @@ -242,6 +245,8 @@ private: friend class lb302SynthView; + NotePlayHandleList m_notes; + QMutex m_notesMutex; } ; @@ -254,7 +259,7 @@ public: private: virtual void modelChanged(); - + knob * m_vcfCutKnob; knob * m_vcfResKnob; knob * m_vcfDecKnob; @@ -263,7 +268,7 @@ private: knob * m_distKnob; knob * m_slideDecKnob; automatableButtonGroup * m_waveBtnGrp; - + ledCheckBox * m_slideToggle; ledCheckBox * m_accentToggle; ledCheckBox * m_deadToggle; From 9cc33447560ff56ff2f037adf272652b5e634d4b Mon Sep 17 00:00:00 2001 From: Vesa Date: Sun, 8 Jun 2014 12:28:43 +0300 Subject: [PATCH 26/61] Fix drag/drop for automation patterns There was some apparently legacy code that was entirely unnecessary and interfering with model drops. Closes #814 --- src/core/AutomationPattern.cpp | 6 ++++-- src/gui/AutomationPatternView.cpp | 8 -------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/src/core/AutomationPattern.cpp b/src/core/AutomationPattern.cpp index 94025a389..c595a422e 100644 --- a/src/core/AutomationPattern.cpp +++ b/src/core/AutomationPattern.cpp @@ -35,6 +35,8 @@ #include "ProjectJournal.h" #include "bb_track_container.h" #include "song.h" +#include "text_float.h" +#include "embed.h" const float AutomationPattern::DEFAULT_MIN_VALUE = 0; @@ -96,8 +98,8 @@ void AutomationPattern::addObject( AutomatableModel * _obj, bool _search_dup ) { if( *it == _obj ) { - // Already exists - // TODO: Maybe let the user know in some non-annoying way + textFloat::displayMessage( _obj->displayName(), tr( "Model is already connected " + "to this pattern." ), embed::getIconPixmap( "automation" ), 2000 ); return; } } diff --git a/src/gui/AutomationPatternView.cpp b/src/gui/AutomationPatternView.cpp index 7f0f22194..51c2ae397 100644 --- a/src/gui/AutomationPatternView.cpp +++ b/src/gui/AutomationPatternView.cpp @@ -391,14 +391,6 @@ void AutomationPatternView::dropEvent( QDropEvent * _de ) { engine::automationEditor()->setCurrentPattern( m_pat ); } - - //This is the only model that's just added to AutomationPattern. - if( m_pat->m_objects.size() == 1 ) - { - //scale the points to fit the new min. and max. value - this->scaleTimemapToFit( AutomationPattern::DEFAULT_MIN_VALUE, - AutomationPattern::DEFAULT_MAX_VALUE ); - } } else { From 2fa7892542771017e5fc07601187763f58c2e947 Mon Sep 17 00:00:00 2001 From: Vesa Date: Sun, 8 Jun 2014 18:06:09 +0300 Subject: [PATCH 27/61] Use QBrush instead of QColor on some theme properties Apparently, we can use QBrush -typed properties in the CSS. This just never occured to me before! So, this has several benefits. A QColor property only allows a singular RGB value, but a QBrush allows the same plus also qgradients, RGBA-colours and maybe even bitmap patterns. So I'm changing some properties to QBrush, where it makes sense to allow this additional functionality - no need to enable it for simple things like text colours or such. - Song editor background: instead of the earlier hack with 7 qproperties just to set a limited background gradient, we can use only 2 properties and allow much more flexibility with Qt's own qgradient syntax - Automation editor: background, graph colour, and the sidebar colour - @musikBear recently complained not seeing the grid through the graph, so transparency can help there, and qlineargradients in the graph can produce very cool visual effects. Grid is pointless to change, it should stay single-colour for now. - Piano roll: here, I only made the background use QBrush - we don't really have much else here that can utilize QBrush, the notes have their own gradient system... maybe the 2nd colour of the note gradient could be customizable though. There are probably more places where this change makes sense... --- data/themes/default/style.css | 22 ++++++---- include/AutomationEditor.h | 16 +++---- include/track.h | 42 ++++--------------- src/core/track.cpp | 79 +++++------------------------------ src/gui/AutomationEditor.cpp | 27 ++++++------ src/gui/PianoRoll.cpp | 2 +- 6 files changed, 54 insertions(+), 134 deletions(-) diff --git a/data/themes/default/style.css b/data/themes/default/style.css index 24b2f25b2..eea6633bd 100644 --- a/data/themes/default/style.css +++ b/data/themes/default/style.css @@ -18,8 +18,15 @@ AutomationEditor { color: #e0e0e0; qproperty-vertexColor: #ff77af; qproperty-gridColor: #808080; - qproperty-graphColor: #99afff; - qproperty-scaleColor: rgb( 32, 32, 32 ); + + qproperty-graphColor: qlineargradient(spread:reflect, + x1:0, y1:0, x2:0, y2:1, + stop:0 rgba(153, 175, 255, 250), stop:1 rgba(153, 175, 255, 100)); + /*#99afff;*/ + qproperty-scaleColor: qlineargradient(spread:reflect, + x1:0, y1:0.5, x2:1, y2:0.5, + stop:0 #333, stop:1 #202020); + /*rgb( 32, 32, 32 );*/ } /* text box */ @@ -259,13 +266,10 @@ nStateButton { /* track background colors */ trackContentWidget { - qproperty-darkerColor1: rgb( 50, 50, 50 ); - qproperty-darkerColor2: rgb( 20, 20, 20 ); - qproperty-darkerColor3: rgb( 15, 15, 15 ); - qproperty-lighterColor1: rgb( 50, 50, 50 ); - qproperty-lighterColor2: rgb( 40, 40, 40 ); - qproperty-lighterColor3: rgb( 30, 30, 30 ); - qproperty-gradMidPoint: 0.33; + qproperty-darkerColor: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 rgb( 50, 50, 50 ), stop:0.33 rgb( 20, 20, 20 ), stop:1 rgb( 15, 15, 15 ) ); + qproperty-lighterColor: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 rgb( 50, 50, 50 ), stop:0.33 rgb( 40, 40, 40 ), stop:1 rgb( 30, 30, 30 ) ); } diff --git a/include/AutomationEditor.h b/include/AutomationEditor.h index 17d966037..5256cf72a 100644 --- a/include/AutomationEditor.h +++ b/include/AutomationEditor.h @@ -51,9 +51,9 @@ class AutomationEditor : public QWidget, public JournallingObject { Q_OBJECT Q_PROPERTY( QColor gridColor READ gridColor WRITE setGridColor ) - Q_PROPERTY( QColor graphColor READ graphColor WRITE setGraphColor ) Q_PROPERTY( QColor vertexColor READ vertexColor WRITE setVertexColor ) - Q_PROPERTY( QColor scaleColor READ scaleColor WRITE setScaleColor ) + Q_PROPERTY( QBrush scaleColor READ scaleColor WRITE setScaleColor ) + Q_PROPERTY( QBrush graphColor READ graphColor WRITE setGraphColor ) public: void setCurrentPattern( AutomationPattern * _new_pattern ); @@ -81,13 +81,13 @@ public: // qproperty access methods QColor gridColor() const; - QColor graphColor() const; + QBrush graphColor() const; QColor vertexColor() const; - QColor scaleColor() const; + QBrush scaleColor() const; void setGridColor( const QColor & c ); - void setGraphColor( const QColor & c ); + void setGraphColor( const QBrush & c ); void setVertexColor( const QColor & c ); - void setScaleColor( const QColor & c ); + void setScaleColor( const QBrush & c ); public slots: void update(); @@ -266,9 +266,9 @@ private: bool inBBEditor(); QColor m_gridColor; - QColor m_graphColor; + QBrush m_graphColor; QColor m_vertexColor; - QColor m_scaleColor; + QBrush m_scaleColor; friend class engine; diff --git a/include/track.h b/include/track.h index 8139ea869..df3d33a93 100644 --- a/include/track.h +++ b/include/track.h @@ -251,15 +251,8 @@ class trackContentWidget : public QWidget, public JournallingObject Q_OBJECT // qproperties for track background gradients - Q_PROPERTY( QColor darkerColor1 READ darkerColor1 WRITE setDarkerColor1 ) - Q_PROPERTY( QColor darkerColor2 READ darkerColor2 WRITE setDarkerColor2 ) - Q_PROPERTY( QColor darkerColor3 READ darkerColor3 WRITE setDarkerColor3 ) - - Q_PROPERTY( QColor lighterColor1 READ lighterColor1 WRITE setLighterColor1 ) - Q_PROPERTY( QColor lighterColor2 READ lighterColor2 WRITE setLighterColor2 ) - Q_PROPERTY( QColor lighterColor3 READ lighterColor3 WRITE setLighterColor3 ) - - Q_PROPERTY( float gradMidPoint READ gradMidPoint WRITE setGradMidPoint ) + Q_PROPERTY( QBrush darkerColor READ darkerColor WRITE setDarkerColor ) + Q_PROPERTY( QBrush lighterColor READ lighterColor WRITE setLighterColor ) public: trackContentWidget( trackView * _parent ); @@ -282,25 +275,11 @@ public: // qproperty access methods - QColor darkerColor1() const; - QColor darkerColor2() const; - QColor darkerColor3() const; + QBrush darkerColor() const; + QBrush lighterColor() const; - QColor lighterColor1() const; - QColor lighterColor2() const; - QColor lighterColor3() const; - - float gradMidPoint() const; - - void setDarkerColor1( const QColor & _c ); - void setDarkerColor2( const QColor & _c ); - void setDarkerColor3( const QColor & _c ); - - void setLighterColor1( const QColor & _c ); - void setLighterColor2( const QColor & _c ); - void setLighterColor3( const QColor & _c ); - - void setGradMidPoint( float _g ); + void setDarkerColor( const QBrush & _c ); + void setLighterColor( const QBrush & _c ); public slots: void update(); @@ -343,13 +322,8 @@ private: QPixmap m_background; // qproperty fields - QColor m_darkerColor1; - QColor m_darkerColor2; - QColor m_darkerColor3; - QColor m_lighterColor1; - QColor m_lighterColor2; - QColor m_lighterColor3; - float m_gradMidPoint; + QBrush m_darkerColor; + QBrush m_lighterColor; } ; diff --git a/src/core/track.cpp b/src/core/track.cpp index 0c04ff369..510f2dec6 100644 --- a/src/core/track.cpp +++ b/src/core/track.cpp @@ -847,14 +847,7 @@ void trackContentObjectView::setAutoResizeEnabled( bool _e ) */ trackContentWidget::trackContentWidget( trackView * _parent ) : QWidget( _parent ), - m_trackView( _parent ), - m_darkerColor1( 0, 0, 0 ), - m_darkerColor2( 0, 0, 0 ), - m_darkerColor3( 0, 0, 0 ), - m_lighterColor1( 0, 0, 0 ), - m_lighterColor2( 0, 0, 0 ), - m_lighterColor3( 0, 0, 0 ), - m_gradMidPoint( 0.0f ) + m_trackView( _parent ) { setAcceptDrops( true ); @@ -894,17 +887,8 @@ void trackContentWidget::updateBackground() m_background = QPixmap( w * 2, height() ); QPainter pmp( &m_background ); - QLinearGradient grad( 0,0, 0, h ); - grad.setColorAt( 0.0, darkerColor1() ); - grad.setColorAt( gradMidPoint(), darkerColor2() ); - grad.setColorAt( 1.0, darkerColor3() ); - pmp.fillRect( 0, 0, w, h, grad ); - - QLinearGradient grad2( 0,0, 0, h ); - grad2.setColorAt( 0.0, lighterColor1() ); - grad2.setColorAt( gradMidPoint(), lighterColor2() ); - grad2.setColorAt( 1.0, lighterColor3() ); - pmp.fillRect( w, 0, w , h, grad2 ); + pmp.fillRect( 0, 0, w, h, darkerColor() ); + pmp.fillRect( w, 0, w , h, lighterColor() ); // draw lines pmp.setPen( QPen( QColor( 0, 0, 0, 160 ), 1 ) ); @@ -1236,61 +1220,20 @@ MidiTime trackContentWidget::endPosition( const MidiTime & _pos_start ) // qproperty access methods //! \brief CSS theming qproperty access method -QColor trackContentWidget::darkerColor1() const -{ return m_darkerColor1; } +QBrush trackContentWidget::darkerColor() const +{ return m_darkerColor; } //! \brief CSS theming qproperty access method -QColor trackContentWidget::darkerColor2() const -{ return m_darkerColor2; } +QBrush trackContentWidget::lighterColor() const +{ return m_lighterColor; } //! \brief CSS theming qproperty access method -QColor trackContentWidget::darkerColor3() const -{ return m_darkerColor3; } +void trackContentWidget::setDarkerColor( const QBrush & c ) +{ m_darkerColor = c; } //! \brief CSS theming qproperty access method -QColor trackContentWidget::lighterColor1() const -{ return m_lighterColor1; } - -//! \brief CSS theming qproperty access method -QColor trackContentWidget::lighterColor2() const -{ return m_lighterColor2; } - -//! \brief CSS theming qproperty access method -QColor trackContentWidget::lighterColor3() const -{ return m_lighterColor3; } - -//! \brief CSS theming qproperty access method -void trackContentWidget::setDarkerColor1( const QColor & _c ) -{ m_darkerColor1 = QColor( _c ); } - -//! \brief CSS theming qproperty access method -void trackContentWidget::setDarkerColor2( const QColor & _c ) -{ m_darkerColor2 = QColor( _c ); } - -//! \brief CSS theming qproperty access method -void trackContentWidget::setDarkerColor3( const QColor & _c ) -{ m_darkerColor3 = QColor( _c ); } - -//! \brief CSS theming qproperty access method -void trackContentWidget::setLighterColor1( const QColor & _c ) -{ m_lighterColor1 = QColor( _c ); } - -//! \brief CSS theming qproperty access method -void trackContentWidget::setLighterColor2( const QColor & _c ) -{ m_lighterColor2 = QColor( _c ); } - -//! \brief CSS theming qproperty access method -void trackContentWidget::setLighterColor3( const QColor & _c ) -{ m_lighterColor3 = QColor( _c ); } - -//! \brief CSS theming qproperty access method -float trackContentWidget::gradMidPoint() const -{ return m_gradMidPoint; } - -//! \brief CSS theming qproperty access method -void trackContentWidget::setGradMidPoint( float _g ) -{ m_gradMidPoint = _g; } - +void trackContentWidget::setLighterColor( const QBrush & c ) +{ m_lighterColor = c; } diff --git a/src/gui/AutomationEditor.cpp b/src/gui/AutomationEditor.cpp index 2f1577793..71abe18c1 100644 --- a/src/gui/AutomationEditor.cpp +++ b/src/gui/AutomationEditor.cpp @@ -98,9 +98,9 @@ AutomationEditor::AutomationEditor() : m_editMode( DRAW ), m_scrollBack( FALSE ), m_gridColor( 0,0,0 ), - m_graphColor( 0,0,0 ), + m_graphColor(), m_vertexColor( 0,0,0 ), - m_scaleColor( 0,0,0 ) + m_scaleColor() { connect( this, SIGNAL( currentPatternChanged() ), this, SLOT( updateAfterPatternChange() ), @@ -507,19 +507,19 @@ void AutomationEditor::setPauseIcon( bool pause ) QColor AutomationEditor::gridColor() const { return m_gridColor; } -QColor AutomationEditor::graphColor() const +QBrush AutomationEditor::graphColor() const { return m_graphColor; } QColor AutomationEditor::vertexColor() const { return m_vertexColor; } -QColor AutomationEditor::scaleColor() const +QBrush AutomationEditor::scaleColor() const { return m_scaleColor; } void AutomationEditor::setGridColor( const QColor & c ) { m_gridColor = c; } -void AutomationEditor::setGraphColor( const QColor & c ) +void AutomationEditor::setGraphColor( const QBrush & c ) { m_graphColor = c; } void AutomationEditor::setVertexColor( const QColor & c ) { m_vertexColor = c; } -void AutomationEditor::setScaleColor( const QColor & c ) +void AutomationEditor::setScaleColor( const QBrush & c ) { m_scaleColor = c; } @@ -1387,10 +1387,10 @@ void AutomationEditor::paintEvent( QPaintEvent * _pe ) QPainter p( this ); style()->drawPrimitive( QStyle::PE_Widget, &opt, &p, this ); - // get foregrounf color + // get foreground color QColor fgColor = p.pen().brush().color(); // get background color and fill background - QColor bgColor = p.background().color(); + QBrush bgColor = p.background(); p.fillRect( 0, 0, width(), height(), bgColor ); // set font-size to 8 @@ -1768,12 +1768,11 @@ void AutomationEditor::drawLevelTick( QPainter & _p, int _tick, float _level, rect_height = (int)( _level * m_y_delta ); } - QColor current_color( graphColor() ); - if( _is_selected == TRUE ) - { - current_color.setRgb( 0x00, 0x40, 0xC0 ); - } - _p.fillRect( x, y_start, rect_width, rect_height, current_color ); + QBrush currentColor = _is_selected + ? QBrush( QColor( 0x00, 0x40, 0xC0 ) ) + : graphColor(); + + _p.fillRect( x, y_start, rect_width, rect_height, currentColor ); } else diff --git a/src/gui/PianoRoll.cpp b/src/gui/PianoRoll.cpp index dd9178ed1..59a1cd488 100644 --- a/src/gui/PianoRoll.cpp +++ b/src/gui/PianoRoll.cpp @@ -2887,7 +2887,7 @@ void PianoRoll::paintEvent( QPaintEvent * _pe ) QPainter p( this ); style()->drawPrimitive( QStyle::PE_Widget, &opt, &p, this ); - QColor bgColor = p.background().color(); + QBrush bgColor = p.background(); // fill with bg color p.fillRect( 0,0, width(), height(), bgColor ); From 22cf0db03dcb2d318b13f21fc86c50aedefc21ff Mon Sep 17 00:00:00 2001 From: Daniel Winzen Date: Sun, 8 Jun 2014 17:49:04 +0200 Subject: [PATCH 28/61] Updated German translation --- data/locale/de.qm | Bin 191705 -> 240099 bytes data/locale/de.ts | 1870 +++++++++++++++++++++++++++------------------ 2 files changed, 1137 insertions(+), 733 deletions(-) diff --git a/data/locale/de.qm b/data/locale/de.qm index 0d300fb4e46ff3368201799955f0875081c24e15..534645fe5b83ac1e0679cff8b473cd5c4f5d8687 100644 GIT binary patch delta 57150 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 L**mZ#wNn2N6G9s2 delta 19487 zcmb7s2YiiJ`2Tax``$gWi6AZ!#0aq?wite6s0z`YVZH|-dDAe{yx9o|D$~0_q^vk=bYy}`y{~RO{F%xyI0!#${NEC$k?rn*hbiqQgnI_$V-x4*$d-sJzZ7LFt z>o4Q|sbsM?utvSmFbf|fqPEM3(maUTS&1gCbRgSROU8q@fFL&MSKu;Y+cwB}FqJ5D zKk>58GUmh)Mf^bYIGLz(AEHYKWc=eBAU5{|8;S;YJgCgb5wSamSb zbQc-_YE0ClF4$F;s3)E;XUKSSkOR4CE>Yio;NUMZ+IA2Puo1;xz-Dk%@x6fHSo{Q{ zk(jIhLgE__5xuqSBB9z|ViO{OzW_&&&>F1la*%|!U|pAV5<-B{l}HHx1K*bc9|KR2 zFb9OA-;%Hy*xieS=a``TU=q8JA$BBR#?#-En2<$uf0qMUPzMt8+7oZ$LgLhM#4Njd z$q$EIN&J2|@iG@>%uXk9#TnurXGz?2h1e_**gT%dcumHkwSY^AP1`KvtR}!Kkedr6 zZu5b#Vd66)(G)9*=RXje{ilri{to0#dpgj>5;9u5lcE7M zsP}asj-}5XQncxc^WQs&6z%E}+gz6vAw40Cl}QnX1^qP9fqcvWQgqIQjJT6xfEV#; zuA~@2`(bMSzBBQ(SJc|@fq2`=)Ov0Y zVy7=rn^6ad57$uJIs0LLVV~^yo>ALXXNj8*P}`fo~V;N5&LHl4_%oLKm5d%VHEcBqz%CKl1Zc%8p zF+`DDD70~Ne4j|6TOsWk$7Hlzb0Ax1ruN_E5^d8^*t}R`D<)8QJ?QtwOB6oZ3+nqy z#vkTW_@qf#Xiw@;1%}UZ^doi18$fJb1L_z%0_ygfBD!LSm%JRvHhEH1HVjPfu|NoE z?*fV%4dLo*qo`a6SKr$dwdORj_Tkjo{~2VZBX#b937lN0^O{1mU!=}QH$v)5$~fvc zb-pu<=#S&nrBgoaf4x4`rQdAg;kndhAk66A?Rw`>1Ooj$rdb>iQnqG-sOwdDq(1%`l$Wo*(UK zA$E8>b(@4Unq#6KHPLa)3K{pCsmCB3$?*ai&%dJ{E1|Aiv#H09nZ!0lP>=no#G}w| z#{`jj3fOs02K5{`2{MsJy_CQLJ@u}yA=YpM^?th&YJ86RmrA4%=VW}m(19%Q3@sgd6hg{r*^p_($_LW-tQD~j zHE8AaEaGv~Xzd|0k;yT8Eg^ zdV0OUN_1@oqmrSZJAtVuz9l|J&or^yi0w_5@$f?n(|>R!)^iXuxaJdm>&x6~Vuf>W zGLIjsK_?ixM^$4LB2N)>3t=^*rxIKIgw@WUim0h9Yv5dgSm_b7`H~ov-MbvT?PU|S>n?(#9oeN$)$Ee|GTbcX}>llu7AXaHmpTFZ#x@q%|eG= zYy=3@RpN)GXFL)pwTIMcw*Z21p}4ac8k2Y4pbk+CD=;1f!%WJlK}!lp~?RD&wS zn;l?h=Xn#A-N?@74?w_?!OlMPAin!scA+7(;)g~_#Y;uEj4JFQw0rL9E7wyLn{l11#()?^|;x z(N`v(KG_#Xk<2q!9e@Qi@L>nG6L0sD=ZpXc>L2H0HUtv)@#9~4T6~GMIm9P5gm5(Q znI8N>yYa+U_vcR@ zefUz znhPGmFf>sSLMh*S2%(u!HY%76^^};7e-m6qb_KB7 zv%Zi$#|2TTvyiNKDP#*<%HV9{jl#ATIYfE0gdMkG`?EXBIKGmw<4F#*qqDFdVHQPx6!!11606Zp zIDGXxVigVxCn7j-rf~9y>%^5d;nbS3#H*YV3hUoRT2|J9?D=%z>=AJG`efn!iWczy zT`%DQfkihb;o^x7#O_ZQE}k2Q==7X$Ng4=N-4<@nhExv@7w#;;5!9b8+`DXlUoQMP z4?CFGRCw$(gV?pb!mHaqA|{L$KK3^fQ>BWEmU9vRe-L#|1jtUj=yY}~5*&-@>;^3> zT~>5{RR{X7TPM19Uj=7l5pcbUOtXT{Q#Dt@kiH)ZBK^XsD41#P@KR2;)V+E4b+A^2zVH!~WsJQn#+7SAta=wQUWWy& zn=AIWj7H|u+AI#(eUezYMPlOkk;s7NivvewVnMFrAY~}Ab2c&QCA`+AdSd$PP@)pY z#GyH6Bqq(pp<|%eOSLlYt>!>J-6Rgf4te_+arn2L5mD8XaoiVwy5y-Y}?B4}Woz^?MksO)?%_FHTyQ zg#}HQu~xfJcu2;8uuu5416hT4GWrC{SarWeoV;Q_k!6enSraF5>e|Urw|(Nwk-5aX z_=whM2%XnPac;?JNrgx_z{OkA`UM-lT% zT)G}CfBaZnt_SC)XvI~7R}(v9c_6Nt`WJDx!9YZ@Zp(nrf#-qnitbwA8(0las}r2VkJY$KuYjFu_fBiAOIRq5pF- z#bd2OxYttg`0|Iu?lc!q)b>Kf;;92!&~)*aDzNFTbmFhuAZ)ibh`;VoAZTqO-srcH zXy7IB-s2XC0|LZ{1C|o)xg$Ovf;b`Qi1@m>fNI!9@pVE9d`X`8E_feNejo8&dmlKp zmg2jJR>mL%Wo}ut7Y54}i*IMB>Y8)mWr>OB~7ufWJ3jgK%q1Rg#0rlV=BXx>8&W*6* zJQOYvPWNe}Xz&}bZ+k_9%P=T?HYpme-izF?uA6>+N|#bUvW~# zb3+yF8rnH|K@nm8K=g6BqLW414uh~k(P{n_qU%aUrw_r%a5gG>tUQ3g;SWWxR{li8 z;uSHi4+85bVlGxCp6aYfuw5Y@uuU-_unv5}T1Ap=Kheh5GG3bKK(^VeNLvLNx2j(7#NV%QOEFxyRG$xej@YgSz`z6C7Z?qC@Yy-`dU1mQVqROGcs6;oAD zk+;4oa=;YDl%K~S=-j55+GZ2+Rw0V%L%oSxyD4TY&L@^}Tt>?|g*0V3=*?HmBbewK zs}&26#u1Nrq*&yJ@Lcj#EQxGQ?3G|qEcxpua(d7wtL zN3k`v4^iuxif!jnAM_lhI2<$yS`n!Dxiya3+wzy<=N{ORTRp|O#`U0HgJiroPsYp3 z9LTOTav(2PAY*7##jhDCzkMqye&4nYN#!iX6G%6^aZm9)`x>!RH5D%oO@w7VsCeH4 zDOo`?C9QxZeO+Ct>~n&sZb_y7g9|ZBj})a#>u-p4w8;4T7NzTJu%_(-rQ4`j=rJkF z>_bX6Vz08?FvJ5RVw66uL9opjW#u6U;9ff_tKIY=UTM5CU?zmI$82T5{656Lo35-s z5?bW^K-s82CQhHEZ1iXL+ScGsoTTpho>j$BFp^Tc{o!F$m zlwAidMB!nHvg@08qFQ5=J*pvcTHZw2b0(Zm`dB+c|A(AZCeb{ia1UjY+fG!q?kSU7 zK7mlqSEl#(Cbs0ha;V9Vi03Fr+%E)+`zdoPBlIdgSUEnTBo^Q&)!zdn(; zSF&<~J+$*Wp!{lP4H&eV$~>Rh#9YcMr?kQMGL@Cq6P61I4rePDuYndE*U5P9jdFS5 zZDRhtl&ijmdp^2T#=>sOwF3%?J2@-Y&1_2SudB-Zb+y5fa?16)p#S~8SN_-l_997A zZrK2J%o0E0eC44kD3c7msyt->p1e$X_|aF;qI=3C7Wdl36*)28bx?aQac%MVuR?FEeZ^D2w8C=d&^shsEF?6#bh zalcjNW%@uY{*1~Cmj-;cLRETSO9)S)%5F;OW(fzf>?JaeAFisDJ^}`4g{ra+bhf6; zc%YW5it!B6?s_V}$KK$;L{-(cpxbw!s``{*2=7vhs$L3gvY=Kq%!Z9_T1^$?3Cq{G zl`7~e7FO^?)wm!ECRwLy+CxB8>#u62%OUdFplY^p57h6vs#Rs^^M>lGkX^fQWs|Jx zvN8mfl;#d(udOP(C8ho@s-Ej$A3R-Ey}IG34KGwNrIw=zWoe^|I|Tz1o~|0u1}lu2 zq8bny4R`xQmDmDm<1$Q@_#;+aah@vKALx{*8oC?$yS%$Y(osBYgvUGOKZ>d%E^V7Qd3 z2UDS5{(|a7o*(gwTU0M=?}Ha?pn7Tj17-TA4rJ9u)vH3-3soJ}d*xo_|K)#CE2Fe1 ziL6&^1!vgko@$pycsE9=-L^og^OvdJcEGSGnYz@4Z-~zj)fG=dCZclGHKJfhmX4Ki z?@kBu>C@D82Ed)~I-?G{=n6gGrfyqv9?rPb>d1IKSKakQ4)Olg)Uhu!h<6&Ij%%iXg}baaw`Rn;%vGD$JSBFi zhK!eos0RkmBG%kbom_Vk?hAs|DTB|Vj5kC*BJvY>n z1r2=K74>3qCUNcW>Xj3xqIkSZz3#`Y@Mfdb>tDs=DkfLGaojybtL4?3M~9*$qg2}# zA&_W!LcP@s!nMO&y>0kvT;CmXAZv8pfjo4CdfTDbL}NqM+ivzjF?ykTdjyUoBU!z3 ztq40Is4cr^YEhjYqTag&YBF|>16k7<>Z7Zk!y<;rcs^Hs^hF_Zszmj%xQ4_#)>0oU z?2XiFh>Qp8s!zW)Biq%huP%jck1VOadj1u%-ca=)9l`pa!qhjC;}CZDQ{TF|iP)+^ z>O0+$P2YN8QNN#p9b^`0#CgDij~e|tNPC5n8h3+ToeDK&PQN9-^Jh)PWg4Q|lQh0% z&k&VM*7!A4z;LzJRK0rx7ZYnW{`J7>)AKZSDkD_;ak8fV#MY3R1Db{tu(0pyIgn3X zq6rN3fW@4q3EYe$ooumb+Kz|w+5JKjlGz=V4wWY4?Gi+_b2Q=oq3;DNH652g26o-o zbp8_y85gbT4!gkn{I2PKA_KBANi!hCpID@m19`quGw1@Gns`%_)bIh0<||EF^_$?# zNKM+Z=fuOeYleEmZd~Z&KxS$BTr+GIN-l%OXhtoKg+Upj89livv0eil$TxJ;%yEPkDgOzP1&DL^Wu<1QD zTib{TFm7pn8hV1r?Tuzn`xIjQz2-n;Gx4e!n!`;L#D~q%ocJ9_(zd(i^lAv{g)W*x z33PInXs(tyg8N{V1KGQ+nwv%#xC{5~2v%JS*W4WJO?2kE=85hN428Sq=|_Rsj|Vib zdO=;5o|JK))`5K8F3lUX^9a4>T|VxM)1ox*yTA_oSV_xo;LOV((270<@T%vu;_E@g z)~?rTGHVm-o~YFpz|@~_taT29LEC#t>o(F72ul^L^;ysg>gT2PE!;@d$xmDPcX#4y zo3>iaLO7LG+J=#E9=r829@?u7EH@tExmp|8{1MUB{@O-;PY_EPqir)`I0}(r+V(%= z!g*V)Hsat>V$%b)k$tWZ>(o>mwGi)N{k7fZ9YuOxRomNA%SbHYH*I`ltmr_t19`}1 zt$8a9%*KA&1a}bha?&Pro((5dU)#T;FR|y(w8^oE?R4F>8C8s^?`_v+dEQ06znXUF zRIt87f_9j#Dx&5>?S#T+P(!YrqJe^jbye&iM6<1D)TYDDcG6W&hT2`Jrt=$ye8JgASM8iP zr2nz5hVB{BRI{#*BM?c_1)d&`5^RC4gKav>Z~b*0lkedQ=BO^JawrT_SzT1;6#V?a zD+hARxJSBPznw*g3`NbSo9KIvOOeQw^YV017+M_ zMaIi7bQy-u;Lv7W))81huM}P0FD4|LLAr@o!O201y2%w&hz`})O>u%y*S?{fGjkPL zc*R<}Ma`bUx%AU5%SJkVO|M&ynh&L2lX1vM-C7G)KCO~2Kl&TQ1xs`rr=gyoy+OA< z4?*hcO}f3mL%n{UD&yIEy8R7N56H{b9fa4UzmjzaH#LNbAF4b4vJZrAp6+yASVXIn zu2AY{fsl;R6|SEJTU}T8>$dSIES%E)RvUI;YJ1&pjd5m?+Z@RAzt`QyH7l9zad-1aPXAP*U;H>htyh&$?C zyex168H@ELXZsUPFv<8}j|17lwlZ#it}lHQUM;DFzCym0c%wpn#Y#|1-`Dyoci`2g zPtjMKq6LRGI*>J9>OkJ1oxX<8OZXOdeU1AMah3B?U*jpX>s(EJ;~`JLp||=bmL`3O z)w!T=as)ppRBNj~tR5nh+#C9c$^(hFROq8WxS`I!MjtZ~l@Y3;k5g7a-EW*e&OZ+N z+)2io78z@4Weia1)>|@{LpWkv>PL;~M=W@R zeu@V1`|LIPuYcC!I)0>n>MN*UaDaYh{t2RzCG@k_-o^D>w*H$g5K7x!8TYNwulfZR za`>+@j=id1J#rg<6eH7tyyFP{>P4_K=XdDW8xeS1n6F>I?Fexnn??TgDN=I2Rzr>ZCuC_Z0X{f3&a^%JzBs6Lb*~ z)D-=dIY*H}h3T&aP9nDRwu}cC=_O>Bi;w&; zZlL~k-bd7a*BBJlu(C#J219{2(TlSNmz9VO`7484`f6Os_!_DNBeoMW4gSaGAyL_2 zXuduR5l^xM+5EXO-dJVmaSQ!hBpPC#r4oDd#t@5Gk=OS$#O=F?AorGxmYWM55A5m% z2l9xuGVV|t5@HLXRzU_wAd#}bFti_bP74jW3xT)3mhpD7A$Kv}Z+jZXWy2!&@-a+| zf{b*$W0*Yc3=B~x!}KW!P(3T{K)&I zRrZ46>_m9gh%5)P_a?*nXQ10>xZ$dB53)4IaNTwsw%^rot7aeQe`ja=1Mwej86F?T z8HMHGJ(N2EHZkgdSCbep?PR5kBSA$>1wQW6yGQJG}d1F9QXPCjDcBEu<6H)LD?5k zf~{a|?AH>P&<%}Ek6@zlKE}2OZo;B|G)AnShXTh^W2Zlw63yFa?7sg4@v$0XZ_5J^ zocX~R6OWzcD2;Ii{SnFJ8dEOsMJAJDw8X>El=m`@@0f-&zhwMs(SBULyf<2xbRep9 z)0poE_iD>B<~JJ+4$L#IZ=8o{ccgKv-&A6m>tq~lGj892Z23(+o^-x~B=M5*Vpp6|i_OMMw{XU#sv57k!2}OGDdU)P#_L~45Dz_TykW0m zRsCSR`3znzEZBH^8-#C0l=0bLi1o^sFuooKHy&KWiE9Sdj}R9Xf- zPj>2ddME0B-#PU#;PUzFnod23RfU1GFsGhtp{J=|IrY)BMq2#Jsh2qJ`9WRSa>*&};uhj`!D;wzIFsbAPL|0th^>6>GCXuVaFfP9HCAC04CZ zBJsTu)-v^eVYRIf>b1nbwdz-5k=CyDI~Dv~|4+{9OEt%^($8zAa^a_@+Y9#%gby zIRCqsoq*I&$2_dxzV$2G_3GQ8q7C)mH7MGU_pV~mhC}a6MH~40szn>xzOPcWVbYfk z$KQJw?V5xC1%1j&Cq?F4 zv^iSA>K19SR@zvxNP~1k!TehNdr8rW=An+WF;YuvO_BH;LanIX=Oa}_w&>8dwF;;A z?_ttFB`ZqWwo1toc#+v`RWRl8b?P7j5yc z%IY|ONvYs*;|iknTI)9KofNT>m6sNz32JNOjz(+WHb$2)O2wZvN~9F(PcbOOCYi;1Er6ZrSkCdvY_c(k{o0gf>>(8EqL%`q~=nw#!c zaI@`6ZuRa|wctvqT4b)))X2ckI}(Ocs1e^7WmmuR8Hf6ez-XLnZ6Gy0g;`a?{g0;72wW1iM0gMFolW?U_m+0IG` z_A@gL%r2PJzYCY1wCDa-!$4Q5(i>(hs5bBs|ClVjw2mM zU5d_0^0Q9Msq9f50|$X|cJZ;3 zGUNQJOPxkAH-r6C61{*F#L)n$W;QD&^}v#(=Z|q_wxkkL*fyrMMhtKlqNuWzyp35( zUTc+<7&pi?z?^P2#iYcWGR#TlxXc>Tlbx(aH~GahBqk}#oZ)ZkJRmW{g#S{^apsJS znDpVM#01mu)GX7`n3POYW~wPJE3>*OE;VgY?te>K9GB-ITXj5G7=KV#}L{C=ji>5-)Vl#S`D#pcL#hVtEDkl1uOBLg_ zuU9b%9_YntezAxx#e2Q?Dn`C>>0;!^l`cm9NNHC63-az|ift&m3@i6VuUTbSz<-=y zMd?XdR!-8CEk>h#S=QnU8u!bx&@Y-gd$YPkMbQ6nI8MCG5^p-4_lNlh=t5y`buu@mZAso2bO&}1n- zjZ%)#KTjfLrY9Dg!eNz-2o~DoPe+7A!PNTm2xY5w9V3II?1P;D?dbnba>yG42RXt> z$yAxuZ2jN8{`btQ$T(YvDr^rk6ls&}=~2ldO`jLxC2eTT-K}R|ITf(U^A!b4XATjp zSGQLwsIa)PP~gAu+aQlxSZ5N#z!-#aHITyC!`(!w)_Y#2K=oK)1wTC*B9yLGBx9+8 zl*%6D#US=GOEG)6sUZG&KY`UKIPhu^lP*_fjpkHmdfT#UtRVeRqz$3$tsw&BQt-!-Hc4CCvlv_dFxHoU@u9E-{7;d-Hs_A) z7om&^htz^P;BVOHLsGTrW@^>0LzooMg_W~ijASoa(XrB%&M-Db$VnjQDb?%3x=B15 ziyRrvUWwB4&8(WOTQAm6A)Ok?zm_WXW2J1@V%eWMn@cKlceiDaW$vPH2MPyIk{lUE zICvEAV62HEz}8e6h?YS}AHVsEm2GOGs^m|@An!^4ia0BWXC-AOhMVIPV@wh0sRNNI zn5tCuPfkuVIsP317?zymC%Irg-%0=1>Ab5`5dQoh76%!KmYU`HTP?QHYV|_*BPIrFm1>q7_TNW-25O7ZpNTh1ezK?{7zs)KeLGW8l_qrSSRUNFBT}3`H^+BChYN)Cj7`MOR;IZycE2VRkj}76D+MP zVEe2AOTDEDXptUmWLIr7H?y0}mT`r(5^OiFGm+W6Z?Y}SCaQQ3rOo2byH~OaO?WAT zo09BFe9C8e;jzP|m^QqegwIE$&0)NZ4VmXG(RM0=n;B~%0jWc44oE}>5gpap1j%gMB}6*ao|~l8k$k1JDTff0=Np(B(@oa#!AYO=7LQe2UVrHS98hW6aL(dV5hBV#fXQycx$%UWuZpIdB9Mn=ojROG1Xtx{7m z(^Hc&r0|-8sltDK`4j-#vrf>qZkXi$U%jM$k615hc??go^^WBh!RD911GUoT7p$}G z>uf$-L?S-=B`;}vG=>Lq7HQ{RS*guJ{9{x@vDz+qX-&n`m8e$WvOrg1bv6*W$G7AEh6b^IXZYj{C{4 zwZ7+)WX$Jf<<~~}yq5f=T!EkE8=lX7Axr*1YDNpgbf~pbh9W17__&D?Mu$xVL z9&ayj*~Kx%Zpfv<&$(L_k5(}$DXE#Jgmklcgc((XOq@uH{jgM@p6$$MYU$KbR;t0E zPgd9j(`A=rS-S0Hi%(&fZ@a%h8BB`#$lO%+;z&HjNP}(MEx?3j*o$HPBvcB$zF9y1K|`5je;Y(YGHMx6j!cI>f0GP|EDFR4w9a3 zPRUFfZi(RDjiFde!tI4NFVR<9;GUvM>c!4PTxWvI&5ZXV`#ppF22C@PDj;RV?uj zDM!!$Dv0@VO`5dkENcwnch0gnr!R<0JMTd>&*jIqY=UEV7*m>59rOo*j z3B_NFkY_jemARmK!mn%=p!5Y63P`xX5&*|9uqA-hi)=rj?r&@{c766Y6t?jC^pc}b zkIQT=-c(mu-+vY^m3qk6*~UKNcSM`_b6$nnetE$|m~GT6-axSN4}1ihT|zj4yPTMC z?xwRBu3JL;Gblrf=*r7`dZs01^@s8#pt2ZiH{^C9hE;6sPOpPQfb8{PRMVwe?|5ZhFeJ-f9?n3m^<$QYl>H8NwPPUD z=st^Zj|^$WJD#T5jDTB?M%xZYeZS6oUSGQQ7IU8;iU1?B9EuBb-*ZovDQ$SqJ4vHH z;-WBtZlDY~`6KVZhDaAb^2WCLf}l}J=WemSEJNCG7vV?fZPvsyBPKa5$=ot4A;B!) zPpyTZ+HV8ahnJSJ?=ro#|29i6DMxAcQhl9&MQKq|i#sgLU=PXC>iF5!S)U=zx`VUG zklxkH_aU+w(v|xxQzO&v z+^VA#&_|fY4H?p(f3o`c>hr+CudxqUPUz=OpVNvGU!((3;7=B%e?CEdl!Lpb%=DPJ zLH3pDWExWMFjj}_GNhb`ECREfe8{>0d>^su@|%b4d#zAP6%Z^tH;AL%W!Mubd(D0b z{$}EUGaac)7_3wI1P^JKi!e|MbQ8MRT-}ArMoT0jAG`S5&5+&u*lnaesj#Od@;V~WW`9dX zdy0L-K>G!Q{n>069=yk+^&NciAUl=M4Dsuj0#}umj-tM4ka>893B}}33#{QV8>VDs zOiETvQj(Nw6iV0vD+o;lTZKx3H?!TYEbL^q2Y!Mm+M4?d&y=>zdO|L9M897(6rS0x zHWIYl7SdG6U{YcW{K}=eop4>M(O$S8(<;lHyJF z;ACieVkR6o>cf6KzrcId5rhf=k7EC;aq9eWR0`JOcc+a9R-YShICbdY-OQ> zw~(JZ$xuRCtmI1OC3RHtlBQu~{wyhmu*4K|OuDIijhJDH8Ft;Eit7sH)h&=jQkmMcPODf1V@nb$<{TNl3pWQ8vBgn zif$a!NTZy&m!U{UY5fc2J1?EN=YJ5uoel_;mKGVgQVMoKP%J$|?2V&sC;jZg)j|!5 zlu~mLt8!PwuKz&+=}fL0FDcb`<1T;aHz97k;(v9mW$#+`?_TTNxNq$uOO@@nH|}+C zX9czUBHfm=r#bGt{C^SmwkHXtq|K>Ve>ZpTZY)Y#Y8Hd9DLnCurrent language not translated (or native English). If you're interested in translating LMMS in another language or want to improve existing translations, you're welcome to help us! Simply contact the maintainer! - Deutsche Übersetzung von Tobias Doerffel. + Deutsche Übersetzung von Tobias Doerffel und Daniel Winzen. License @@ -43,11 +43,65 @@ If you're interested in translating LMMS in another language or want to imp Copyright (c) 2004-2014, LMMS developers - Copyright (c) 2004-2012, LMMS-Entwickler {2004-2014,?} + Copyright (c) 2004-2014, LMMS-Entwickler <html><head/><body><p><a href="http://lmms.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">http://lmms.sourceforge.net</span></a></p></body></html> - + <html><head/><body><p><a href="http://lmms.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">http://lmms.sourceforge.net</span></a></p></body></html> + + + + AmplifierControlDialog + + VOL + VOL + + + Volume: + Lautstärke: + + + PAN + PAN + + + Panning: + Balance: + + + LEFT + LINKS + + + Left gain: + Linke Verstärkung: + + + RIGHT + RECHTS + + + Right gain: + Rechte Verstärkung: + + + + AmplifierControls + + Volume + Lautstärke + + + Panning + Balance + + + Left gain + Linke Verstärkung + + + Right gain + Rechte Verstärkung @@ -79,14 +133,6 @@ If you're interested in translating LMMS in another language or want to imp If you enable this button, the whole sample is reversed. This is useful for cool effects, e.g. a reversed crash. Wenn Sie diesen Button aktivieren, wird das gesamte Sample umgekehrt. Das kann nützlich für coole Effekte sein, wie z.B. eine umgekehrte Crash. - - Loop sample at start- and end-point - Sample an Start- und Endpunkt wiederholen - - - Here you can set, whether looping-mode is enabled. If enabled, AudioFileProcessor loops between start and end-points of a sample until the whole note is played. This is useful for things like string and choir samples. - Hier können Sie festlegen, ob der Looping-Modus aktiviert sein soll. Wenn aktiviert, wiederholt AudioFileProcessor das Sample zwischen Start- und Endpunkt solange, bis die gesamte Note gespielt ist. Das ist vorallem für String- und Chor-Samples nützlich. - Amplify: Verstärkung: @@ -99,32 +145,40 @@ If you're interested in translating LMMS in another language or want to imp Startpoint: Startpunkt: - - With this knob you can set the point where AudioFileProcessor should begin playing your sample. If you enable looping-mode, this is the point to which AudioFileProcessor returns if a note is longer than the sample between the start and end-points. - Mit diesem Knopf können Sie festlegen, wo AudioFileProcessor anfangen soll, Ihr Sample zu spielen. Wenn Sie den Looping-Modus aktivieren, ist das der Punkt, wohin AudioFileProcessor zurückkehrt, wenn eine Note länger als das Sample zwischen Start- und Endpunkt ist. - Endpoint: Endpunkt: - - With this knob you can set the point where AudioFileProcessor should stop playing your sample. If you enable looping-mode, this is the point where AudioFileProcessor returns if a note is longer than the sample between the start and end-points. - Mit diesem Knopf können Sie festlegen, wo AudioFileProcessor aufhören soll, Ihr Sample zu spielen. Wenn Sie den Looping-Modus aktivieren, ist das der Punkt, an dem AudioFileProcessor zum Startpunkt zurückkehrt, wenn eine Note länger als das Sample zwischen Start- und Endpunkt ist. - Continue sample playback across notes - + Samplewiedergabe über Noten fortsetzen Enabling this option makes the sample continue playing across different notes - if you change pitch, or the note length stops before the end of the sample, then the next note played will continue where it left off. To reset the playback to the start of the sample, insert a note at the bottom of the keyboard (< 20 Hz) - + Wenn Sie diese Option aktivieren, wird das Sample über verschiedene Noten weitergespielt. Wenn Sie die Tonhöhe ändern oder die Note endet, bevor das Ende des Samples erreicht ist, dann fängt die nächste Note da an, wo aufgehört wurde. Um die Wiedergabe an den Anfang des Samples zurückzusetzen, fügen Sie eine Note am unteren Ende des Keyboards ein (< 20Hz) + + + Loop sample at start- and end-point + Sample am Start- und Endpunkt wiederholen + + + Here you can set, whether looping-mode is enabled. If enabled, AudioFileProcessor loops between start and end-points of a sample until the whole note is played. This is useful for things like string and choir samples. + Hier können Sie festlegen, ob der Wiederholungsmodus aktiviert ist. Wenn aktiviert, wiederholt AudioFileProcessor das Sample, bis die ganze Note gespielt wurde. Dies ist nützlich für Sachen, wie Streicher oder Chor Samples. + + + With this knob you can set the point where AudioFileProcessor should begin playing your sample. If you enable looping-mode, this is the point to which AudioFileProcessor returns if a note is longer than the sample between the start and end-points. + Mit diesem Knopf können Sie den Punkt festlegen, an dem AudioFileProcessor anfangen soll Ihr Sample abzuspielen. Wenn Sie den Wiederholungsmodus aktivieren, ist dies der Punkt, an dem AudioFileProcessor wieder anfängt zu spielen, wenn eine Note länger ist, als das Sample zwischen den Start- und Endpunkten. + + + With this knob you can set the point where AudioFileProcessor should stop playing your sample. If you enable looping-mode, this is the point where AudioFileProcessor returns if a note is longer than the sample between the start and end-points. + Mit diesem Knopf können Sie den Punkt festlegen, an dem AudioFileProcessor aufhören soll Ihr Sample abzuspielen. Wenn Sie den Wiederholungsmodus aktivieren, ist dies der Punkt, an dem AudioFileProcessor wieder von vorne anfängt zu spielen, wenn eine Note länger ist, als das Sample zwischen den Start- und Endpunkten. AudioFileProcessorWaveView Sample length: - + Samplelänge: @@ -237,11 +291,11 @@ If you're interested in translating LMMS in another language or want to imp Remove song-global automation - + Song-globale Automation entfernen Remove all linked controls - + Alle verknüpften Controller entfernen @@ -264,19 +318,19 @@ If you're interested in translating LMMS in another language or want to imp Draw mode (Shift+D) - Zeichnen-Modus (Umschalt+D) + Zeichnenmodus (Umschalt+D) Erase mode (Shift+E) - Radier-Modus (Umschalt+E) + Radiermodus (Umschalt+E) Click here and draw-mode will be activated. In this mode you can add and move single values. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. - Klicken Sie hier, um den Zeichnen-Modus zu aktivieren. In diesem Modus können Sie einzelne Werte hinzufügen und verschieben. Das ist der Standard-Modus, der meistens benutzt wird. Sie können auch 'Umschalt+D' auf Ihrer Tastatur drücken, um in diesen Modus zu gelangen. + Klicken Sie hier, um den Zeichnenmodus zu aktivieren. In diesem Modus können Sie einzelne Werte hinzufügen und verschieben. Das ist der Standard-Modus, der meistens benutzt wird. Sie können auch 'Umschalt+D' auf Ihrer Tastatur drücken, um in diesen Modus zu gelangen. Click here and erase-mode will be activated. In this mode you can erase single values. You can also press 'Shift+E' on your keyboard to activate this mode. - Klicken Sie hier, um den Radier-Modus zu aktivieren. In diesem Modus können Sie einzelne Werte löschen. Sie können auch 'Umschalt+E' auf Ihrer Tastatur drücken, um diesen Modus zu aktivieren. + Klicken Sie hier, um den Radiermodus zu aktivieren. In diesem Modus können Sie einzelne Werte löschen. Sie können auch 'Umschalt+E' auf Ihrer Tastatur drücken, um diesen Modus zu aktivieren. Cut selected values (Ctrl+X) @@ -324,39 +378,39 @@ If you're interested in translating LMMS in another language or want to imp Discrete progression - + Diskretes Fortschreiten Linear progression - + Lineares Fortschreiten Cubic Hermite progression - + Kubisches, hermetisches Fortschrieten Tension: - + Spannung: Click here to choose discrete progressions for this automation pattern. The value of the connected object will remain constant between control points and be set immediately to the new value when each control point is reached. - + Klicken Sie hier, um diskretes Fortschreiten als Automationsmuster auszuwählen. Der Wert des verbundenen Objekts bleibt konstant zwischen den Kontrollpunkten und wird sofort auf den neuen Wert gesetzt, wenn ein Kontrollpunkt erreicht wird. Click here to choose linear progressions for this automation pattern. The value of the connected object will change at a steady rate over time between control points to reach the correct value at each control point without a sudden change. - + Klicken Sie hier, um lineares Fortschreiten als Automationsmuster auszuwählen. Der Wert des verbundenen Objekts wird über die Zeit kontinuierlich zwischen Kontrollpunkten auf den korrekten Wert am jeweiligen Kontrollpunkt geändert, ohne plötzliche Änderungen. Click here to choose cubic hermite progressions for this automation pattern. The value of the connected object will change in a smooth curve and ease in to the peaks and valleys. - + Klicken Sie hier, um kubisches, hermetisches Fortschreiten als Automationsmuster auszuwählen. Der Wert des verbundenen Objekts wird in einer nahtlosen Kurve geändert und in Spitzen und Täler übergehen. Tension value for spline - + Spannungswert für Spline A higher tension value may make a smoother curve but overshoot some values. A low tension value will cause the slope of the curve to level off at each control point. - + Ein höherer Spannungswert erzeugt möglicherweise eine nahtlosere Kurve, aber überschwingt einige Werte. Ein niedrigerer Spannungswert wird ein Abfallen und dann Abflachen der Kurve an jedem Kontrollpunkt verursachen. @@ -404,6 +458,48 @@ If you're interested in translating LMMS in another language or want to imp Automation-Spur + + BassBoosterControlDialog + + FREQ + FREQ + + + Frequency: + Frequenz: + + + GAIN + GAIN + + + Gain: + Verstärkung: + + + RATIO + RATIO + + + Ratio: + Verhältnis: + + + + BassBoosterControls + + Frequency + Frequenz + + + Gain + Verstärkung + + + Ratio + Verhältnis + + Controller @@ -482,11 +578,11 @@ If you're interested in translating LMMS in another language or want to imp Confirm Delete - + Löschen bestätigen Confirm delete? There are existing connection(s) associted with this controller. There is no way to undo. - + Löschen bestätigen? Es bestehen Verbindungen, die an diesen Controller angeschlossen sind. Es gibt keine Möglichkeit dies rückgängig zu machen. @@ -516,6 +612,132 @@ If you're interested in translating LMMS in another language or want to imp &Hilfe + + DualFilterControlDialog + + Filter 1 enabled + Filter 1 aktiviert + + + Filter 2 enabled + Filter 2 aktiviert + + + Click to enable/disable Filter 1 + Klicken Sie, um Filter 1 zu aktivieren/deaktivieren + + + Click to enable/disable Filter 2 + Klicken Sie, um Filter 2 zu aktivieren/deaktivieren + + + + DualFilterControls + + Filter 1 enabled + Filter 1 aktiviert + + + Filter 1 type + Filtertyp 1 + + + Cutoff 1 frequency + Kennfrequenz 1 + + + Q/Resonance 1 + Q/Resonanz 1 + + + Gain 1 + Verstärkung 1 + + + Mix + Mischung + + + Filter 2 enabled + Filter 2 aktiviert + + + Filter 2 type + Filtertyp 2 + + + Cutoff 2 frequency + Kennfrequenz 2 + + + Q/Resonance 2 + Q/Resonanz 2 + + + Gain 2 + Verstärkung 2 + + + LowPass + Tiefpass + + + HiPass + Hochpass + + + BandPass csg + Bandpass csg + + + BandPass czpg + Bandpass czpg + + + Notch + Notch + + + Allpass + Allpass + + + Moog + Moog + + + 2x LowPass + 2x Tiefpass + + + RC LowPass 12dB + RC-Tiefpass 12dB + + + RC BandPass 12dB + RC-Bandpass 12dB + + + RC HighPass 12dB + RC-Hochpass 12dB + + + RC LowPass 24dB + RC-Tiefpass 24dB + + + RC BandPass 24dB + RC-Bandpass 24dB + + + RC HighPass 24dB + RC-Hochpass 24dB + + + Vocal Formant Filter + Vokalformant-Filter + + Effect @@ -628,7 +850,19 @@ The Gate knob controls the 'given threshold' for the effect's aut The Controls button opens a dialog for editing the effect's parameters. Right clicking will bring up a context menu where you can change the order in which the effects are processed or delete an effect altogether. - + Effektplugins funktionieren als eine Aneinanderreihung von Effekten, wo das Signal von oben nach unter verarbeitet wird. + +Der Ein-/Ausschalter ermöglicht es Ihnen ein Plugin jeder Zeit zu umgehen. + +Der Wet/Dry-Knopf legt das Verhältnis zwischen Eingangssignal und vom Effekt bearbeiteten Signal im Ausgang fest. Der Eingag dieses Effekts ist der Ausgang des vorherigen Effekts. Somit enthält das »dry«-Signal, für Effekte weiter unten in der Kette, alle vorherigen Effekte. + +Der Abfallzeit-Knopf legt fest, wie lange das Signal weiterverarbeitet werden soll, nachdem die Noten losgelassen wurde. Der Effekt hört auf Signale zu verarbeiten, wenn die Lautstärke eines Signals für eine festgelegte Zeit unter einen festgelegten Schwellwert gefallen ist. Dieser Knopf legt die »festgelegte Zeit« fest. Längere Zeiten brauchen mehr Rechenleistung, deshalb sollte diese Zahl für die meisten Effekte niedrig sein. Es muss für Effekte, die über längere Zeit Stille erzeugen, z.B. Verzögerungen, erhöht werden. + +Der Gate-Knopf kontrolliert den »festgelegten Schwellwert« für das automatische Ausschalten des Effekts. Die Uhr für die »festgelegte Zeit« beginnt sobald der Pegel des verarbeiteten Signals unter den mit diesem Knopf festgelegten Pegel fällt. + +Der Regler-Knopf öffnet einen Dialog zum Bearbeiten der Parameter des Effekts. + +Ein Recktsklick öffnet ein Kontextmenü, in dem Sie die Reihenfolge der Effekte ändern oder einen Effekt entfernen können. Move &up @@ -1007,14 +1241,6 @@ Right clicking will bring up a context menu where you can change the order in wh 8x 8x - - Sample-exact controllers - Sample-genaue Controller - - - Alias-free oscillators - Alias-freie Oszillatoren - Start Start @@ -1025,7 +1251,15 @@ Right clicking will bring up a context menu where you can change the order in wh Export as loop (remove end silence) - + Als Schleife exportieren (Stille am Ende entfernen) + + + Sample-exact controllers + Sample-exakte Regler + + + Alias-free oscillators + Unterschiedsfreie Oszillatoren @@ -1055,7 +1289,7 @@ Right clicking will bring up a context menu where you can change the order in wh FX Fader %1 - FX-Schieber %1 + FX Schieber %1 Mute @@ -1070,130 +1304,130 @@ Right clicking will bring up a context menu where you can change the order in wh InstrumentFunctionArpeggio Arpeggio - Arpeggio + Arpeggio Arpeggio type - Arpeggiotyp + Arpeggiotyp Arpeggio range - Arpeggio-Bereich + Arpeggio-Bereich Arpeggio time - Arpeggio-Zeit + Arpeggio-Zeit Arpeggio gate - Arpeggio-Gate + Arpeggio-Gate Arpeggio direction - Arpeggio-Richtung + Arpeggio-Richtung Arpeggio mode - Arpeggio-Modus + Arpeggio-Modus Up - Hoch + Hoch Down - Runter + Runter Up and down - Hoch und runter + Hoch und runter Random - Zufällig + Zufällig Free - Frei + Frei Sort - Sortiert + Sortiert Sync - Synchron + Synchron InstrumentFunctionArpeggioView ARPEGGIO - ARPEGGIO + ARPEGGIO An arpeggio is a method playing (especially plucked) instruments, which makes the music much livelier. The strings of such instruments (e.g. harps) are plucked like chords. The only difference is that this is done in a sequential order, so the notes are not played at the same time. Typical arpeggios are major or minor triads, but there are a lot of other possible chords, you can select. - Ein Arpeggio ist eine Art, (vorallem gezupfte) Instrumente zu spielen, die die Musik viel lebendiger macht. Die Seiten von solchen Instrumenten (z.B. Harfen) werden wie Akkorde gezupft, der einzige Unterschied besteht darin, dass dies nacheinander geschieht. Die Noten werden also nicht zur gleichen Zeit gespielt. Typische Arpeggios sind Dur- oder Moll-Dreiklänge, aber es gibt noch viele andere Akkorde, die Sie auswählen können. + Ein Arpeggio ist eine Art, (vorallem gezupfte) Instrumente zu spielen, die die Musik viel lebendiger macht. Die Seiten von solchen Instrumenten (z.B. Harfen) werden wie Akkorde gezupft, der einzige Unterschied besteht darin, dass dies nacheinander geschieht. Die Noten werden also nicht zur gleichen Zeit gespielt. Typische Arpeggios sind Dur- oder Moll-Dreiklänge, aber es gibt noch viele andere Akkorde, die Sie auswählen können. RANGE - BEREICH + RANGE Arpeggio range: - Arpeggio-Bereich: + Arpeggio-Bereich: octave(s) - Oktave(n) + Oktave(n) Use this knob for setting the arpeggio range in octaves. The selected arpeggio will be played within specified number of octaves. - Benutzen Sie diesen Knopf, um den Arpeggio-Bereich in Oktaven zu setzen. Das gewähle Arpeggio wird innerhalb der angegebenen Anzahl von Oktaven abgespielt. + Benutzen Sie diesen Knopf, um den Arpeggio-Bereich in Oktaven zu setzen. Das gewähle Arpeggio wird innerhalb der angegebenen Anzahl von Oktaven abgespielt. TIME - ZEIT + ZEIT Arpeggio time: - Arpeggio-Zeit: + Arpeggio-Zeit: ms - ms + ms Use this knob for setting the arpeggio time in milliseconds. The arpeggio time specifies how long each arpeggio-tone should be played. - Benutzen Sie diesen Knopf, um die Arpeggio-Zeit in Millisekunden zu setzen. Die Arpeggio-Zeit gibt an, wie lange jeder einzelne Arpeggio-Ton gespielt werden soll. + Benutzen Sie diesen Knopf, um die Arpeggio-Zeit in Millisekunden zu setzen. Die Arpeggio-Zeit gibt an, wie lange jeder einzelne Arpeggio-Ton gespielt werden soll. GATE - GATE + GATE Arpeggio gate: - Arpeggio-Gate: + Arpeggio-Gate: % - % + % Use this knob for setting the arpeggio gate. The arpeggio gate specifies the percent of a whole arpeggio-tone that should be played. With this you can make cool staccato arpeggios. - Benutzen Sie diesen Knopf, um das Arpeggio-Gate zu setzen. Das Arpeggio-Gate gibt an, wie viel Prozent eines ganzen Arpeggio-Tons gespielt werden sollen. Damit können Sie coole Staccato-Arpeggios erzeugen. + Benutzen Sie diesen Knopf, um das Arpeggio-Gate zu setzen. Das Arpeggio-Gate gibt an, wie viel Prozent eines ganzen Arpeggio-Tons gespielt werden sollen. Damit können Sie coole Staccato-Arpeggios erzeugen. Chord: - + Akkord: Direction: - Richtung: + Richtung: Mode: - Modus: + Modus: @@ -1564,6 +1798,14 @@ Right clicking will bring up a context menu where you can change the order in wh Minor + Moll + + + Chromatic + Chromatisch + + + Half-Whole Diminished @@ -1571,7 +1813,7 @@ Right clicking will bring up a context menu where you can change the order in wh InstrumentFunctionNoteStackingView RANGE - BEREICH + RANGE Chord range: @@ -1587,11 +1829,11 @@ Right clicking will bring up a context menu where you can change the order in wh STACKING - + STACKING Chord: - + Akkord: @@ -1626,7 +1868,19 @@ Right clicking will bring up a context menu where you can change the order in wh NOTE - + NOTE + + + CUSTOM BASE VELOCITY + BENUTZERDEFINIERTE GRUNDLAUTSTÄRKE + + + Specify the velocity normalization base for MIDI-based instruments at note volume 100% + Geben Sie die Lautstärken-Normalisationsbasis für MIDI-basierende Instrumente bei einer Notenlautstärke von 100% an + + + BASE VELOCITY + GRUNDLAUTSTÄRKE @@ -1768,11 +2022,15 @@ Right clicking will bring up a context menu where you can change the order in wh FREQ - FREQ + FREQ cutoff frequency: - + Kennfrequenz: + + + Envelopes, LFOs and filters are not supported by the current instrument. + Hüllkurven, LFOs und Filter sind vom aktuellen Instrument nicht unterstützt. @@ -1787,7 +2045,7 @@ Right clicking will bring up a context menu where you can change the order in wh Panning - Panning + Balance Pitch @@ -1811,7 +2069,7 @@ Right clicking will bring up a context menu where you can change the order in wh Pitch range - + Tonhöhenbereich @@ -1830,11 +2088,11 @@ Right clicking will bring up a context menu where you can change the order in wh Panning - Panning + Balance Panning: - Panning: + Balance: PAN @@ -1877,11 +2135,11 @@ Right clicking will bring up a context menu where you can change the order in wh Panning - Panning + Balance Panning: - Panning: + Balance: PAN @@ -1941,11 +2199,11 @@ Right clicking will bring up a context menu where you can change the order in wh Pitch range (semitones) - + Tonhöhenbereich (Halbtöne) RANGE - BEREICH + RANGE @@ -1992,6 +2250,13 @@ Right clicking will bring up a context menu where you can change the order in wh Unbekanntes LADSPA-Plugin %1 angefordert. + + LcdSpinBox + + Please enter a new value between %1 and %2: + Bitte geben Sie einen neuen Wert zwischen %1 und %2 ein: + + LfoController @@ -2043,7 +2308,7 @@ Right clicking will bring up a context menu where you can change the order in wh todo - + Zu erledigen SPD @@ -2116,7 +2381,8 @@ Right clicking will bring up a context menu where you can change the order in wh Click here for a user-defined shape. Double click to pick a file. - + Klicken Sie hier für eine benutzerdefinierte From. +Doppelklicken Sie, um eine Datei auszuwählen. @@ -2359,23 +2625,23 @@ Bitte besuchen Sie http://lmms.sf.net/wiki für Dokumentationen über LMMS. Save as new &version - + Als neue &Version speichern E&xport tracks... - + Spuren E&xportieren… LMMS (*.mmp *.mmpz) - - - - LMMS Project (*.mmp *.mmpz);;LMMS Project Template (*.mpt) - + LMMS (*.mmp *.mmpz) Version %1 - + Version %1 + + + LMMS Project (*.mmpz *.mmp);;LMMS Project Template (*.mpt) + LMMS Projekt (*.mmpz *.mmp);;LMMS Projektvorlage (*.mpt) @@ -2491,7 +2757,11 @@ Bitte besuchen Sie http://lmms.sf.net/wiki für Dokumentationen über LMMS. Fixed output note - + Feste Ausgangnote + + + Base velocity + Grundlautstärke @@ -2592,11 +2862,11 @@ Bitte besuchen Sie http://lmms.sf.net/wiki für Dokumentationen über LMMS. Peak Controller Bug - + Peak Controller Fehler Due to a bug in older version of LMMS, the peak controllers may not be connect properly. Please ensure that peak controllers are connected properly and re-save this file. Sorry for any inconvenience caused. - + Aufgrud eines Fehlers in einer älteren Version von LMMS, sind die Peak Controller möglicherweise nicht richtig verbunden. Bitte stellen Sie sicher, dass die Peak Controller richtig verbunden sind und speichern Sie die Datei erneut. Entschuldigung für jegliche verursachte Unannehmlichkeiten. @@ -2634,23 +2904,23 @@ Bitte besuchen Sie http://lmms.sf.net/wiki für Dokumentationen über LMMS. AMNT - + AMNT MULT - + MULT Amount Multiplicator: - + Stärkenmultiplikator: ATCK - + ATCK DCAY - + DCAY @@ -2677,11 +2947,154 @@ Bitte besuchen Sie http://lmms.sf.net/wiki für Dokumentationen über LMMS. Abs Value - + Absoluter Wert Amount Multiplicator - + Stärkenmultiplikator + + + + PianoRoll + + Cut selected notes (Ctrl+X) + Ausgewählte Noten ausschneiden (Strg+X) + + + Copy selected notes (Ctrl+C) + Ausgewählte Noten kopieren (Strg+C) + + + Paste notes from clipboard (Ctrl+V) + Noten aus Zwischenablage einfügen (Strg+V) + + + Play/pause current pattern (Space) + Aktuellen Pattern abspielen/pausieren (Leertaste) + + + Stop playing of current pattern (Space) + Abspielen des aktuellen Patterns stoppen (Leertaste) + + + Piano-Roll - %1 + Piano-Roll - %1 + + + Piano-Roll - no pattern + Piano-Roll - Kein Pattern + + + Please open a pattern by double-clicking on it! + Bitte öffnen Sie einen Pattern, indem Sie ihn doppelklicken! + + + Record notes from MIDI-device/channel-piano + Noten von MIDI-Gerät/Kanal-Klavier aufnehmen + + + Last note + Letzte Note + + + Draw mode (Shift+D) + Zeichnenmodus (Umschalt+D) + + + Erase mode (Shift+E) + Radiermodus (Umschalt+E) + + + Select mode (Shift+S) + Auswahl-Modus (Umschalt+S) + + + Record notes from MIDI-device/channel-piano while playing song or BB track + Noten vom MIDI-Gerät/Kanal-Klavier aufnehmen während der Song oder BB-Track abgespielt wird + + + Click here to play the current pattern. This is useful while editing it. The pattern is automatically looped when its end is reached. + Klicken Sie hier, um den aktuellen Pattern abzuspielen. Das ist nützlich beim Bearbeiten. Der Pattern wird automatisch wiederholt, wenn sein Ende erreicht ist. + + + Click here to record notes from a MIDI-device or the virtual test-piano of the according channel-window to the current pattern. When recording all notes you play will be written to this pattern and you can play and edit them afterwards. + Klicken Sie hier, um Noten von einem MIDI-Gerät oder dem virtuellen Test-Klavier des zugehörigen Kanal-Fensters in den aktuellen Pattern aufzunehmen. Beim Aufnehmen werden alle Noten, die Sie spielen, in diesen Pattern geschrieben und hinterher können Sie diese abspielen und bearbeiten. + + + Click here to record notes from a MIDI-device or the virtual test-piano of the according channel-window to the current pattern. When recording all notes you play will be written to this pattern and you will hear the song or BB track in the background. + Klicken Sie hier, um Noten von einem MIDI-Gerät oder dem virtuellen Test-Klavier des zugehörigen Kanal-Fensters in den aktuellen Pattern aufzunehmen. Beim Aufnehmen werden alle Noten, die Sie spielen, in diesen Pattern geschrieben und Sie werden den Song oder die BB-Spur im Hintergrund hören. + + + Click here to stop playback of current pattern. + Klicken Sie hier, um die Wiedergabe des aktuellen Patterns zu stoppen. + + + Click here and the selected notes will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. + Klicken Sie hier, um die markierten Noten in die Zwischenablage auszuschneiden. Sie können sie überall in einem beliebigen Pattern wieder einfügen, indem Sie auf den Einfügen-Button klicken. + + + Click here and the selected notes will be copied into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. + Klicken Sie hier, um die markierten Noten in die Zwischenablage zu kopieren. Sie können sie überall in einem beliebigen Pattern wieder einfügen, indem Sie auf den Einfügen-Button klicken. + + + Click here and the notes from the clipboard will be pasted at the first visible measure. + Klicken Sie hier, um die Noten aus der Zwischenablage im ersten sichtbaren Takt einzufügen. + + + Note lock + Notenraster + + + Note Volume + Noten-Lautstärke + + + Note Panning + Noten-Balance + + + Detune mode (Shift+T) + Verstimmungsmodus (Shift+T) + + + Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold Ctrl to temporarily go into select mode. + Klicken Sie hier, um den Zeichnenmodus zu aktivieren. In diesem Modus können Sie Noten hinzufügen, in der Länge ändern und verschieben. Das ist der Standardmodus, der meistens benutzt wird. Sie können auch »Umschalt+D« auf Ihrer Tastatur drücken, um in diesen Modus zu gelangen. Halten Sie in diesem Modus Strg gedrückt, um vorübergehend in den Auswahlmodus zu wechslen. + + + Click here and erase mode will be activated. In this mode you can erase notes. You can also press 'Shift+E' on your keyboard to activate this mode. + Klicken Sie hier, um den Radiermodus zu aktivieren. In diesem Modus können Sie einzelne Noten löschen. Sie können auch »Umschalt+E« auf Ihrer Tastatur drücken, um diesen Modus zu aktivieren. + + + Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold Ctrl in draw mode to temporarily use select mode. + Klicken Sie hier, um den Auswahlmodus zu aktivieren. In diesem Modus können Sie einzelne Noten auswählen. Alternativ können Sie auch Strg im Zeichnenmodus gedrückt halten, um vorrübergehend den Auswahlmodus zu benutzen. + + + Click here and detune mode will be activated. In this mode you can click a note to open its automation detuning. You can utilize this to slide notes from one to another. You can also press 'Shift+T' on your keyboard to activate this mode. + Klicken Sie hier und der Verstimmungmodus wird aktivert. In diesem Modus können Sie auf eine Note klicken, um die Automations-Verstimmung zu öffnen. Sie können diese benutzen, um von einer Note in eine andere zu rutschen. Sie können auch »Umschalt+T« auf Ihrer Tastatur drücken, um diesen Modus zu aktivieren. + + + Mark/unmark current semitone + Aktuellen Halbton markieren/demarkieren + + + Mark current scale + Aktuelle Tonleiter markieren + + + Mark current chord + Aktuellen Akkord markieren + + + Unmark all + Alles Markierungen entfernen + + + No scale + Keine Tonleiter + + + No chord + Kein Akkord @@ -2728,87 +3141,87 @@ Grund: "%2" C Note name - + C Db Note name - + Db C# Note name - + C# D Note name - + D Eb Note name - + Eb D# Note name - + D# E Note name - + E Fb Note name - + Fb Gb Note name - + Gb F# Note name - + F# G Note name - + G Ab Note name - + Ab G# Note name - + G# A Note name - + A Bb Note name - + B A# Note name - + A# B Note name - + H @@ -2857,113 +3270,259 @@ Grund: "%2" File: Datei: + + File: %1 + Datei: %1 + SampleBuffer Open audio file - Audio-Datei öffnen - - - All Audio-Files (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw *.mp3) - Alle Audio-Dateien (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw *.mp3) + Audiodatei öffnen Wave-Files (*.wav) - Wave-Dateien (*.wav) + Wave-Dateien (*.wav) OGG-Files (*.ogg) - OGG-Dateien (*.ogg) + OGG-Dateien (*.ogg) DrumSynth-Files (*.ds) - DrumSynth-Dateien (*.ds) + DrumSynth-Dateien (*.ds) FLAC-Files (*.flac) - FLAC-Dateien (*.flac) + FLAC-Dateien (*.flac) SPEEX-Files (*.spx) - SPEEX-Dateien (*.spx) - - - MP3-Files (*.mp3) - MP3-Dateien (*.mp3) + SPEEX-Dateien (*.spx) VOC-Files (*.voc) - VOC-Dateien (*.voc) + VOC-Dateien (*.voc) AIFF-Files (*.aif *.aiff) - AIFF-Dateien (*.aif *.aiff) + AIFF-Dateien (*.aif *.aiff) AU-Files (*.au) - AU-Dateien (*.au) + AU-Dateien (*.au) RAW-Files (*.raw) - RAW-Dateien (*.raw) + RAW-Dateien (*.raw) + + + All Audio-Files (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw) + Alle Audiodateien (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw) SampleTCOView double-click to select sample - Doppelklick, um Sample zu wählen + Doppelklick, um Sample zu wählen Delete (middle mousebutton) - Löschen (mittlere Maustaste) + Löschen (mittlere Maustaste) Cut - Ausschneiden + Ausschneiden Copy - Kopieren + Kopieren Paste - Einfügen + Einfügen Mute/unmute (<Ctrl> + middle click) - Stumm/Laut schalten (<Strg> + Mittelklick) + Stumm/Laut schalten (<Strg> + Mittelklick) Set/clear record - Aufnahme setzen/löschen + Aufnahme setzen/löschen SampleTrack Sample track - Sample-Spur + Samplespur Volume - Lautstärke + Lautstärke SampleTrackView Track volume - Lautstärke der Spur + Lautstärke der Spur Channel volume: - Kanal Lautstärke: + Kanal Lautstärke: VOL - VOL + VOL + + + + SongEditor + + Click here, if you want to stop playing of your song. The song-position-marker will be set to the start of your song. + Klicken Sie hier, wenn Sie das Abspielen des Songs stoppen wollen. Der Song-Positions-Marker wird automatisch auf den Song-Anfang zurückgesetzt. + + + Could not open file + Konnte Datei nicht öffnen + + + Could not write file + Konnte Datei nicht schreiben + + + Song-Editor + Song-Editor + + + Click here, if you want to play your whole song. Playing will be started at the song-position-marker (green). You can also move it while playing. + Klicken Sie hier, wenn Sie Ihren ganzen Song abspielen wollen. Das Abspielen wird am Song-Positions-Marker (grün) gestartet. Sie können diesen auch während des Abspielens verschieben. + + + Play song (Space) + Song abspielen (Leertaste) + + + Stop song (Space) + Abspielen des Songs stoppen (Leertaste) + + + Add beat/bassline + Beat/Bassline hinzufügen + + + Add sample-track + Sample-Spur hinzufügen + + + Draw mode + Zeichenmodus + + + Edit mode (select and move) + Editier-Modus (auswählen und verschieben) + + + Add automation-track + Automation-Spur hinzufügen + + + Record samples from Audio-device + Samples vom Audiogerät aufnehmen + + + Record samples from Audio-device while playing song or BB track + Samples vom Audiogerät während der Wiedergabe des Songs oder BB-Tracks aufnehmen + + + Could not open file %1. You probably have no permissions to read this file. + Please make sure to have at least read permissions to the file and try again. + Konnte die Datei %1 nicht öffnen. Sie sind wahrscheinlich nicht berechtigt, diese Datei zu lesen. Bitte stellen Sie sicher, dass Sie wenigstens Leserechte auf diese Datei besitzen und versuchen es erneut. + + + Error in file + Fehler in Datei + + + The file %1 seems to contain errors and therefore can't be loaded. + Die Datei %1 scheint fehlerhaft zu sein und kann daher nicht geladen werden. + + + Tempo + Tempo + + + TEMPO/BPM + TEMPO/BPM + + + tempo of song + Geschwindigkeit des Songs + + + The tempo of a song is specified in beats per minute (BPM). If you want to change the tempo of your song, change this value. Every measure has four beats, so the tempo in BPM specifies, how many measures / 4 should be played within a minute (or how many measures should be played within four minutes). + Das Tempo eines Liedes wird in Beats pro Minute (BPM) angegeben. Wenn Sie das Tempo Ihres Songs ändern wollen, ändern Sie diesen Wert. Jeder Takt hat vier Schläge (Beats); das Tempo gibt also an, wie viele Takte / 4 innerhalb einer Minute gespielt werden sollen (bzw. wie viele Takte innerhalb von vier Minuten gespielt werden sollen). + + + High quality mode + High-Quality-Modus + + + Master volume + Master-Lautstärke + + + master volume + Master-Lautstärke + + + Master pitch + Master-Tonhöhe + + + master pitch + Master-Tonhöhe + + + Value: %1% + Wert: %1% + + + Value: %1 semitones + Wert: %1 Halbtöne + + + Could not open %1 for writing. You probably are not permitted to write to this file. Please make sure you have write-access to the file and try again. + Konnte %1 nicht zum Schreiben öffnen. Sie sind wahrscheinlich nicht dazu berechtigt in diese Datei zu schreiben. Bitte stellen Sie sicher, dass Sie Schreibrechte für diese Datei haben und versuchen Sie es erneut. + + + + SpectrumAnalyzerControlDialog + + Linear spectrum + Lineares Spektrum + + + Linear Y axis + Lineare Y-Achse + + + + SpectrumAnalyzerControls + + Linear spectrum + Lineares Spektrum + + + Linear Y axis + Lineare Y-Achse + + + Channel mode + Kanalmodus @@ -3049,50 +3608,50 @@ Grund: "%2" TimeDisplayWidget click to change time units - + Klicken Sie hier, um die Zeiteinheit zu ändern TrackContainer Couldn't import file - Konnte Datei nicht importieren + Datei konnte nicht importiert werden Couldn't find a filter for importing file %1. You should convert this file into a format supported by LMMS using another software. - Es konnte kein Filter gefunden werden, um die Datei %1 zu importieren. + Es konnte kein Filter gefunden werden, um die Datei %1 zu importieren. Sie sollten diese Datei mit Hilfe anderer Software in ein von LMMS unterstützes Format umwandeln. Couldn't open file - Konnte Datei nicht öffnen + Datei konnte nicht geöffnet werden Couldn't open file %1 for reading. Please make sure you have read-permission to the file and the directory containing the file and try again! - Konnte Datei %1 nicht zum Lesen öffnen. -Bitte stellen Sie sicher, dass Sie Lese-Rechte auf diese Datei sowie das Verzeichnis besitzen und probieren es erneut! + Datei %1 konnte nicht zum Lesen geöffnet werden. +Bitte stellen Sie sicher, dass Sie Leserechte auf diese Datei sowie das Verzeichnis besitzen und probieren es erneut! Loading project... - Lade Projekt... + Lade Projekt… Cancel - Abbrechen + Abbrechen Please wait... - Bitte warten... + Bitte warten… Importing MIDI-file... - Importiere MIDI-Datei... + Importiere MIDI-Datei… Importing FLP-file... - Importiere FLP-Datei... + Importiere FLP-Datei… @@ -3242,22 +3801,22 @@ Bitte stellen Sie sicher, dass Sie Lese-Rechte auf diese Datei sowie das Verzeic Ui Contributors ordered by number of commits: - + Mitwirkende sortiert nach der Anzahl an Einreichungen: Involved - + Beteiligt VersionedSaveDialog Increment version number - + Versionsnummer erhöhen Decrement version number - + Versionsnummer vermindern @@ -3344,11 +3903,11 @@ Bitte stellen Sie sicher, dass Sie Lese-Rechte auf diese Datei sowie das Verzeic by - + von - VST plugin control - + - VST Plugin Controller @@ -3395,15 +3954,15 @@ Bitte stellen Sie sicher, dass Sie Lese-Rechte auf diese Datei sowie das Verzeic Show/hide - + Anzeigen/ausblenden Effect by: - + Effekt von: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /> - + &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /> @@ -3412,20 +3971,6 @@ Bitte stellen Sie sicher, dass Sie Lese-Rechte auf diese Datei sowie das Verzeic Loading plugin Lade Plugin - - Please wait while loading VST-plugin... - Bitte warten, während das VST-Plugin geladen wird... - - - Failed loading VST-plugin - Laden des VST-Plugins fehlgeschlagen - - - The VST-plugin %1 could not be loaded for some reason. -If it runs with other VST-software under Linux, please contact an LMMS-developer! - Das VST-Plugin %1 konnte aus irgendeinem Grund nicht geladen werden. -Wenn es mit anderer VST-Software unter Linux funktioniert, kontaktieren Sie bitte einen LMMS-Entwickler! - Open Preset Preset öffnen @@ -3436,15 +3981,15 @@ Wenn es mit anderer VST-Software unter Linux funktioniert, kontaktieren Sie bitt : default - + : Standard " - + " ' - + ' Save Preset @@ -3466,6 +4011,18 @@ Wenn es mit anderer VST-Software unter Linux funktioniert, kontaktieren Sie bitt .fxb .fxb + + Please wait while loading VST plugin... + Bitte warten, während das VST-Plugin geladen wird… + + + Failed loading VST plugin + Laden des VST-Plugins fehlgeschlagen + + + The VST plugin %1 could not be loaded for some reason. + Das VST-Plugin %1 konnte aus irgend einem Grund nicht geladen werden. + ZynAddSubFxInstrument @@ -3487,7 +4044,7 @@ Wenn es mit anderer VST-Software unter Linux funktioniert, kontaktieren Sie bitt FM Gain - + FM-Verstärkung Resonance Center Frequency @@ -3546,11 +4103,11 @@ Wenn es mit anderer VST-Software unter Linux funktioniert, kontaktieren Sie bitt FM Gain: - + FM-Verstärkung: FM GAIN - + FM GAIN Resonance center frequency: @@ -3558,7 +4115,7 @@ Wenn es mit anderer VST-Software unter Linux funktioniert, kontaktieren Sie bitt RES CF - + RES CF Resonance bandwidth: @@ -3566,7 +4123,7 @@ Wenn es mit anderer VST-Software unter Linux funktioniert, kontaktieren Sie bitt RES BW - + RES BW Forward MIDI Control Changes @@ -3591,56 +4148,14 @@ Wenn es mit anderer VST-Software unter Linux funktioniert, kontaktieren Sie bitt Reverse sample Sample umkehren + + Stutter + Stottern + Loop Wiederholen - - Stutter - - - - - bassBoosterControlDialog - - FREQ - FREQ - - - Frequency: - Frequenz: - - - GAIN - GAIN - - - Gain: - Gain: - - - RATIO - RATE - - - Ratio: - Rate: - - - - bassBoosterControls - - Frequency - Frequenz - - - Gain - Gain - - - Ratio - Rate - bbEditor @@ -3674,11 +4189,11 @@ Wenn es mit anderer VST-Software unter Linux funktioniert, kontaktieren Sie bitt Remove steps - Steps entfernen + Schritte entfernen Add steps - Steps hinzufügen + Schritte hinzufügen @@ -3793,6 +4308,120 @@ Wenn es mit anderer VST-Software unter Linux funktioniert, kontaktieren Sie bitt Klick für eine benutzerdefinierte Wellenform. + + dynProcControlDialog + + INPUT + INPUT + + + Input gain: + Eingangsverstärkung: + + + OUTPUT + OUTPUT + + + Output gain: + Ausgabeverstärkung: + + + ATTACK + ATTACK + + + Peak attack time: + Spitzen Anschwellzeit: + + + RELEASE + RELEASE + + + Peak release time: + Spitzen Ausklingzeit: + + + Reset waveform + Wellenform zurücksetzen + + + Click here to reset the wavegraph back to default + Klicken Sie hier, um den Wellengraph zum Standard zurückzusetzen + + + Smooth waveform + Wellenform glätten + + + Click here to apply smoothing to wavegraph + Klicken Sie hier, um den Wellengraph zu glätten + + + Increase wavegraph amplitude by 1dB + Die Amplitude des Wellengraphs um 1dB erhöhen + + + Click here to increase wavegraph amplitude by 1dB + Klicken Sie hier, um die Amplitude des Wellengraphs um 1dB zu erhöhen + + + Decrease wavegraph amplitude by 1dB + Die Amplitude des Wellengraphs um 1dB vermindern + + + Click here to decrease wavegraph amplitude by 1dB + Klicken Sie hier, um die Amplitude des Wellengraphs um 1dB zu vermindern + + + Stereomode Maximum + Stereomodus Maximum + + + Process based on the maximum of both stereo channels + Basierend auf dem Maximum beider Stereokanäle verarbeiten + + + Stereomode Average + Stereomodus Durchschnitt + + + Process based on the average of both stereo channels + Basierend auf dem Durchschnitt beider Stereokanäle verarbeiten + + + Stereomode Unlinked + Stereomodus Unverknüpft + + + Process each stereo channel independently + Jeden Stereokanal unabhängig verarbeiten + + + + dynProcControls + + Input gain + Eingangsverstärkung + + + Output gain + Ausgabeverstärkung + + + Attack time + Anschwellzeit + + + Release time + Ausklingzeit + + + Stereo mode + Stereomodus + + exportProjectDialog @@ -3826,7 +4455,7 @@ Bitte stellen Sie sicher, dass Sie Schreibrechte auf diese Datei und das Verzeic fader Please enter a new value between %1 and %2: - Bitte geben Sie einen neuen Wert zwischen %1 und %2 ein: + Bitte geben Sie einen neuen Wert zwischen %1 und %2 ein: @@ -3856,7 +4485,7 @@ Bitte stellen Sie sicher, dass Sie Schreibrechte auf diese Datei und das Verzeic Please wait, loading sample for preview... - Bitte warten, lade Sample für Vorschau... + Bitte warten, lade Sample für Vorschau… --- Factory files --- @@ -3880,6 +4509,10 @@ Bitte stellen Sie sicher, dass Sie Schreibrechte auf diese Datei und das Verzeic End frequency Endfrequenz + + Gain + Gain + Decay Abfallzeit @@ -3888,10 +4521,6 @@ Bitte stellen Sie sicher, dass Sie Schreibrechte auf diese Datei und das Verzeic Distortion Verzerrung - - Gain - Gain - kickerInstrumentView @@ -3903,18 +4532,18 @@ Bitte stellen Sie sicher, dass Sie Schreibrechte auf diese Datei und das Verzeic End frequency: Endfrequenz: + + Gain: + Gain: + Decay: - Abfallzeit (decay): + Abfallzeit: Distortion: Verzerrung: - - Gain: - Gain: - knob @@ -3967,7 +4596,19 @@ Analysis Tools are plugins for which only input channels were identified. Don't Knows are plugins for which no input or output channels were identified. Double clicking any of the plugins will bring up information on the ports. - + Dieser Dialog zeigt Informationen zu allen LADSPA Plugins an, dieLMMS gefunden hat. Die Plugins werden in fünf Kategorien eingeteilt, basierend auf der Interpretation der Porttypen und Namen. + +Verfügbare Effekte sind die, die von LMMS benutzt werden können. Um in LMMS einen Effekt benutzen zu können, muss er vor allem ein Effekt sein, was bedeutet, dass er beides, Eingabe- und Ausgabekanäle, haben muss. LMMS identifiziert Eingabekanäle als einen Audioport, der »in« im Namen enthält. Ausgabekanäle werden durch die Buchstaben »out« identifizert. Des weiteren muss der Effekt die gleiche Anzahl an Ein- und Ausgängen besitzen und muss echtzeitfähig sein. + +Nicht verfügbare Effekte sind die, die als Effekt identifiziert wurden, aber entweder nicht die gleiche Anzahl an Ein- und Ausgabekanälen besizen oder nicht echtzeitfähig sind. + +Instrumente sind Plugins, für die nur Ausgabekanäle identifiziert wurden. + +Analysewerkzeuge sind Plugins, für die nur Eingabekanäle identifiziert wurden. + +Weiß nicht sind Plugins, für die kein Ein- oder Ausgabekanal identifiziert wurde. + +Doppelklicken auf eines der Plugins zeigt Informaitonen über die Ports an. Type: @@ -4080,7 +4721,7 @@ Double clicking any of the plugins will bring up information on the ports. Dead - + Stumpf Slide Decay @@ -4230,7 +4871,7 @@ Double clicking any of the plugins will bring up information on the ports. Dead - + Stumpf 24dB/oct Filter @@ -4570,23 +5211,23 @@ Double clicking any of the plugins will bring up information on the ports. - VST parameter control - + - VST Parameter Controller Automated - + Automatisiert Click here if you want to display automated parameters only. - + Klicken Sie hier, wenn Sie nur automatisierte Parameter anzeigen möchten. Close - + Schließen Close VST effect knob-controller window. - + VST Effekt Knopf-Controllerfenster schließen. @@ -4601,23 +5242,23 @@ Double clicking any of the plugins will bring up information on the ports. - VST plugin control - + - VST Plugin Controller Automated - + Automatisiert Click here if you want to display automated parameters only. - + Klicken Sie hier, wenn Sie nur automatisierte Parameter anzeigen möchten. Close - + Schließen Close VST plugin knob-controller window. - + VST Effekt Knopf-Controllerfenster schließen. @@ -4631,39 +5272,39 @@ Double clicking any of the plugins will bring up information on the ports.opl2instrument Patch - Patch + Patch Op 1 Attack - + Op 1 Anschwellzeit Op 1 Decay - + Op 1-Abfallzeit Op 1 Sustain - + Op 1 Dauerpegel Op 1 Release - + Op 1 Ausklingzeit Op 1 Level - + Op 1 Strärke Op 1 Level Scaling - + Op 1 Stärkenskalierung Op 1 Frequency Multiple - + Op 1 Frequenzmultiplikator Op 1 Feedback - + Op 1 Rückkopplung Op 1 Key Scaling Rate @@ -4675,43 +5316,43 @@ Double clicking any of the plugins will bring up information on the ports. Op 1 Tremolo - + Op 1 Tremolo Op 1 Vibrato - + Op 1 Vibrato Op 1 Waveform - + Op 1 Wellenform Op 2 Attack - + Op 2 Anschwellzeit Op 2 Decay - + Op 2-Abfallzeit Op 2 Sustain - + Op 2 Dauerpegel Op 2 Release - + Op 2 Ausklingzeit Op 2 Level - + Op 2 Strärke Op 2 Level Scaling - + Op 2 Stärkenskalierung Op 2 Frequency Multiple - + Op 2 Frequenzmultiplikator Op 2 Key Scaling Rate @@ -4723,27 +5364,27 @@ Double clicking any of the plugins will bring up information on the ports. Op 2 Tremolo - + Op 2 Tremolo Op 2 Vibrato - + Op 2 Vibrato Op 2 Waveform - + Op 2 Wellenform FM - + FM Vibrato Depth - + Vibrato-Tiefe Tremolo Depth - + Tremolo-Tiefe @@ -4775,10 +5416,6 @@ Double clicking any of the plugins will bring up information on the ports.Osc %1 panning: Oszillator %1 Balance: - - Osc %1 fine detuning left: - Oszillator %1 Fein-Verstimmung links: - cents Cent @@ -4791,16 +5428,20 @@ Double clicking any of the plugins will bring up information on the ports.Volume: Lautstärke: + + Osc %1 fine detuning left: + Oszillator %1 Fein-Verstimmung links: + papuInstrument Sweep time - + Streichzeit Sweep direction - + Streichrichtung Sweep RtShift amount @@ -4812,67 +5453,67 @@ Double clicking any of the plugins will bring up information on the ports. Channel 1 volume - + Kanal 1 Lautstärke Volume sweep direction - + Lautstärken-Streichrichtung Length of each step in sweep - + Länge jedes Schritts beim Streichen Channel 2 volume - + Kanal 2 Lautstärke Channel 3 volume - + Kanal 3 Lautstärke Channel 4 volume - + Kanal 4 Lautstärke Right Output level - + Rechter Ausgabelevel Left Output level - + Linker Ausgabelevel Channel 1 to SO2 (Left) - + Kanal 1 zu SO2 (Links) Channel 2 to SO2 (Left) - + Kanal 2 zu SO2 (Links) Channel 3 to SO2 (Left) - + Kanal 3 zu SO2 (Links) Channel 4 to SO2 (Left) - + Kanal 4 zu SO2 (Links) Channel 1 to SO1 (Right) - + Kanal 1 zu SO1 (Rechts) Channel 2 to SO1 (Right) - + Kanal 2 zu SO1 (Rechts) Channel 3 to SO1 (Right) - + Kanal 3 zu SO1 (Rechts) Channel 4 to SO1 (Right) - + Kanal 4 zu SO1 (Rechts) Treble @@ -4880,22 +5521,22 @@ Double clicking any of the plugins will bring up information on the ports. Bass - + Bass Shift Register width - + Schieberegister-Breite papuInstrumentView Sweep Time: - + Streichzeit: Sweep Time - + Streichzeit Sweep RtShift amount: @@ -4915,15 +5556,15 @@ Double clicking any of the plugins will bring up information on the ports. Square Channel 1 Volume: - + Quadratkanal 1 Lautstärke: Length of each step in sweep: - + Länge jedes Schritts beim Streichen: Length of each step in sweep - + Länge jedes Schritts beim Streichen Wave pattern duty @@ -4931,43 +5572,43 @@ Double clicking any of the plugins will bring up information on the ports. Square Channel 2 Volume: - + Quadratkanal 2 Lautstärke: Square Channel 2 Volume - + Quadratkanal 2 Lautstärke Wave Channel Volume: - + Wellenkanal Lautstärke: Wave Channel Volume - + Wellenkanal Lautstärke Noise Channel Volume: - + Rauschkanal Lautstärke: Noise Channel Volume - + Rauschkanal Lautstärke SO1 Volume (Right): - + SO1 Lautstärke (Rechts): SO1 Volume (Right) - + SO1 Lautstärke (Rechts) SO2 Volume (Left): - + SO2 Lautstärke (Links): SO2 Volume (Left) - + SO2 Lautstärke (Links) Treble: @@ -4979,67 +5620,67 @@ Double clicking any of the plugins will bring up information on the ports. Bass: - + Bass: Bass - + Bass Sweep Direction - + Streichrichtung Volume Sweep Direction - + Lautstärken-Streichrichtung Shift Register Width - + Schieberegister-Breite Channel1 to SO1 (Right) - + Kanal1 zu SO1 (Rechts) Channel2 to SO1 (Right) - + Kanal2 zu SO1 (Rechts) Channel3 to SO1 (Right) - + Kanal3 zu SO1 (Rechts) Channel4 to SO1 (Right) - + Kanal4 zu SO1 (Rechts) Channel1 to SO2 (Left) - + Kanal1 zu SO2 (Links) Channel2 to SO2 (Left) - + Kanal2 zu SO2 (Links) Channel3 to SO2 (Left) - + Kanal3 zu SO2 (Links) Channel4 to SO2 (Left) - + Kanal4 zu SO2 (Links) Wave Pattern - + Wellenmuster The amount of increase or decrease in frequency - + Die Menge an Erhöhung oder Verminderung in der Frequenz The rate at which increase or decrease in frequency occurs - + Die Rate, mit der Erhöhung oder Verminderung in der Frequenz geschieht The duty cycle is the ratio of the duration (time) that a signal is ON versus the total period of the signal. @@ -5047,37 +5688,15 @@ Double clicking any of the plugins will bring up information on the ports. Square Channel 1 Volume - + Quadratkanal 1 Lautstärke The delay between step change - + Die Verzögerung zwischen Schrittänderung Draw the wave here - - - - - pattern - - Cannot freeze pattern - Kann Pattern nicht einfrieren - - - The pattern currently cannot be freezed because you're in play-mode. Please stop and try again! - Der Pattern kann derzeit nicht eingefroren werden, da Sie sich im Abspiel-Modus befinden. Bitte stoppen Sie und versuchen es erneut! - - - - patternFreezeStatusDialog - - Freezing pattern... - Friere Pattern ein... - - - Cancel - Abbrechen + Die Welle hier zeichnen @@ -5086,7 +5705,7 @@ Double clicking any of the plugins will bring up information on the ports.double-click to open this pattern in piano-roll use mouse wheel to set volume of a step Doppelklick, um diesen Pattern im Piano-Roll zu öffnen -Lautstärke eines Steps kann mit Mausrad geändert werden +Lautstärke eines Schritts kann mit Mausrad geändert werden Open in piano-roll @@ -5104,168 +5723,13 @@ Lautstärke eines Steps kann mit Mausrad geändert werden Change name Name ändern - - Refreeze - Erneut einfrieren - - - Freeze - Einfrieren - - - Unfreeze - Ausfrieren - Add steps - Steps hinzufügen + Schritte hinzufügen Remove steps - Steps entfernen - - - - PianoRoll - - Cut selected notes (Ctrl+X) - Ausgewählte Noten ausschneiden (Strg+X) - - - Copy selected notes (Ctrl+C) - Ausgewählte Noten kopieren (Strg+C) - - - Paste notes from clipboard (Ctrl+V) - Noten aus Zwischenablage einfügen (Strg+V) - - - Play/pause current pattern (Space) - Aktuellen Pattern abspielen/pausieren (Leertaste) - - - Stop playing of current pattern (Space) - Abspielen des aktuellen Patterns stoppen (Leertaste) - - - Piano-Roll - %1 - Piano-Roll - %1 - - - Piano-Roll - no pattern - Piano-Roll - Kein Pattern - - - Please open a pattern by double-clicking on it! - Bitte öffnen Sie einen Pattern, indem Sie ihn doppelklicken! - - - Record notes from MIDI-device/channel-piano - Noten von MIDI-Gerät/Kanal-Klavier aufnehmen - - - Last note - Letzte Note - - - Draw mode (Shift+D) - Zeichnen-Modus (Umschalt+D) - - - Erase mode (Shift+E) - Radier-Modus (Umschalt+E) - - - Select mode (Shift+S) - Auswahl-Modus (Umschalt+S) - - - Record notes from MIDI-device/channel-piano while playing song or BB track - Noten vom MIDI-Gerät/Kanal-Klavier aufnehmen während der Song oder BB-Track abgespielt wird - - - Click here to play the current pattern. This is useful while editing it. The pattern is automatically looped when its end is reached. - Klicken Sie hier, um den aktuellen Pattern abzuspielen. Das ist nützlich beim Bearbeiten. Der Pattern wird automatisch wiederholt, wenn sein Ende erreicht ist. - - - Click here to record notes from a MIDI-device or the virtual test-piano of the according channel-window to the current pattern. When recording all notes you play will be written to this pattern and you can play and edit them afterwards. - Klicken Sie hier, um Noten von einem MIDI-Gerät oder dem virtuellen Test-Klavier des zugehörigen Kanal-Fensters in den aktuellen Pattern aufzunehmen. Beim Aufnehmen werden alle Noten, die Sie spielen, in diesen Pattern geschrieben und hinterher können Sie diese abspielen und bearbeiten. - - - Click here to record notes from a MIDI-device or the virtual test-piano of the according channel-window to the current pattern. When recording all notes you play will be written to this pattern and you will hear the song or BB track in the background. - - - - Click here to stop playback of current pattern. - Klicken Sie hier, um die Wiedergabe des aktuellen Patterns zu stoppen. - - - Click here and the selected notes will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. - Klicken Sie hier, um die markierten Noten in die Zwischenablage auszuschneiden. Sie können sie überall in einem beliebigen Pattern wieder einfügen, indem Sie auf den Einfügen-Button klicken. - - - Click here and the selected notes will be copied into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. - Klicken Sie hier, um die markierten Noten in die Zwischenablage zu kopieren. Sie können sie überall in einem beliebigen Pattern wieder einfügen, indem Sie auf den Einfügen-Button klicken. - - - Click here and the notes from the clipboard will be pasted at the first visible measure. - Klicken Sie hier, um die Noten aus der Zwischenablage im ersten sichtbaren Takt einzufügen. - - - Note lock - - - - Note Volume - Noten-lautstärke - - - Note Panning - - - - Detune mode (Shift+T) - Verstimmungsmodus (Shift+T) - - - Click here and draw mode will be activated. In this mode you can add, resize and move notes. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. In this mode, hold Ctrl to temporarily go into select mode. - - - - Click here and erase mode will be activated. In this mode you can erase notes. You can also press 'Shift+E' on your keyboard to activate this mode. - - - - Click here and select mode will be activated. In this mode you can select notes. Alternatively, you can hold Ctrl in draw mode to temporarily use select mode. - - - - Click here and detune mode will be activated. In this mode you can click a note to open its automation detuning. You can utilize this to slide notes from one to another. You can also press 'Shift+T' on your keyboard to activate this mode. - - - - Mark/unmark current semitone - Aktuellen Halbton markieren/demarkieren - - - Mark current scale - Aktuelle Tonleite markieren - - - Mark current chord - Aktuellen Akkord markieren - - - Unmark all - Alles Markierungen entfernen - - - No scale - Keine Tonleiter - - - No chord - Kein Akkord + Schritte entfernen @@ -5274,10 +5738,6 @@ Lautstärke eines Steps kann mit Mausrad geändert werden Instrument plugins Instrument-Plugins - - three powerful oscillators you can modulate in several ways - Drei leistungsfähige Oszillatoren, die Sie auf verschiedene Art und Weise modulieren können - VST-host for using VST(i)-plugins within LMMS VST-Host zum Benutzen von VST(i)-Plugins innerhalb von LMMS @@ -5298,10 +5758,6 @@ Lautstärke eines Steps kann mit Mausrad geändert werden Filter for importing MIDI-files into LMMS Filter, um MIDI-Dateien in LMMS zu importieren - - simple sampler with various settings for using samples (e.g. drums) in an instrument-track - Einfacher Sampler mit verschiedenen Einstellungen zur Nutzung von Samples (z.B. Drums) in einer Instrument-Spur - Filter for importing FL Studio projects into LMMS Filter für Import von FL Studio Projekten in LMMS @@ -5314,18 +5770,10 @@ Lautstärke eines Steps kann mit Mausrad geändert werden plugin for using arbitrary LADSPA-effects inside LMMS. Plugin, um beliebige LADSPA-Effekte in LMMS nutzen zu können. - - plugin for using arbitrary VST-effects inside LMMS. - Plugin um beliebige VST-Effekte in LMMS nutzen zu können. - Incomplete monophonic imitation tb303 Unvollständiger monophonischer TB303-Klon - - versatile kick- & bassdrum-synthesizer - Vielfältiger Kick- & Bassdrum-Synthesizer - GUS-compatible patch instrument GUS-kompatibles Patch-Instrument @@ -5338,10 +5786,6 @@ Lautstärke eines Steps kann mit Mausrad geändert werden List installed LADSPA plugins Installierte LADSPA-Plugins auflisten - - plugin for boosting bass - Plugin zur Bass-Verstärkung - Plugin for freely manipulating stereo output Plugin zur freien Manipulation der Stereoausgabe @@ -5382,15 +5826,51 @@ Dieser Chip wurde in Commodore 64 Computern genutzt. 2-operator FM Synth - + 2-Operator FM-Synth Filter for importing Hydrogen files into LMMS - + Filter zum importieren von Hydrogendateien in LMMS LMMS port of sfxr - + LMMS-Portierung von sfxr + + + plugin for processing dynamics in a flexible way + Ein Plugin, um Dynamik auf Flexible Weise zu verarbeiten + + + A native amplifier plugin + Ein natives Verstärker-Plugin + + + Graphical spectrum analyzer plugin + Graphisches Spektrumanalyzer Plugin + + + Boost your bass the fast and simple way + Verstärken Sie Ihren Bass auf schnellen und einfachen Wege + + + plugin for waveshaping + Plugin für Wellenformen + + + plugin for using arbitrary VST effects inside LMMS. + Plugin um beliebige VST-Effekte in LMMS zu benutzen. + + + Simple sampler with various settings for using samples (e.g. drums) in an instrument-track + Einfacher Sampler mit verschiedenen Einstellungen zum Benutzen von Samples (z.B. Trommeln) in einer Instrumentenspur + + + Three powerful oscillators you can modulate in several ways + Drei mächtige Oszillatoren, die Sie auf mehrere Arten modulieren können + + + Versatile kick- & bassdrum-synthesizer + Vielseitiger Kick- & Bassdrum-Synthesizer @@ -5701,23 +6181,23 @@ Latenz: %2 ms Sync VST plugins to host playback - + VST Plugins mit der Host-Wiedergabe synchronisieren Enable note labels in piano roll - + Notenbeschriftung in Piano-Roll aktivieren Enable waveform display by default - + Wellenform standardmäßig anzeigen Enable auto save feature - + Automatisches Speichern aktivieren Show playback cursor in AudioFileProcessor - + Wiedergabe-Courser im AudioFileProcessor anzeigen @@ -5760,7 +6240,7 @@ Latenz: %2 ms Chorus Lines - + Chorus/Anzahl Chorus Level @@ -5831,7 +6311,7 @@ Latenz: %2 ms Chorus Lines: - + Chorus/Anzahl: Chorus Level: @@ -5854,7 +6334,7 @@ Latenz: %2 ms sfxrInstrument Wave Form - + Wellenform @@ -5976,19 +6456,19 @@ Latenz: %2 ms Attack rate determines how rapidly the output of Voice %1 rises from zero to peak amplitude. - + Anschwellzeit gibt an, wie schnell die Ausgabe von Stimme %1 von Null zur Spitzenamplitude anschwellt. Decay rate determines how rapidly the output falls from the peak amplitude to the selected Sustain level. - + Abfallzeit gibt an, wie schnell die Ausgabe von der Spitzenamplitude bis zum ausgewählten Dauerpegel fällt. Output of Voice %1 will remain at the selected Sustain amplitude as long as the note is held. - + Die Ausgabe von Stimme %1 wird solange bei dem ausgewählten Dauerpegel verbleiben, wie die Note gehalten wird. The output of of Voice %1 will fall from Sustain amplitude to zero amplitude at the selected Release rate. - + Die Ausgabe von Stimme %1 wird vom Dauerpegel mit der ausgewählten Ausklingzeit auf Null abfallen. The Pulse Width resolution allows the width to be smoothly swept with no discernable stepping. The Pulse waveform on Oscillator %1 must be selected to have any audible effect. @@ -5996,27 +6476,27 @@ Latenz: %2 ms The Coarse detuning allows to detune Voice %1 one octave up or down. - + Die Grob-Verstimmung ermöglicht es die Stimme %1 um eine Oktave nach oben oder unten zu verstimmen. Sync synchronizes the fundamental frequency of Oscillator %1 with the fundamental frequency of Oscillator %2 producing "Hard Sync" effects. - + Sync synchronisiert die Grundfrequenz von Oszillator %1 mit der Grundfrequenz von Oszillator %2, was einen "Hard Sync" Effekt hervorruft. Ring-mod replaces the Triangle Waveform output of Oscillator %1 with a "Ring Modulated" combination of Oscillators %1 and %2. - + Ringmodus ersetzt die Dreiecks-Wellenfrom-Ausgabe von Oszillator %1 mit einer ringmodulierten Kombination der Oszillatoren %1 und %2. When Filtered is on, Voice %1 will be processed through the Filter. When Filtered is off, Voice %1 appears directly at the output, and the Filter has no effect on it. - + Wenn gefilter an ist, wird Stimme %1 durch den Filter verarbeitet. Wenn gefiltert aus ist, wird Stimme %1 direckt an die Ausgabe weitergeleitet und der Filter hat keine Auswirkung darauf. Test - + Test Test, when set, resets and locks Oscillator %1 at zero until Test is turned off. - + Test, wenn aktiviert, wird Oszillator %1 zurückgesetzt und auf Null gesperrt, bis Test ausgeschaltet wird. @@ -6083,157 +6563,11 @@ Latenz: %2 ms Hydrogen projects - + Hydrogen-Projekte Select directory for writing exported tracks... - - - - - SongEditor - - Click here, if you want to stop playing of your song. The song-position-marker will be set to the start of your song. - Klicken Sie hier, wenn Sie das Abspielen des Songs stoppen wollen. Der Song-Positions-Marker wird automatisch auf den Song-Anfang zurückgesetzt. - - - Could not open file - Konnte Datei nicht öffnen - - - Could not write file - Konnte Datei nicht schreiben - - - Song-Editor - Song-Editor - - - Click here, if you want to play your whole song. Playing will be started at the song-position-marker (green). You can also move it while playing. - Klicken Sie hier, wenn Sie Ihren ganzen Song abspielen wollen. Das Abspielen wird am Song-Positions-Marker (grün) gestartet. Sie können diesen auch während des Abspielens verschieben. - - - Play song (Space) - Song abspielen (Leertaste) - - - Stop song (Space) - Abspielen des Songs stoppen (Leertaste) - - - Add beat/bassline - Beat/Bassline hinzufügen - - - Add sample-track - Sample-Spur hinzufügen - - - Draw mode - Zeichen-Modus - - - Edit mode (select and move) - Editier-Modus (auswählen und verschieben) - - - Add automation-track - Automation-Spur hinzufügen - - - Record samples from Audio-device - Samples vom Audiogerät aufnehmen - - - Record samples from Audio-device while playing song or BB track - Samples vom Audiogerät während der Wiedergabe des Songs oder BB-Tracks aufnehmen - - - Could not open file %1. You probably have no permissions to read this file. - Please make sure to have at least read permissions to the file and try again. - Konnte die Datei %1 nicht öffnen. Sie sind wahrscheinlich nicht berechtigt, diese Datei zu lesen. Bitte stellen Sie sicher, dass Sie wenigstens Leserechte auf diese Datei besitzen und versuchen es erneut. - - - Error in file - Fehler in Datei - - - The file %1 seems to contain errors and therefore can't be loaded. - Die Datei %1 scheint fehlerhaft zu sein und kann daher nicht geladen werden. - - - Tempo - Tempo - - - TEMPO/BPM - TEMPO/BPM - - - tempo of song - Geschwindigkeit des Songs - - - The tempo of a song is specified in beats per minute (BPM). If you want to change the tempo of your song, change this value. Every measure has four beats, so the tempo in BPM specifies, how many measures / 4 should be played within a minute (or how many measures should be played within four minutes). - Das Tempo eines Liedes wird in Beats pro Minute (BPM) angegeben. Wenn Sie das Tempo Ihres Songs ändern wollen, ändern Sie diesen Wert. Jeder Takt hat vier Schläge (Beats); das Tempo gibt also an, wie viele Takte / 4 innerhalb einer Minute gespielt werden sollen (bzw. wie viele Takte innerhalb von vier Minuten gespielt werden sollen). - - - High quality mode - High-Quality-Modus - - - Master volume - Master-Lautstärke - - - master volume - Master-Lautstärke - - - Master pitch - Master-Tonhöhe - - - master pitch - Master-Tonhöhe - - - Value: %1% - Wert: %1% - - - Value: %1 semitones - Wert: %1 Halbtöne - - - Could not open %1 for writing. You probably are not permitted to write to this file. Please make sure you have write-access to the file and try again. - - - - - spectrumAnalyzerControlDialog - - Linear spectrum - Lineares Spektrum - - - Linear Y axis - Lineare Y-Achse - - - - spectrumAnalyzerControls - - Linear spectrum - Lineares Spektrum - - - Linear Y-axis - Lineare Y-Axe - - - Channel mode - Kanalmodus + Wählen Sie einen Ordner zum schreiben der exportierten Spuren aus… @@ -6320,11 +6654,11 @@ Latenz: %2 ms Press <Ctrl> to disable magnetic loop points. - + Drücken Sie <Strg>, um magnetische Loop-Punkte zu deaktivieren. Hold <Shift> to move the begin loop point; Press <Ctrl> to disable magnetic loop points. - + Halten Sie <Umschalt>, um den Anfangs-Loop-Punkt zu verschieben; Drücken Sie <Strg>, um magnetische Loop-Punkte zu deaktivieren. @@ -6441,7 +6775,7 @@ Wenn es mit anderer VST-software unter Linux funktioniert, kontaktieren Sie bitt Please wait while loading VST-plugin... - Bitte warten, während das VST-Plugin geladen wird... + Bitte warten, während das VST-Plugin geladen wird… @@ -6464,7 +6798,7 @@ Wenn es mit anderer VST-software unter Linux funktioniert, kontaktieren Sie bitt Pan %1 - + Balance %1 Detune %1 @@ -6753,7 +7087,77 @@ Die LED rechts unterhalb der Wellenform gibt an, ob die Saite aktiviert ist. Voice %1 test - + Stimme %1 Test + + + + waveShaperControlDialog + + INPUT + INPUT + + + Input gain: + Eingangsverstärkung: + + + OUTPUT + OUTPUT + + + Output gain: + Ausgabeverstärkung: + + + Reset waveform + Wellenform zurücksetzen + + + Click here to reset the wavegraph back to default + Klicken Sie hier, um den Wellengraph zum Standard zurückzusetzen + + + Smooth waveform + Wellenform glätten + + + Click here to apply smoothing to wavegraph + Klicken Sie hier, um den Wellengraph zu glätten + + + Increase graph amplitude by 1dB + Die Amplitude des Wellengraphs um 1dB erhöhen + + + Click here to increase wavegraph amplitude by 1dB + Klicken Sie hier, um die Amplitude des Wellengraphs um 1dB zu erhöhen + + + Decrease graph amplitude by 1dB + Die Amplitude des Wellengraphs um 1dB vermindern + + + Click here to decrease wavegraph amplitude by 1dB + Klicken Sie hier, um die Amplitude des Wellengraphs um 1dB zu vermindern + + + Clip input + Eingang begrenzen + + + Clip input signal to 0dB + Eingangssignal auf 0dB begrenzen + + + + waveShaperControls + + Input gain + Eingangsverstärkung + + + Output gain + Ausgabeverstärkung From 72e194044da05a0b5bbf84f5839d104c2617d650 Mon Sep 17 00:00:00 2001 From: Yann Collette Date: Mon, 9 Jun 2014 09:56:49 +0200 Subject: [PATCH 29/61] update fr translation --- data/locale/fr.ts | 574 +++++++++++++++++++++++----------------------- 1 file changed, 288 insertions(+), 286 deletions(-) diff --git a/data/locale/fr.ts b/data/locale/fr.ts index e6ccb95fd..fc9015c97 100644 --- a/data/locale/fr.ts +++ b/data/locale/fr.ts @@ -43,11 +43,11 @@ If you're interested in translating LMMS in another language or want to imp Copyright (c) 2004-2014, LMMS developers - Copyright (c) 2004-2008, les développeurs de LMMS {2004-2010,?} {2004-2014,?} + Copyright (c) 2004-2014, les développeurs de LMMS <html><head/><body><p><a href="http://lmms.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">http://lmms.sourceforge.net</span></a></p></body></html> - + <html><head/><body><p><a href="http://lmms.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">http://lmms.sourceforge.net</span></a></p></body></html> @@ -113,18 +113,18 @@ If you're interested in translating LMMS in another language or want to imp Continue sample playback across notes - + Continuer de jouer l'échantillon à traver les notes Enabling this option makes the sample continue playing across different notes - if you change pitch, or the note length stops before the end of the sample, then the next note played will continue where it left off. To reset the playback to the start of the sample, insert a note at the bottom of the keyboard (< 20 Hz) - + Activer cette option fait que l'échantillon continue de jouer à traver les différentes notes - si vous changez la hauteur, ou si la longueur de la note s'arrête avant la fin de l'échantillon, alors la note suivante jouée continuera où elle aura été arrêtée. Pour remettre à zéro le jeu au début de l'échantillon, insérez une note en bas du clavier (< 20 Hz) AudioFileProcessorWaveView Sample length: - + Longueur de l'échantillon: @@ -237,171 +237,171 @@ If you're interested in translating LMMS in another language or want to imp Remove song-global automation - + Supprime l'automation globale de la chanson Remove all linked controls - + Supprime tous les contrôles liés AutomationEditor Play/pause current pattern (Space) - Jouer/Mettre en pause le motif (Barre d'espace) + Jouer/Mettre en pause le motif (Barre d'espace) Stop playing of current pattern (Space) - Arrêter de jouer le motif (Barre d'espace) + Arrêter de jouer le motif courant (Barre d'espace) Click here if you want to play the current pattern. This is useful while editing it. The pattern is automatically looped when the end is reached. - Cliquez ici si vous souhaitez jouer le motif. Ceci est utile pendant son édition. Le motif est automatiquement rejoué lorsque sa fin est atteinte. + Cliquez ici si vous souhaitez jouer le motif courant. Ceci est utile pendant son édition. Le motif est automatiquement rejoué lorsque sa fin est atteinte. Click here if you want to stop playing of the current pattern. - Cliquez ici si vous souhaitez arrêter de jouer le motif. + Cliquez ici si vous souhaitez arrêter de jouer le motif courant. Draw mode (Shift+D) - Mode dessin (Shift+D) + Mode dessin (Shift+D) Erase mode (Shift+E) - Mode effacement (Shift+E) + Mode effacement (Shift+E) Click here and draw-mode will be activated. In this mode you can add and move single values. This is the default mode which is used most of the time. You can also press 'Shift+D' on your keyboard to activate this mode. - Cliquez ici et le mode dessin sera activé. Dans ce mode vous pourrez ajouter et déplacer des valeurs particulières. Ceci est le mode par défaut qui est utilisé la plupart du temps. Vous pouvez aussi appuyer sur les touches 'Shift+D' de votre clavier pour activer ce mode. + Cliquez ici et le mode dessin sera activé. Dans ce mode vous pourrez ajouter et déplacer des valeurs particulières. Ceci est le mode par défaut qui est utilisé la plupart du temps. Vous pouvez aussi appuyer sur les touches 'Shift+D' de votre clavier pour activer ce mode. Click here and erase-mode will be activated. In this mode you can erase single values. You can also press 'Shift+E' on your keyboard to activate this mode. - Cliquez ici et le mode effacement sera activé. Dans ce mode vous pourrez effacer des valeurs particulières. Vous pouvez aussi appuyer sur les touches 'Shift+E' de votre clavier pour activer ce mode. + Cliquez ici et le mode effacement sera activé. Dans ce mode vous pourrez effacer des valeurs particulières. Vous pouvez aussi appuyer sur les touches 'Shift+E' de votre clavier pour activer ce mode. Cut selected values (Ctrl+X) - Couper les valeurs sélectionnées (Ctrl+X) + Couper les valeurs sélectionnées (Ctrl+X) Copy selected values (Ctrl+C) - Copier les valeurs sélectionnées (Ctrl+C) + Copier les valeurs sélectionnées (Ctrl+C) Paste values from clipboard (Ctrl+V) - Coller les valeurs sélectionnées (Ctrl+V) + Coller les valeurs sélectionnées (Ctrl+V) Click here and selected values will be cut into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. - Cliquez ici et les valeurs sélectionnées seront coupées et copiées dans le presse-papier. Vous pourrez les coller n'importe où dans n'importe quel motif en cliquant sur le bouton coller. + Cliquez ici et les valeurs sélectionnées seront coupées et copiées dans le presse-papier. Vous pourrez les coller n'importe où dans n'importe quel motif en cliquant sur le bouton coller. Click here and selected values will be copied into the clipboard. You can paste them anywhere in any pattern by clicking on the paste button. - Cliquez ici et les valeurs sélectionnées seront copiées dans le presse-papier. Vous pourrez les coller n'importe où dans n'importe quel motif en cliquant sur le bouton coller. + Cliquez ici et les valeurs sélectionnées seront copiées dans le presse-papier. Vous pourrez les coller n'importe où dans n'importe quel motif en cliquant sur le bouton coller. Click here and the values from the clipboard will be pasted at the first visible measure. - Cliquez ici et les valeurs se trouvant dans le presse-papier seront collées sur la première mesure visible. + Cliquez ici et les valeurs se trouvant dans le presse-papier seront collées sur la première mesure visible. Automation Editor - no pattern - Éditeur d'automation - pas de motif + Éditeur d'automation - pas de motif Automation Editor - %1 - Éditeur d'automation - %1 + Éditeur d'automation - %1 Please open an automation pattern with the context menu of a control! - Veuillez ouvrir un motif d'automation avec le menu contextuel d'un contrôle ! + Veuillez ouvrir un motif d'automation avec le menu contextuel d'un contrôle ! Values copied - Les valeurs ont été copiées + Les valeurs ont été copiées All selected values were copied to the clipboard. - Toutes les valeurs ont été copiées dans le presse-papier. + Toutes les valeurs ont été copiées dans le presse-papier. Discrete progression - + Progression discrète Linear progression - + Progression linéaire Cubic Hermite progression - + Progression cubique de Hermite Tension: - + Tension : Click here to choose discrete progressions for this automation pattern. The value of the connected object will remain constant between control points and be set immediately to the new value when each control point is reached. - + Cliquez ici pour choisir la progression discrète pour ce motif d'automation. La valeur de l'objet connecté restera contante entre les points de contrôle et se verra affecter immédiatement une nouvelle valeur quand un point de contrôle est atteint. Click here to choose linear progressions for this automation pattern. The value of the connected object will change at a steady rate over time between control points to reach the correct value at each control point without a sudden change. - + Cliquez ici pour choisir la progression linéaire pour ce motif d'automation. La valeur de l'objet connecté changera à un taux contant entre les points de contrôle et atteindra la valeur correcte à chaque point de contrôle sans changement soudain. Click here to choose cubic hermite progressions for this automation pattern. The value of the connected object will change in a smooth curve and ease in to the peaks and valleys. - + Cliquez ici pour choisir la progression cubique de Hermite pour ce motif d'automation. La valeur de l'objet connecté changera suivant une courbe lisse. Tension value for spline - + Valeur de tension pour la spline A higher tension value may make a smoother curve but overshoot some values. A low tension value will cause the slope of the curve to level off at each control point. - + Une valeur de tension élevée donne une courbe plus lisse mais introduit des dépassements pour certaines valeurs. Une valeur de tension basse fera que la pente de la courbe se stabilisera à chaque point de contrôle. AutomationPattern Drag a control while pressing <Ctrl> - Déplacer un contrôle en appuyant sur <Ctrl> + Déplacer un contrôle en appuyant sur <Ctrl> AutomationPatternView double-click to open this pattern in automation editor - double-cliquer pour ouvrir ce motif dans l'éditeur d'automation + double-cliquer pour ouvrir ce motif dans l'éditeur d'automation Open in Automation editor - Ouvrir dans l'éditeur d'automation + Ouvrir dans l'éditeur d'automation Clear - Effacer + Effacer Reset name - Réinitialiser le nom + Réinitialiser le nom Change name - Changer le nom + Changer le nom %1 Connections - %1 connexions + %1 connexions Disconnect "%1" - Déconnecter "%1" + Déconnecter "%1" AutomationTrack Automation track - Piste d'automation + Piste d'automation @@ -482,11 +482,11 @@ If you're interested in translating LMMS in another language or want to imp Confirm Delete - + Confirmer la suppression Confirm delete? There are existing connection(s) associted with this controller. There is no way to undo. - + Confirmer la suppression ? Il existe des connection(s) associée(s) avec ce contrôleur. Il n'est pas possible d'annuler cette action. @@ -1037,7 +1037,7 @@ Un clic-droit fera apparaître un menu contextuel où vous pourrez changer l&apo Export as loop (remove end silence) - + Exporter sous la forme d'une boucle (supprime le silence de fin) @@ -1082,130 +1082,130 @@ Un clic-droit fera apparaître un menu contextuel où vous pourrez changer l&apo InstrumentFunctionArpeggio Arpeggio - Arpège + Arpège Arpeggio type - Type d'arpège + Type d'arpège Arpeggio range - Gamme d'arpège + Plage d'arpège Arpeggio time - Temps d'arpège + Temps d'arpège Arpeggio gate - Durée d'arpège + Durée d'arpège Arpeggio direction - Sens d'arpège + Direction de l'arpège Arpeggio mode - Mode d'arpège + Mode d'arpège Up - Ascendant + Ascendant Down - Descendant + Descendant Up and down - Ascendant et descendant + Ascendant et descendant Random - Aléatoire + Aléatoire Free - Libre + Libre Sort - Tri + Tri Sync - + Sync InstrumentFunctionArpeggioView ARPEGGIO - ARPÈGE + ARPÈGE An arpeggio is a method playing (especially plucked) instruments, which makes the music much livelier. The strings of such instruments (e.g. harps) are plucked like chords. The only difference is that this is done in a sequential order, so the notes are not played at the same time. Typical arpeggios are major or minor triads, but there are a lot of other possible chords, you can select. - Un arpège est une façon de jouer des instruments (en particulier ceux à cordes pincées), qui rend la musique plus vivante. Les cordes de tels instruments (p. ex. les harpes) sont pincées comme des accords. La seule différence est que cela est fait de manière séquentielle, ce qui fait que les notes ne sont pas jouées en même temps. Les arpèges typiques sont des triades majeures ou mineures, mais il y a beaucoup d'autres accords possibles, vous pouvez choisr. + Un arpège est une façon de jouer des instruments (en particulier ceux à cordes pincées), qui rend la musique plus vivante. Les cordes de tels instruments (p. ex. les harpes) sont pincées comme des accords. La seule différence est que cela est fait de manière séquentielle, ce qui fait que les notes ne sont pas jouées en même temps. Les arpèges typiques sont des triades majeures ou mineures, mais il y a beaucoup d'autres accords possibles, vous pouvez choisr. RANGE - GAMME + PLAGE Arpeggio range: - Gamme d'arpège : + Plage d'arpège : octave(s) - octave(s) + octave(s) Use this knob for setting the arpeggio range in octaves. The selected arpeggio will be played within specified number of octaves. - Utilisez ce bouton pour régler la gamme d'octaves de l'arpège. L'arpège sélectionné sera joué sur le nombre d'octaves choisi. + Utilisez ce bouton pour régler la plage de l'arpège en octaves. L'arpège sélectionné sera joué sur le nombre d'octaves choisi. TIME - TEMPS + TEMPS Arpeggio time: - Temps d'arpège : + Temps d'arpège : ms - ms + ms Use this knob for setting the arpeggio time in milliseconds. The arpeggio time specifies how long each arpeggio-tone should be played. - Utilisez ce bouton pour régler le temps d'arpège en millisecondes. Le temps d'arpège indique la durée pendant laquelle chaque note de l'arpège sera joué. + Utilisez ce bouton pour régler le temps d'arpège en millisecondes. Le temps d'arpège indique la durée pendant laquelle chaque note de l'arpège sera joué. GATE - + DUREE Arpeggio gate: - Durée d'arpège : + Durée d'arpège : % - % + % Use this knob for setting the arpeggio gate. The arpeggio gate specifies the percent of a whole arpeggio-tone that should be played. With this you can make cool staccato arpeggios. - Utilisez ce bouton pour régler la durée d'arpège. La durée d'arpège indique le pourcentage d'une note complète de l'arpège qui sera joué. Avec ceci vous pouvez faire de beaux arpèges staccato. + Utilisez ce bouton pour régler la durée d'arpège. La durée d'arpège indique le pourcentage d'une note complète de l'arpège qui sera joué. Avec ceci vous pouvez faire de beaux arpèges staccato. Chord: - + Accord: Direction: - Sens : + Direction : Mode: - Mode : + Mode : @@ -1576,7 +1576,7 @@ Un clic-droit fera apparaître un menu contextuel où vous pourrez changer l&apo Minor - + Mineur @@ -1599,11 +1599,11 @@ Un clic-droit fera apparaître un menu contextuel où vous pourrez changer l&apo STACKING - + EMPILEMENT Chord: - + Accord: @@ -1638,7 +1638,7 @@ Un clic-droit fera apparaître un menu contextuel où vous pourrez changer l&apo NOTE - + NOTE @@ -1713,31 +1713,31 @@ Un clic-droit fera apparaître un menu contextuel où vous pourrez changer l&apo RC LowPass 12dB - + RC Passe Bas 12dB RC BandPass 12dB - + RC Passe Bande 12dB RC HighPass 12dB - + RC Passe Haut 12dB RC LowPass 24dB - + RC Passe Bas 24dB RC BandPass 24dB - + RC Passe Bande 24dB RC HighPass 24dB - + RC Passe Haut 24dB Vocal Formant Filter - + Filtre Formant Vocal @@ -1780,11 +1780,11 @@ Un clic-droit fera apparaître un menu contextuel où vous pourrez changer l&apo FREQ - FRÉQ + FRÉQ cutoff frequency: - + Fréquence de coupure: @@ -1823,7 +1823,7 @@ Un clic-droit fera apparaître un menu contextuel où vous pourrez changer l&apo Pitch range - + Plage de hauteur @@ -1953,11 +1953,11 @@ Un clic-droit fera apparaître un menu contextuel où vous pourrez changer l&apo Pitch range (semitones) - + Plage de hauteur (demi-tons) RANGE - GAMME + PLAGE @@ -2128,7 +2128,8 @@ Un clic-droit fera apparaître un menu contextuel où vous pourrez changer l&apo Click here for a user-defined shape. Double click to pick a file. - + Cliquez ici pour une forme définie par l'utilisateur. +Double cliquez pour choisir un fichier. @@ -2355,39 +2356,39 @@ Veuillez visiter http://lmms.sf.net/wiki pour la documentation de LMMS. Save as new &version - + Enregistrer comme nouvelle &version E&xport tracks... - + E&xporter les pistes... LMMS (*.mmp *.mmpz) - + LMMS (*.mmp *.mmpz) LMMS Project (*.mmp *.mmpz);;LMMS Project Template (*.mpt) - + Projet LMMS (*.mmp *.mmpz);;Modèle de projet LMMS (*.mpt) Version %1 - + Version %1 Project recovery - + Récupération de projet It looks like the last session did not end properly. Do you want to recover the project of this session? - + Il semble que la dernière session ne se soit pas terminée correctement. Voulez-vous récupérer le projet de cette session? Configuration file - + Fichier de configuration Error while parsing configuration file at line %1:%2: %3 - + Erreur pendant l'analyse du fichier de configuration à la ligne %1:%2:%3 @@ -2503,7 +2504,7 @@ Veuillez visiter http://lmms.sf.net/wiki pour la documentation de LMMS. Fixed output note - + Note de sortie fixe @@ -2604,11 +2605,11 @@ Veuillez visiter http://lmms.sf.net/wiki pour la documentation de LMMS. Peak Controller Bug - + Bug du contrôleur de crêtes Due to a bug in older version of LMMS, the peak controllers may not be connect properly. Please ensure that peak controllers are connected properly and re-save this file. Sorry for any inconvenience caused. - + A cause d'un bug dans les anciennes versions de LMMS, les contrôleurs de crêtes peuvent ne pas s'être connecté correctement. Verifiez que les contrôleurs de crêtes sont connectés correctement et re-sauvegardez ce fichier. Désolé pour la gène occasionnée. @@ -2638,31 +2639,31 @@ Veuillez visiter http://lmms.sf.net/wiki pour la documentation de LMMS. Attack: - Attaque : + Attaque : Release: - Relâchement : + Relâchement : AMNT - + AMNT MULT - + MULT Amount Multiplicator: - + Multiplicateur de quantité: ATCK - + ATCK DCAY - + DCAY @@ -2681,19 +2682,19 @@ Veuillez visiter http://lmms.sf.net/wiki pour la documentation de LMMS. Attack - Attaque + Attaque Release - Relâchement + Relâchement Abs Value - + Valeur Abs Amount Multiplicator - + Multiplicateur de quantité @@ -2740,87 +2741,87 @@ Raison : "%2" C Note name - + C Db Note name - + Db C# Note name - + C# D Note name - + D Eb Note name - + Eb D# Note name - + D# E Note name - + E Fb Note name - + Fb Gb Note name - + Gb F# Note name - + F# G Note name - + G Ab Note name - + Ab G# Note name - + G# A Note name - + A Bb Note name - + Bb A# Note name - + A# B Note name - + B @@ -2874,108 +2875,108 @@ Raison : "%2" SampleBuffer Open audio file - Ouvrir un fichier audio + Ouvrir un fichier audio All Audio-Files (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw *.mp3) - Tous les fichiers audio (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw *.mp3) + Tous les fichiers audio (*.wav *.ogg *.ds *.flac *.spx *.voc *.aif *.aiff *.au *.raw *.mp3) Wave-Files (*.wav) - Fichiers WAVE (*.wav) + Fichiers WAVE (*.wav) OGG-Files (*.ogg) - Fichiers OGG (*.ogg) + Fichiers OGG (*.ogg) DrumSynth-Files (*.ds) - Fichiers DrumSynth (*.ds) + Fichiers DrumSynth (*.ds) FLAC-Files (*.flac) - Fichiers FLAC (*.flac) + Fichiers FLAC (*.flac) SPEEX-Files (*.spx) - Fichiers SPEEX (*.spx) + Fichiers SPEEX (*.spx) MP3-Files (*.mp3) - Fichiers MP3 (*.mp3) + Fichiers MP3 (*.mp3) VOC-Files (*.voc) - Fichiers VOC (*.voc) + Fichiers VOC (*.voc) AIFF-Files (*.aif *.aiff) - Fichiers AIFF (*.aif *.aiff) + Fichiers AIFF (*.aif *.aiff) AU-Files (*.au) - Fichiers AU (*.au) + Fichiers AU (*.au) RAW-Files (*.raw) - Fichiers RAW (*.raw) + Fichiers RAW (*.raw) SampleTCOView double-click to select sample - Double-cliquez pour choisir un échantillon + Double-cliquez pour choisir un échantillon Delete (middle mousebutton) - + Supprimer (bouton du milieu de la souris) Cut - Couper + Couper Copy - Copier + Copier Paste - Coller + Coller Mute/unmute (<Ctrl> + middle click) - Couper/Jouer (<Ctrl> + clic-milieu) + Couper/Jouer (<Ctrl> + clic-milieu) Set/clear record - Régler/Effacer l'enregistrement + Régler/Effacer l'enregistrement SampleTrack Sample track - Piste d'échantillon + Piste d'échantillon Volume - Volume + Volume SampleTrackView Track volume - Volume de la piste + Volume de la piste Channel volume: - Volume du canal : + Volume du canal : VOL - VOL + VOL @@ -3061,50 +3062,50 @@ Raison : "%2" TimeDisplayWidget click to change time units - + cliquez pour changer les unités de temps TrackContainer Couldn't import file - Le fichier n'a pas pu être importé + Le fichier n'a pas pu être importé Couldn't find a filter for importing file %1. You should convert this file into a format supported by LMMS using another software. - Aucun filtre n'a pu être trouvé pour importer le fichier %1. + Aucun filtre n'a pu être trouvé pour importer le fichier %1. Vous devriez convertir ce fichier dans un format pris en charge par LMMS en utilisant un autre logiciel. Couldn't open file - Le fichier n'a pas pu être ouvert + Le fichier n'a pas pu être ouvert Couldn't open file %1 for reading. Please make sure you have read-permission to the file and the directory containing the file and try again! - Le fichier %1 n'a pas pu être ouvert en lecture. + Le fichier %1 n'a pas pu être ouvert en lecture. Veuillez vérifier que vous avez les droits en lecture pour ce fichier et le répertoire qui contient ce fichier et réessayez ! Loading project... - Chargement du projet... + Chargement du projet... Cancel - Annuler + Annuler Please wait... - Veuillez patienter... + Veuillez patienter... Importing MIDI-file... - Importation du fichier MIDI... + Importation du fichier MIDI... Importing FLP-file... - Importation du fichier FLP... + Importation du fichier FLP... @@ -3254,22 +3255,22 @@ Veuillez vérifier que vous avez les droits en lecture pour ce fichier et le ré Ui Contributors ordered by number of commits: - + Contributeurs classés par nombre de commits: Involved - + Impliqué VersionedSaveDialog Increment version number - + Incrémenter le numéro de version Decrement version number - + Décrémenter le numéro de version @@ -3312,110 +3313,110 @@ Veuillez vérifier que vous avez les droits en lecture pour ce fichier et le ré Control VST-plugin from LMMS host - + Contrôler le greffon VST à partir de l'hôte LMMS Click here, if you want to control VST-plugin from host. - + Cliquez ici si vous voulez contrôler le greffon VST à partir de l'hôte. Open VST-plugin preset - + Ouvrir les pré-réglages du greffon VST Click here, if you want to open another *.fxp, *.fxb VST-plugin preset. - + Cliquez ici si vous voulez ouvrir un autre pré-réglage de greffon VST *.fxp, *.fxb. Previous (-) - + Précédent (-) Click here, if you want to switch to another VST-plugin preset program. - + Cliquez ici si vous voulez passer à un autre programme de pré-réglage de plugin VST. Save preset - Enregistrer le préréglage + Enregistrer le pré-réglage Click here, if you want to save current VST-plugin preset program. - + Cliquez ici si vous voulez sauvegarder le programme de pré-réglage de greffon VST courant. Next (+) - + Suivant (+) Click here to select presets that are currently loaded in VST. - + Cliquez ici pour sélectionner les pré-réglages qui sont actuellement chargés dans le VST. Preset - + Pré-réglage by - + par - VST plugin control - + - contrôle de greffon VST VstEffectControlDialog Show/hide - + Montrer/Cacher Control VST-plugin from LMMS host - + Contrôler le greffon VST à partir de l'hôte LMMS Click here, if you want to control VST-plugin from host. - + Cliquez ici si vous voulez contrôler le greffon VST à partir de l'hôte. Open VST-plugin preset - + Ouvrir le pré-réglage du greffon VST Click here, if you want to open another *.fxp, *.fxb VST-plugin preset. - + Cliquez ici si vous voulez ouvrir un autre pré-réglage de greffon VST *.fxp, *.fxb. Previous (-) - + Précédent (-) Click here, if you want to switch to another VST-plugin preset program. - + Cliquez ici si vous voulez passer à un autre programme de pré-réglage de plugin VST. Next (+) - + Suivant (+) Click here to select presets that are currently loaded in VST. - + Cliquez ici pour sélectionner les pré-réglages qui sont actuellement chargés dans le VST. Save preset - Enregistrer le préréglage + Enregistrer le pré-réglage Click here, if you want to save current VST-plugin preset program. - + Cliquez ici si vous voulez sauvegarder le programme de pré-réglage de greffon VST courant. Effect by: - + Effet par: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /> - + &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /> @@ -3440,78 +3441,78 @@ S'il fonctionne avec d'autres logiciels VST sous Linux, merci de conta Open Preset - + Ouvrir le Pré-réglage Vst Plugin Preset (*.fxp *.fxb) - + Pré-réglage de Greffon VST (*.fxp *.fxb) : default - + : défaut " - + " ' - + ' Save Preset - + Enregistrer le pré-réglage .fxp - + .fxp .FXP - + .FXP .FXB - + .FXB .fxb - + .fxb ZynAddSubFxInstrument Portamento - + Portamento Filter Frequency - + Fréquence du Filtre Filter Resonance - + Résonance du Filtre Bandwidth - + Largeur de bande FM Gain - + Gain FM Resonance Center Frequency - + Fréquence Centrale de la Résonance Resonance Bandwidth - + Largeur de Bande de la Résonance Forward MIDI Control Change Events - + Transmet les évènements MIDI Control Change @@ -3526,63 +3527,63 @@ S'il fonctionne avec d'autres logiciels VST sous Linux, merci de conta Portamento: - + Portamento: PORT - + PORT Filter Frequency: - + Fréquence du Filtre: FREQ - FRÉQ + FRÉQ Filter Resonance: - + Résonance du Filtre: RES - RES + RES Bandwidth: - + Largeur de bande: BW - + BW FM Gain: - + Gain FM: FM GAIN - + GAIN FM Resonance center frequency: - + Fréquence centrale de la résonance: RES CF - + RES CF Resonance bandwidth: - + Largeur de Bande de la Résonance: RES BW - + RES BW Forward MIDI Control Changes - + Transmet les évènements MIDI Control Change @@ -3609,7 +3610,8 @@ S'il fonctionne avec d'autres logiciels VST sous Linux, merci de conta Stutter - + ?? + Bégaiement @@ -3686,11 +3688,11 @@ S'il fonctionne avec d'autres logiciels VST sous Linux, merci de conta Remove steps - Supprimer des pas + Supprimer des pas Add steps - Ajouter des pas + Ajouter des pas @@ -3720,7 +3722,7 @@ S'il fonctionne avec d'autres logiciels VST sous Linux, merci de conta Clone of %1 - + Clone de %1 @@ -3838,7 +3840,7 @@ Veuillez vérifier que vous avez les droits d'accès en écriture pour ce f fader Please enter a new value between %1 and %2: - Veuillez entrer un valeur entre %1 et %2 : + Veuillez entrer un valeur entre %1 et %2 : @@ -4586,62 +4588,62 @@ En double-cliquant sur ces greffons vous ferez apparaître des informations sur manageVSTEffectView - VST parameter control - + - Paramètre de contrôle VST VST Sync - + VST Sync Click here if you want to synchronize all parameters with VST plugin. - + Cliquez ici si vous voulez synchroniser tous les paramètres avec le greffon VST. Automated - + Automatique Click here if you want to display automated parameters only. - + Cliquez ici si vous voulez seulement afficher les paramètres automatiques. Close - + Fermer Close VST effect knob-controller window. - + Fermer la fenêtre des boutons contrôleurs des effets VST. manageVestigeInstrumentView - VST plugin control - + - contrôle de greffon VST VST Sync - + VST Sync Click here if you want to synchronize all parameters with VST plugin. - + Cliquez ici si vous voulez synchroniser tous les paramètres avec le greffon VST. Automated - + Automatique Click here if you want to display automated parameters only. - + Cliquez ici si vous voulez seulement afficher les paramètres automatiques. Close - + Fermer Close VST plugin knob-controller window. - + Fermer la fenêtre des boutons contrôleurs des effets VST. @@ -4655,39 +4657,39 @@ En double-cliquant sur ces greffons vous ferez apparaître des informations sur opl2instrument Patch - Son + Son Op 1 Attack - + Op 1 Decay - + Op 1 Sustain - + Op 1 Release - + Op 1 Level - + Op 1 Level Scaling - + Op 1 Frequency Multiple - + Op 1 Feedback - + Op 1 Key Scaling Rate @@ -4759,15 +4761,15 @@ En double-cliquant sur ces greffons vous ferez apparaître des informations sur FM - + FM Vibrato Depth - + Profondeur de Vibrato Tremolo Depth - + Profondeur de Trémolo @@ -5269,27 +5271,27 @@ utilisez la molette de la souris pour régler le volume d'un pas Mark/unmark current semitone - + Cocher/décocher le demi-ton courant Mark current scale - + Cocher la gamme courante Mark current chord - + Cocher l'accord courant Unmark all - + Déchocher tout No scale - + Pas de gamme No chord - + Pas d'accord @@ -5405,15 +5407,15 @@ This chip was used in the Commodore 64 computer. 2-operator FM Synth - + Synthé FM à 2 opérateurs Filter for importing Hydrogen files into LMMS - + Filtre pour importer des fichiers Hydrogen dans LMMS LMMS port of sfxr - + Port LMMS de sfxr @@ -5712,35 +5714,35 @@ Latence : %2 ms One instrument track window mode - + Mode fenêtre une piste d'instrument Compact track buttons - + Boutons de piste compacte Sync VST plugins to host playback - + Sync les greffons VST à la lecture de l'hôte Enable note labels in piano roll - + Activer les étiquettes de note dans le piano virtuel Enable waveform display by default - + Activer l'affichage de forme d'onde par défaut Smooth scroll in Song Editor - + Déplacement fluide dans l'Editeur de Chanson Enable auto save feature - + Activer la fonction de sauvegarde automatique Show playback cursor in AudioFileProcessor - + Afficher le curseur de lecture dans AudioFileProcessor @@ -5877,7 +5879,7 @@ Latence : %2 ms sfxrInstrument Wave Form - + Forme d'Onde @@ -6106,11 +6108,11 @@ Latence : %2 ms Hydrogen projects - + Projets Hydrogen Select directory for writing exported tracks... - + Sélectionnez un répertoire pour écrire les pistes exportées... @@ -6231,7 +6233,7 @@ Veuillez vérifier que vous avez les droits en lecture pour ce fichier et le ré Could not open %1 for writing. You probably are not permitted to write to this file. Please make sure you have write-access to the file and try again. - + Ne peux pas ouvrir %1 en écriture. Vous n'avez probablement pas les droits pour écrire dans ce fichier. Assurez vous que vous avez les droits d'accès en écriture pour ce fichier et essayez à nouveau. @@ -6344,11 +6346,11 @@ Veuillez vérifier que vous avez les droits en lecture pour ce fichier et le ré Press <Ctrl> to disable magnetic loop points. - + Appuyez sur <Ctrl> pour désactiver les marqueur magnétiques de jeu en boucle. Hold <Shift> to move the begin loop point; Press <Ctrl> to disable magnetic loop points. - + Maintenez <Shift> pour déplacer le marqueur de début de jeu en boucle. Appuyez sur <Ctrl> pour désactiver les marqueurs magnétiques de jeu en boucle. From 045353735f188c232b2c0710a56e058368b477d5 Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Mon, 9 Jun 2014 11:12:01 -0400 Subject: [PATCH 30/61] Updated logo for NSIS installer --- data/nsis_branding.bmp | Bin 25886 -> 34338 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/data/nsis_branding.bmp b/data/nsis_branding.bmp index 901497e2c33879a331516cbf39078dc3dc1f2ee2..f617b5bccf81834be8e3fe7af4c4d1b7b0f3bc8b 100644 GIT binary patch literal 34338 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 literal 25886 zcmeI4d300PoyVE^Yo;MU2wt>XUS(^SCEM~I@P-$>FOs|sZO*iroYR?3n@;95nVz;u z+RW1FX_E;FkU$o)49O%tBqiX4Km&oWIM`s>#=9+fk+r<1U9vsjr)P`{a%#MUkjm%z z`RQ8k-uv!Hzu*1d-@RAc%eW722>kpj&JW}FS^TQ;`&Szxao(`umG5lWaQ{8@Zy*7u z?S)nUeEoX4fB*WXH_nBA?(!DcuwlgyFgrWzoAu##x7$53GUE69aqXY+BYnkre))~a z**{B_;_-NfhlhPWs&t>HbL0P-*Qcn36qKW=7M794uOlo z=-rb0T;5y%_rDH@1CPCWjC6@4Nj}&1Le9n9OphwtuS)gE3dsCsqFGC7%X%tG_f#Ev z`}MUd@oP*gc-3x`A-cW~&K=EpFE^}jBYS#l(qv-Vc!tcNEHoFjkj=G3O^!1))*Z$= z6V~vX#!t_jM#mMr+-0Y_T&|<%kCnAmsEOp9nUpM_GJ6ILr3FMD7-|TO)~0PF8}mLZ zZu-scQ=gtf4VRtwH{^}WW(cv;-up%4yDbrywy?~b6HGCx@w8N9W|}dRX4p(Np+$8z zT_sVj_K3OU7XCX?Kicyz-PgKT)>%QUboO=r{U07uj>sRFOU?070JHqJFeJ1ZtEP!; z)DYU-ck&7IVO|owz|g|^tf|#ANQY!Tb9jm|CNK`;~SL|DdI6XoTtjD215W`%n%LPNHo^l>T7H@ zMV8`SmhxtMbN+`rSH^I!{$RFGnd489JA^8?B;BXTgd_E<7Tckg(9k7T+iG@NO3E!2 zt7lbq>QP*TRPN^wh+E^(Sy2D2<83*fGIS$CmmSUwaLRiahX>}(D( z3l9DtUkB!J8S5XTk`fZ_>uov!=4ktrc*jlnbR8 z&TGZhFx;A!=ZRW!7Ejn&8>y+jVumbbr??X)al&E14qcq3lrQ6e}De zl}myn#Vb*JZ)wj#gx)7Z?U%)94lGb*y2FfYw1pz+9{LR1OTXVfG3hl;@^WBifsROUOj zXCK=Uvcq5)U%2`bq+p}15#t70b_QjLf8o&C8td#;sWU?E*fz~4jfi~H(^bJT4w6R4 z+Rhr!OFI?G4sn)SsdmWHoDv+VPAOcg${|j62(vtj1-V0wB>l;V3CMi${NucVp@AUz zenXR%9jAFgf1rWXl$c9*S%oz;KA+ zt*ws8myXn7qNmzgjhQBTC`dWgd0$%I2#s&k7Q1!`e38tKZBKmh%L#Jg)_iU^#pCm~ zn=flFH_N9afR<*5K}wVDNiut)+AU9qcMYgk1)buQC(p&PPez6q25aZN-7kY7d?{Qg z^e2W9kb+qGA$LD!(`2DP_xhhhe;Z(o~Wn`k- zN%fG)c9F!E0O1OQ1mxt|_z=S-8hW4pl?8^t2sw(FTA^iUg|)K8R;+Ldc;>Cy=dwN- zJhlA!i6x3!GMRMSpStp&iU9?Dsf;x6LqBcJ^ANs1npCI+Vdmda%H>Ao3i zJ>sa@Sl81ab_i6YRAs01YTyv3I%HBzJf8^lhe2B!Q4=r(G}@8E2oY~CnJz2z?1&%W zK6d7@pm(i#BE3YaXR2Q_sFgVrg=T?-NK)FxDb%n-qP9z={^$_HC7S)EuGhe@$wmd3 zsVO@uG+NqhYpL;-$Mmy*ditkJ+_%QbG{b(=kfvWNcL`N?snD7ru*Ayctz z9Lh82W3|NsKxmpf$grVbBXK0ktYWE6NF9VwZWk#?ah#3K{*V!hwFQHC;Oe0oq89T? z<7zrs4$Cu|i9{*d`EJ6C^1&~BN?e8f zQAWkV%D%q&IQKejBSje27XXM#wVnSY^=w8w!55j(2gVC63Fr((AZZrFJ2|Y79WDa5 z=<sf)18qtKs8qKTo}+ zjv3`gPejE}MGMXGNz-vONs1vfO^D$laEmT!hKRKx$_7UYJH)~#tggmO%so|+)tYHd zSyyHKt4)XBJv_g!8+(OUy{{WN&^v&U=iZMG+@m zO;Tt|h_`dt$3kO^MdWT=f+03+V&NDx4W@yM%sa8E0ssT^hn1LtYO-UEhPKXBUwpn| z_Y2=WckUd0^J)xoVgGj9=O@aJRVVZ%@D2QE6F+K_$DiN|OwkD@bcr#s6HzgfQHkgn zP4TfLE5z^ywm-Q#(0!;eFppngF2oR#?h4k(uNBzxGHq#EPztQ1p)p=(SV=QnV2gDbRmR$aSIeGx?Kx`y z;q73g0M5?ft|yN^EjTUa8F^eIhcnIrx~Oq3Nb-$5T=OUS(Nj@zQ+$xbkz|VFPjJ{% z+t|lh!(+q29^#vsw(K=g?UNny3(_dt7L_xp!d|w3@jAnKJG{XV+7*j$$Qos*y84-h zBgc=Bc5*q^2;WOO$T$CZIQ9KZW*-~qI0g>K$e}TE$GN--9v3`~92g{jf*&=-kDcPj znRuWVY1qiTyyXXHe&q44b`SYognQWxsb`v<`*p|f;`O{(M|hS)RpY1vF)W2bXNY65 z9fB~HfMe+twNk@cs&h5woXGp`vkzZrzkvPqU(!4-x9iiZXR6oZ} zjxgCqHjNSVfD!2&1Dih?6%9=@8O5252p`?Z>fT&>y7c1k7hjV9H}YT0W{3cZZ;qNn zpC+siU;KXbP=vtF%5!9C?G2d8s0{Rn(5s+_6;s955_$_Fz!sTHu*CIcZ9?0V=;%Bj4=jtjL8_H&hsQ;nMO7+ zMosWIlaY~Qo0-?{Ri9P9-g%ftM1S+qHxgIShgvqn>&-)jN$_)Nth4HJC4VwZPR2jr z$fzVL5CzAq24Zk9KVZb{BJFRnJs0K*p@aB9i?5|@prUwh#Y;yHVgWy$70#m*qrW}* zY|;@K`x=Kk%Hi~Ln1f7aKNAe8W0VQ1utvrRgJoc`(Kn89*ail}a9?=uJ>m-qzqs&A zmy>dy-dXQ@F9unt^VjF%HW{MgXe2Zh{RD4zzn#~U&79aIw+Tv}MVK3|vDVISAPwjq zSSA?i0&yLxtF&la9W711rtO~(jJfSxs)AAzd|$ z+`MxXNsrV2?^pgSwOhuS*qY^1);nwH{YL?DLq!7u45^p^ePD~A&Z7H{e|H^GpYdMq z_7@9TC!^SX?5Jxzj-JEnVSyoaTw^hN10-)?WU)us48yjF-c79Y_t#&j{iyFGT^TPv zRjUprd}U3(<^`>kAzcxyGNUIF2B$_I>3Kvr7@cV4=6N$U_6B<84Y=*J6w`4XnjtNH zD$P|05fqc9!eJ5XDvQ_2V_#*n^epP=p2x`S4wxcra)8AeWV44E5&fGZE^RKnxZ@@L zL3;h1ch<8I2UzpAxmz+^9YZ`N7{Uzb$2~Q2`oX@x;|y$*Ibut^`9O!DI2eK+`bKzE z0K{wurXNeKrC?ZZs+Z^`%*#x6CmRRr3JW|bjIhQY78t@HIlUZCA1ktdOZer@DQ9KB z>U`R0qQ9MOhF+(5x3u*7)pOMh>8jxyWoXsv^US_Abhx^2SJX&^%9~W;gaxI4HdKrmE>`QICkx!QgaqD259pyC`d9cConKT-LR)h^w1;pR#`3@kskv z2VESL=U=k(yy@exMhvev?YwFoH&5*u+LO_p5q)D#)?z&>oGLx$z~Cb&Lv{y;dxaCxwJH4Emf|x- zhX>!b5CmQ85WSn|(J$AUA)PBaNjhSUKj)_|JaqLT?zJ$fpI_mg-!)I|RHW^&o3=x$ zKZG@MVS)O{@XPm#Pb5Cy^Zbx`G(;~bx5bI;!*GEleL*@M$0v`MUf#(wY*WvPYV1`y zE7e0*qd)8xM+ST;r-Q@0$_nq=81c#dkGKDuewzA9V*KFaKucfxW$1is3#=zYy0irX zCWrae;n&1pBu3k|?eMELq^8zX2ZoHx3|=RPq2C;Sc8l(G zw7~i^TqugZFxZVh>-srUzcta%%pc5ZCe=qN2_U|tLkJVxOvy~0KA!rNSA%=8aj*NWp#Km7>PiWApg%X$9 I0vk5`KlMQgh5!Hn From 9af0d7af93596d93a10deeb620e02a1a983b4144 Mon Sep 17 00:00:00 2001 From: Vesa Date: Tue, 10 Jun 2014 09:02:20 +0300 Subject: [PATCH 31/61] LB302: further fixes - My earlier fixes caused some new issues, now I'm fixing them, this time I'm pretty sure there won't be anything I missed --- plugins/lb302/lb302.cpp | 22 +++++++++++++--------- plugins/lb302/lb302.h | 1 + 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/plugins/lb302/lb302.cpp b/plugins/lb302/lb302.cpp index 331dec240..f0b1f7f71 100644 --- a/plugins/lb302/lb302.cpp +++ b/plugins/lb302/lb302.cpp @@ -472,7 +472,7 @@ int lb302Synth::process(sampleFrame *outbuf, const int size) // Hold on to the current VCF, and use it throughout this period lb302Filter *filter = vcf; - if( delete_freq == current_freq ) { + if( release_frame == 0 || delete_freq == current_freq ) { // Normal release delete_freq = -1; vca_mode = 1; @@ -761,27 +761,29 @@ void lb302Synth::processNote( NotePlayHandle * _n ) //if (_n->released() && catch_decay == 0) // catch_decay = 1; - bool decay_note = false; +/* bool decay_note = false;*/ - release_frame = _n->framesLeft() - desiredReleaseFrames(); + release_frame = qMax( release_frame, _n->framesLeft() ); //LB303 if ( _n->totalFramesPlayed() <= 0 ) { // This code is obsolete, hence the "if false" // Existing note. Allow it to decay. - if(deadToggle.value() == 0 && decay_note) { +/* if(deadToggle.value() == 0 && decay_note) { - /* lb302Note note; + lb302Note note; note.vco_inc = _n->frequency()*vco_detune/engine::mixer()->processingSampleRate(); // TODO: Use actual sampling rate. note.dead = deadToggle.value(); initNote(¬e); vca_mode=0; - */ + - } + }*/ /// Start a new note. - else if( _n->m_pluginData == NULL ) { + if( _n->m_pluginData != this || ( ! m_playingNote && ! _n->isReleased() ) ) + { + m_playingNote = _n; new_freq = _n->unpitchedFrequency(); true_freq = _n->frequency(); _n->m_pluginData = this; @@ -808,6 +810,7 @@ void lb302Synth::processNote( NotePlayHandle * _n ) void lb302Synth::play( sampleFrame * _working_buffer ) { + release_frame = 0; while( ! m_notes.isEmpty() ) { processNote( m_notes.takeFirst() ); @@ -825,9 +828,10 @@ void lb302Synth::play( sampleFrame * _working_buffer ) void lb302Synth::deleteNotePluginData( NotePlayHandle * _n ) { //printf("GONE\n"); - if( _n->unpitchedFrequency() == current_freq ) + if( m_playingNote == _n ) { delete_freq = current_freq; + m_playingNote = NULL; } } diff --git a/plugins/lb302/lb302.h b/plugins/lb302/lb302.h index b3bfb2100..8ff0df4cb 100644 --- a/plugins/lb302/lb302.h +++ b/plugins/lb302/lb302.h @@ -245,6 +245,7 @@ private: friend class lb302SynthView; + NotePlayHandle * m_playingNote; NotePlayHandleList m_notes; QMutex m_notesMutex; } ; From 11209593e09106e9ae1194880d48dc0d54552618 Mon Sep 17 00:00:00 2001 From: Vesa Date: Wed, 11 Jun 2014 15:05:07 +0300 Subject: [PATCH 32/61] Last LB302 fixes for now (I hope!) --- plugins/lb302/lb302.cpp | 141 +++++++++++++++------------------------- plugins/lb302/lb302.h | 5 +- 2 files changed, 56 insertions(+), 90 deletions(-) diff --git a/plugins/lb302/lb302.cpp b/plugins/lb302/lb302.cpp index f0b1f7f71..dbfa61301 100644 --- a/plugins/lb302/lb302.cpp +++ b/plugins/lb302/lb302.cpp @@ -331,7 +331,7 @@ lb302Synth::lb302Synth( InstrumentTrack * _instrumentTrack ) : vca_attack = 1.0 - 0.96406088; vca_decay = 0.99897516; - vco_shape = SAWTOOTH; + vco_shape = BL_SAWTOOTH; // Experimenting with a0 between original (0.5) and 1.0 vca_a0 = 0.5; @@ -343,15 +343,13 @@ lb302Synth::lb302Synth( InstrumentTrack * _instrumentTrack ) : db24Toggled(); sample_cnt = 0; - release_frame = 1<<24; + release_frame = 0; catch_frame = 0; catch_decay = 0; last_offset = 0; - new_freq = -1; - current_freq = -1; - delete_freq = -1; + new_freq = false; filterChanged(); @@ -472,27 +470,20 @@ int lb302Synth::process(sampleFrame *outbuf, const int size) // Hold on to the current VCF, and use it throughout this period lb302Filter *filter = vcf; - if( release_frame == 0 || delete_freq == current_freq ) { - // Normal release - delete_freq = -1; + if( release_frame == 0 || ! m_playingNote ) + { vca_mode = 1; } - if( new_freq > 0.0f ) { + if( new_freq ) + { //printf(" playing new note..\n"); lb302Note note; note.vco_inc = GET_INC( true_freq ); - //printf("GET_INC %f %f %d\n", note.vco_inc, new_freq, vca_mode ); - ///**vco_detune*//engine::mixer()->processingSampleRate(); // TODO: Use actual sampling rate. - //printf("VCO_INC = %f\n", note.vco_inc); note.dead = deadToggle.value(); initNote(¬e); - //printf("%f %f, ", vco_inc, vco_c); - current_freq = new_freq; - - new_freq = -1.0f; - //printf("GOT_INC %f %f %d\n\n", note.vco_inc, new_freq, vca_mode ); + new_freq = false; } @@ -500,7 +491,13 @@ int lb302Synth::process(sampleFrame *outbuf, const int size) // TODO: NORMAL RELEASE // vca_mode = 1; - for(int i=0;i= release_frame ) + { + vca_mode = 1; + } // update vcf if(vcf_envpos >= ENVINC) { @@ -524,17 +521,10 @@ int lb302Synth::process(sampleFrame *outbuf, const int size) // update vco vco_c += vco_inc; - + if(vco_c > 0.5) vco_c -= 1.0; - /*LB303 - if (catch_decay > 0) { - if (catch_decay < decay_frames) { - catch_decay++; - } - }*/ - switch(int(rint(wave_shape.value()))) { case 0: vco_shape = SAWTOOTH; break; case 1: vco_shape = TRIANGLE; break; @@ -640,17 +630,11 @@ int lb302Synth::process(sampleFrame *outbuf, const int size) */ //LB302 samp *= (float)(decay_frames - catch_decay)/(float)decay_frames; - for(int c=0; c=release_frame) { - vca_mode=1; - } - */ - // Handle Envelope if(vca_mode==0) { vca_a+=(vca_a0-vca_a)*vca_attack; @@ -696,18 +680,7 @@ void lb302Synth::initNote( lb302Note *n) vca_mode = 2; } - // Initiate Slide - // TODO: Break out into function, should be called again on detuneChanged - if (vco_slideinc) { - //printf(" sliding\n"); - vco_slide = vco_inc-vco_slideinc; // Slide amount - vco_slidebase = vco_inc; // The REAL frequency - vco_slideinc = 0; // reset from-note - } - else { - vco_slide = 0; - } - // End break-out + initSlide(); // Slide-from note, save inc for next note if (slideToggle.value()) { @@ -730,6 +703,21 @@ void lb302Synth::initNote( lb302Note *n) } +void lb302Synth::initSlide() +{ + // Initiate Slide + if (vco_slideinc) { + //printf(" sliding\n"); + vco_slide = vco_inc-vco_slideinc; // Slide amount + vco_slidebase = vco_inc; // The REAL frequency + vco_slideinc = 0; // reset from-note + } + else { + vco_slide = 0; + } +} + + void lb302Synth::playNote( NotePlayHandle * _n, sampleFrame * _working_buffer ) { if( _n->isMasterNote() ) @@ -748,49 +736,34 @@ void lb302Synth::playNote( NotePlayHandle * _n, sampleFrame * _working_buffer ) m_notes.prepend( _n ); } m_notesMutex.unlock(); + + release_frame = qMax( release_frame, _n->framesLeft() + _n->offset() ); } void lb302Synth::processNote( NotePlayHandle * _n ) { - //fpp_t framesPerPeriod = engine::mixer()->framesPerPeriod(); - - // Currently have release/decay disabled - // Start the release decay if this is the first release period. - //if (_n->released() && catch_decay == 0) - // catch_decay = 1; - -/* bool decay_note = false;*/ - - release_frame = qMax( release_frame, _n->framesLeft() ); - - - //LB303 if ( _n->totalFramesPlayed() <= 0 ) { - // This code is obsolete, hence the "if false" - - // Existing note. Allow it to decay. -/* if(deadToggle.value() == 0 && decay_note) { - - lb302Note note; - note.vco_inc = _n->frequency()*vco_detune/engine::mixer()->processingSampleRate(); // TODO: Use actual sampling rate. - note.dead = deadToggle.value(); - initNote(¬e); - vca_mode=0; - - - }*/ /// Start a new note. - if( _n->m_pluginData != this || ( ! m_playingNote && ! _n->isReleased() ) ) + if( _n->m_pluginData != this ) { m_playingNote = _n; - new_freq = _n->unpitchedFrequency(); - true_freq = _n->frequency(); + new_freq = true; _n->m_pluginData = this; } + + if( ! m_playingNote && ! _n->isReleased() && release_frame > 0 ) + { + m_playingNote = _n; + if ( slideToggle.value() ) + { + vco_slideinc = GET_INC( _n->frequency() ); + } + } // Check for slide - if( _n->unpitchedFrequency() == current_freq ) { + if( m_playingNote == _n ) + { true_freq = _n->frequency(); if( slideToggle.value() ) { @@ -800,27 +773,22 @@ void lb302Synth::processNote( NotePlayHandle * _n ) vco_inc = GET_INC( true_freq ); } } - - //LB303 } - - } void lb302Synth::play( sampleFrame * _working_buffer ) { - release_frame = 0; while( ! m_notes.isEmpty() ) { processNote( m_notes.takeFirst() ); }; - + const fpp_t frames = engine::mixer()->framesPerPeriod(); - process( _working_buffer, frames); - instrumentTrack()->processAudioBuffer( _working_buffer, frames, - NULL ); + process( _working_buffer, frames ); + instrumentTrack()->processAudioBuffer( _working_buffer, frames, NULL ); + release_frame = 0; } @@ -830,7 +798,6 @@ void lb302Synth::deleteNotePluginData( NotePlayHandle * _n ) //printf("GONE\n"); if( m_playingNote == _n ) { - delete_freq = current_freq; m_playingNote = NULL; } } diff --git a/plugins/lb302/lb302.h b/plugins/lb302/lb302.h index 8ff0df4cb..2777e7fa5 100644 --- a/plugins/lb302/lb302.h +++ b/plugins/lb302/lb302.h @@ -169,6 +169,7 @@ private: void processNote( NotePlayHandle * n ); void initNote(lb302Note *note); + void initSlide(); private: FloatModel vcf_cut_knob; @@ -234,9 +235,7 @@ private: int catch_frame; int catch_decay; - float new_freq; - float current_freq; - float delete_freq; + bool new_freq; float true_freq; void recalcFilter(); From 91519898d0a43c5ec0c82c13461b249b1d7525cf Mon Sep 17 00:00:00 2001 From: sarahkeefe Date: Wed, 11 Jun 2014 13:21:01 -0400 Subject: [PATCH 33/61] Replacing includes with to fix compile issue on OS X --- include/RemotePlugin.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/RemotePlugin.h b/include/RemotePlugin.h index edf09efbe..c2a37e437 100644 --- a/include/RemotePlugin.h +++ b/include/RemotePlugin.h @@ -52,7 +52,7 @@ #include #endif -#include +#include #if QT_VERSION >= 0x040400 #include @@ -75,7 +75,7 @@ #ifdef USE_QT_SHMEM -#include +#include #if QT_VERSION >= 0x040400 #include From 940fb0d3d523cbec38225cdd855179a6cfe3f144 Mon Sep 17 00:00:00 2001 From: sarahkeefe Date: Wed, 11 Jun 2014 17:16:28 -0400 Subject: [PATCH 34/61] Updating include to QtCore/QtGlobal --- include/RemotePlugin.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/RemotePlugin.h b/include/RemotePlugin.h index c2a37e437..40eb78632 100644 --- a/include/RemotePlugin.h +++ b/include/RemotePlugin.h @@ -52,7 +52,7 @@ #include #endif -#include +#include #if QT_VERSION >= 0x040400 #include @@ -75,7 +75,7 @@ #ifdef USE_QT_SHMEM -#include +#include #if QT_VERSION >= 0x040400 #include From 13d0bc73d92a3128536fb50814bcbc714d73de35 Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Thu, 12 Jun 2014 00:43:18 -0400 Subject: [PATCH 35/61] HKCR registry cleanup per #385 --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index f4b1b2a8f..86a3caba3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -655,6 +655,8 @@ SET(CPACK_NSIS_EXTRA_INSTALL_COMMANDS " SET(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS " \\\${unregisterExtension} \\\".mmp\\\" \\\"LMMS Project\\\" \\\${unregisterExtension} \\\".mmpz\\\" \\\"LMMS Project (compressed)\\\" + DeleteRegKey HKCR \\\"LMMS Project\\\" + DeleteRegKey HKCR \\\"LMMS Project (compressed)\\\" ") ELSE(WIN32) SET(CPACK_STRIP_FILES "bin/lmms;${PLUGIN_DIR}/*.so") From 64289f5953c7d6ee4cebfa72a926baf1d9868c37 Mon Sep 17 00:00:00 2001 From: tresf Date: Thu, 12 Jun 2014 02:17:03 -0400 Subject: [PATCH 36/61] nsis_branding.bmp, 256 color version to fix #831 --- data/nsis_branding.bmp | Bin 34338 -> 9742 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/data/nsis_branding.bmp b/data/nsis_branding.bmp index f617b5bccf81834be8e3fe7af4c4d1b7b0f3bc8b..a7e75e3c1a7a7e22126690fa289216e794f959a8 100644 GIT binary patch literal 9742 zcmchc3tW>`AIE>1y=g?*3*rT@paQ1kHJPP(0};6jB7q7F1>}x$)sgcOhNuJvlLQ-> z%BA514FMH($S^C(3XsrdOuPcQklR>$&ok)r`i^akUdHqJJZwAX;W^*^&hPo3^Z#$T z&70F9JKh@x7?XD?mjKo7NpPv9oFFsH-*ldPcLrQ9{0sDAAgGAU*Li)|Uwj48dDGxnI12HH4`NmENNhPb9_!B; zAT)Oo{Lf89@L6Mcd@}(~MdQH8pMm70!>}!y3ad+F;96*mt;J*ESo$^+lMlkH*bqs{ zN8ogIG#oCPAhc{4e6Q+Y$2VpOyljA&;+fcf*$~dW37}t{4EO80NJ(X3!&MXbm+8Z| zbQb7W7GO)65$F{Yu%~n${BG(YfHx1vzD!4Og(1>1jw0sD2iSbm5Psjz2Kz(?f^JPh zIv8Qe=4*%+i zoe#`VSbPCVzpcmTzuRDUlPM1U?ucDaKE$Ofm+{#HXCyVa;A7De9C_r5Yu9;5ezFne zH~84sZh_QhPkjD|4|YqI8f$1dlItwF*|QGw##4i z4?ipBl04t6XPe38T`nnZ5{aJG?b6rUbmN8mBiE5O^=;qq`1ttPyN@3?RA-vLJ};|r zfJ~;Ct7VyS0_QTXq$H2x5{VvFxeN{bQ*KD{w&6~USb`H3`bz*(A@^xy(K|io)vQdR+Z|=tvE78Dw&D_vMk}ETxw~AQUX^&1FH4 zVlXJOI5Llq?^jnhBxs!LSV`Wo#Jwle371eHAZQA?V&e&!jH{u#`u=0hbLk%?T4l4C zac7?j1kWhRlyJqzhcm+C?p9Y*k_`e^VqV_K^z`G5u&PIt@s)5Tr%?7{_!U$Ws=?qg zNF-FLDKVGMQ}N1y!=s|I zziSv2y_hMan*v(WHM99REEoGUt!ow0Mb9D7>C z91)jJ$TZJIqqqbDLD?{Mxbhc9vzW&T*kJgJ+IBUm%f(8MW3kdxHSe!Vfq<+)YIE&9 zc{2SFi=}bBOe&tr45qGLgo}_dtu!4cOe$pCLACW_ojgszSejmkp40j{k0eJqy_dzJ zYj}Mm>yRwnP*<1dLDb?gs^PbxmLwX)G>l8^;28T=ZOpq~j zXMJDA5J|@u#vhYBg-oTUxte8qkvMVU6}@{(a!dvoAa(}M>&BsnMk${Pf(|LzNG14zm6 zs)CvuDHdkU85POqvN?Hq++&HHLE!p(A6-XQqlcAib;j(x+4#RDLs_wKv@@I3eb^jQ z`N`uXCejTXRao)mN4T%|O6pAi{!~_#5Q!)*5h)oidR5M5Vp1&BU71-(s!aG z8gI~Sy-@tQxl4tRLXvTjEl)*={>wJ&>S*3MbyC<-Qc}EJQo^CQI7huld)4=~iR??K zzxx&IC6zXBqlHi<6B!rv1PCevbh|6l67oaBi~Kp0A`^-@Y&MUO5iTw}Z0wqg%JYD~ z$5Z!J8JARA{%j5CbYz~ibXLJJ71` zplV#FoJ-nyaowWQvZuoCOj7uWve`Q$K1}<$X0zVP%pyKNm&fPvO4#he+#UA%iV{pU z##eTU3NER%HO+kSnM%rLlwRb|Gr=wct%*9O30ywEoZ{jWvYZ|6qurDwn97Fjvt1<@ zWizAgRkAIjjEf|dWiAsu3J6p=pU);({Gyy4#w+p%&R9LfeQ=TVkl2ih8Qomu2@rf$ zP*6}_-osV+$r6*@Dih2;rBQf6UtChkW|pPGCW=e820Xh`US3d8NWgOVMVX%Cf*vTm z@&DP_Hy5$l0rM@DRYI~;q)K8GS2@3+;97ZZPS^yu+XEEf<-UhHTvF+iAX-3aRd=OT z##LT^EhjU~cy-o5#dkR@sd`*e$!)ipGMn}2RbF0{xoXPp7Wvx^*k?7lq|%Q3)i!0+ z(j?RC+Ls;!xacVOHfnQ8r7gQZ2&jBWaa}72n`C!gGsfy+><5=r`XGpQxK>zPNEV$m zHOeUpWKg@QUtCi0O}F_OpV=F2d#?5X|M0^8aY?1^S*wS5^;r`8hcGYwTYtHT&FXvo Mp#0MP2I?*FAJ0=Ung9R* literal 34338 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 From ebc9da8c71933956900a61f5145fb943a5571a36 Mon Sep 17 00:00:00 2001 From: Hannu Haahti Date: Thu, 12 Jun 2014 16:20:26 +0300 Subject: [PATCH 37/61] kicker: keep start note behaviour for old presets --- plugins/kicker/kicker.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/plugins/kicker/kicker.cpp b/plugins/kicker/kicker.cpp index 5fe9c6716..0a653a75f 100644 --- a/plugins/kicker/kicker.cpp +++ b/plugins/kicker/kicker.cpp @@ -108,6 +108,8 @@ void kickerInstrument::saveSettings( QDomDocument & _doc, void kickerInstrument::loadSettings( const QDomElement & _this ) { + m_versionModel.loadSettings( _this, "version" ); + m_startFreqModel.loadSettings( _this, "startfreq" ); m_endFreqModel.loadSettings( _this, "endfreq" ); m_decayModel.loadSettings( _this, "decay" ); @@ -126,18 +128,22 @@ void kickerInstrument::loadSettings( const QDomElement & _this ) m_clickModel.loadSettings( _this, "click" ); m_slopeModel.loadSettings( _this, "slope" ); m_startNoteModel.loadSettings( _this, "startnote" ); + if( m_versionModel.value() < 1 ) + { + m_startNoteModel.setValue( false ); + } m_endNoteModel.loadSettings( _this, "endnote" ); - m_versionModel.loadSettings( _this, "version" ); // Try to maintain backwards compatibility if( !_this.hasAttribute( "version" ) ) { + m_decayModel.setValue( m_decayModel.value() * 1.33f ); m_envModel.setValue( 1.0f ); m_slopeModel.setValue( 1.0f ); m_clickModel.setValue( 0.0f ); - m_versionModel.setValue( KICKER_PRESET_VERSION ); } + m_versionModel.setValue( KICKER_PRESET_VERSION ); } From a0d6115482173122d5693a4f09a119fc3743cf62 Mon Sep 17 00:00:00 2001 From: Vesa Date: Fri, 13 Jun 2014 19:43:37 +0300 Subject: [PATCH 38/61] A fix to IPH waiting code: don't wait for already finished notes, plus a bit of optimization --- include/InstrumentPlayHandle.h | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/include/InstrumentPlayHandle.h b/include/InstrumentPlayHandle.h index c2fd5c918..1e1b7d5da 100644 --- a/include/InstrumentPlayHandle.h +++ b/include/InstrumentPlayHandle.h @@ -56,14 +56,21 @@ public: // if not, we need to ensure that all our nph's have been processed first ConstNotePlayHandleList nphv = NotePlayHandle::nphsOfInstrumentTrack( m_instrument->instrumentTrack(), true ); - foreach( const NotePlayHandle * cnph, nphv ) + bool nphsLeft; + do { - NotePlayHandle * nph = const_cast( cnph ); - while( nph->state() != ThreadableJob::Done ) + nphsLeft = false; + foreach( const NotePlayHandle * cnph, nphv ) { - nph->process(); + NotePlayHandle * nph = const_cast( cnph ); + if( nph->state() != ThreadableJob::Done && ! nph->isFinished() ) + { + nphsLeft = true; + nph->process(); + } } } + while( nphsLeft ); m_instrument->play( _working_buffer ); } From c45163f9364ee7b5d8a9bf107c99442518446194 Mon Sep 17 00:00:00 2001 From: Vesa Date: Sat, 14 Jun 2014 14:32:15 +0300 Subject: [PATCH 39/61] LB302: one last fix... --- plugins/lb302/lb302.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/lb302/lb302.cpp b/plugins/lb302/lb302.cpp index dbfa61301..fce7c9f07 100644 --- a/plugins/lb302/lb302.cpp +++ b/plugins/lb302/lb302.cpp @@ -720,7 +720,7 @@ void lb302Synth::initSlide() void lb302Synth::playNote( NotePlayHandle * _n, sampleFrame * _working_buffer ) { - if( _n->isMasterNote() ) + if( _n->isMasterNote() || ( _n->hasParent() && _n->isReleased() ) ) { return; } From a172783cd05ff6f6fd90fea95aed59f0b6ea4ebc Mon Sep 17 00:00:00 2001 From: Vesa Date: Fri, 13 Jun 2014 12:01:15 +0300 Subject: [PATCH 40/61] 3-in-1 bugfix special Fixes bugs: #568, #289 and the incorrect timing for midi-noteoffs (see mailing list) --- include/NotePlayHandle.h | 3 ++- src/core/NotePlayHandle.cpp | 34 ++++++++++++++++++++++++++-------- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/include/NotePlayHandle.h b/include/NotePlayHandle.h index d2a5170b7..c564b1fc8 100644 --- a/include/NotePlayHandle.h +++ b/include/NotePlayHandle.h @@ -94,7 +94,7 @@ public: /*! Returns whether playback of note is finished and thus handle can be deleted */ virtual bool isFinished() const { - return m_released && framesLeft() <= 0; + return m_released && framesLeft() <= 0 && m_scheduledNoteOff < 0; } /*! Returns number of frames left for playback */ @@ -264,6 +264,7 @@ private: // played after release f_cnt_t m_releaseFramesDone; // number of frames done after // release of note + f_cnt_t m_scheduledNoteOff; // variable for scheduling noteoff at next period NotePlayHandleList m_subNotes; // used for chords and arpeggios volatile bool m_released; // indicates whether note is released bool m_hasParent; diff --git a/src/core/NotePlayHandle.cpp b/src/core/NotePlayHandle.cpp index db535474a..6c1b2f874 100644 --- a/src/core/NotePlayHandle.cpp +++ b/src/core/NotePlayHandle.cpp @@ -61,6 +61,7 @@ NotePlayHandle::NotePlayHandle( InstrumentTrack* instrumentTrack, m_framesBeforeRelease( 0 ), m_releaseFramesToDo( 0 ), m_releaseFramesDone( 0 ), + m_scheduledNoteOff( -1 ), m_released( false ), m_hasParent( parent != NULL ), m_hadChildren( false ), @@ -100,7 +101,7 @@ NotePlayHandle::NotePlayHandle( InstrumentTrack* instrumentTrack, m_instrumentTrack->midiNoteOn( *this ); } - if( !isMasterNote() || !instrumentTrack->isArpeggioEnabled() ) + if( hasParent() || !instrumentTrack->isArpeggioEnabled() ) { const int baseVelocity = m_instrumentTrack->midiPort()->baseVelocity(); @@ -182,6 +183,15 @@ int NotePlayHandle::midiKey() const void NotePlayHandle::play( sampleFrame * _working_buffer ) { + if( m_scheduledNoteOff >= 0 ) // always trigger scheduled noteoffs, because they're only scheduled if the note is released + { + m_instrumentTrack->processOutEvent( + MidiEvent( MidiNoteOff, midiChannel(), midiKey(), 0 ), + MidiTime::fromFrames( m_scheduledNoteOff, engine::framesPerTick() ), + m_scheduledNoteOff ); + m_scheduledNoteOff = -1; + } + if( m_muted ) { return; @@ -289,9 +299,9 @@ f_cnt_t NotePlayHandle::framesLeft() const { return m_framesBeforeRelease; } - else if( m_released && actualReleaseFramesToDo() >= m_releaseFramesDone ) + else if( m_released ) { - return m_framesBeforeRelease + actualReleaseFramesToDo() - m_releaseFramesDone; + return m_framesBeforeRelease + m_releaseFramesToDo - m_releaseFramesDone; } return m_frames+actualReleaseFramesToDo()-m_totalFramesPlayed; } @@ -330,15 +340,23 @@ void NotePlayHandle::noteOff( const f_cnt_t _s ) // then set some variables indicating release-state m_framesBeforeRelease = _s; - m_releaseFramesToDo = qMax( 0, m_instrumentTrack->m_soundShaping.releaseFrames() ); + m_releaseFramesToDo = qMax( 0, actualReleaseFramesToDo() ); if( hasParent() || !instrumentTrack()->isArpeggioEnabled() ) { // send MidiNoteOff event - m_instrumentTrack->processOutEvent( - MidiEvent( MidiNoteOff, midiChannel(), midiKey(), 0 ), - MidiTime::fromFrames( m_framesBeforeRelease, engine::framesPerTick() ), - _s ); + f_cnt_t realOffset = offset() + _s; // get actual frameoffset of release, in global time + if( realOffset < engine::mixer()->framesPerPeriod() ) // if release happens during this period, trigger midievent + { + m_instrumentTrack->processOutEvent( + MidiEvent( MidiNoteOff, midiChannel(), midiKey(), 0 ), + MidiTime::fromFrames( realOffset, engine::framesPerTick() ), + realOffset ); + } + else // if release flows over to next period, use m_scheduledNoteOff to trigger it later + { + m_scheduledNoteOff = realOffset - engine::mixer()->framesPerPeriod(); + } } // inform attached components about MIDI finished (used for recording in Piano Roll) From 3f19478b87bb9af2e0039444facafed78f6f083c Mon Sep 17 00:00:00 2001 From: Vesa Date: Fri, 13 Jun 2014 13:01:23 +0300 Subject: [PATCH 41/61] Further safeguards needed... --- src/core/NotePlayHandle.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/core/NotePlayHandle.cpp b/src/core/NotePlayHandle.cpp index 6c1b2f874..84933e431 100644 --- a/src/core/NotePlayHandle.cpp +++ b/src/core/NotePlayHandle.cpp @@ -119,7 +119,14 @@ NotePlayHandle::NotePlayHandle( InstrumentTrack* instrumentTrack, NotePlayHandle::~NotePlayHandle() { noteOff( 0 ); - + if( m_scheduledNoteOff >= 0 ) // ensure that scheduled noteoffs get triggered if somehow the nph got destructed prematurely + { + m_instrumentTrack->processOutEvent( + MidiEvent( MidiNoteOff, midiChannel(), midiKey(), 0 ), + MidiTime::fromFrames( m_scheduledNoteOff, engine::framesPerTick() ), + m_scheduledNoteOff ); + } + if( hasParent() == false ) { delete m_baseDetuning; @@ -199,7 +206,7 @@ void NotePlayHandle::play( sampleFrame * _working_buffer ) if( m_released == false && instrumentTrack()->isSustainPedalPressed() == false && - m_totalFramesPlayed + engine::mixer()->framesPerPeriod() >= m_frames ) + m_totalFramesPlayed + engine::mixer()->framesPerPeriod() > m_frames ) { noteOff( m_frames - m_totalFramesPlayed ); } From d1eb9886fd810807cf55df40813b986c92019ca9 Mon Sep 17 00:00:00 2001 From: Vesa Date: Fri, 13 Jun 2014 13:49:14 +0300 Subject: [PATCH 42/61] Make that 4: Fix stuck midi notes on changing master pitch --- include/InstrumentTrack.h | 2 ++ src/core/NotePlayHandle.cpp | 4 ++-- src/tracks/InstrumentTrack.cpp | 7 ++++++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/include/InstrumentTrack.h b/include/InstrumentTrack.h index b09ecaa6f..20200e1a7 100644 --- a/include/InstrumentTrack.h +++ b/include/InstrumentTrack.h @@ -160,6 +160,8 @@ public: { return &m_baseNoteModel; } + + int baseNote() const; Piano *pianoModel() { diff --git a/src/core/NotePlayHandle.cpp b/src/core/NotePlayHandle.cpp index 84933e431..8806d65e3 100644 --- a/src/core/NotePlayHandle.cpp +++ b/src/core/NotePlayHandle.cpp @@ -68,7 +68,7 @@ NotePlayHandle::NotePlayHandle( InstrumentTrack* instrumentTrack, m_muted( false ), m_bbTrack( NULL ), m_origTempo( engine::getSong()->getTempo() ), - m_origBaseNote( instrumentTrack->baseNoteModel()->value() ), + m_origBaseNote( instrumentTrack->baseNote() ), m_frequency( 0 ), m_unpitchedFrequency( 0 ), m_baseDetuning( NULL ), @@ -182,7 +182,7 @@ void NotePlayHandle::setPanning( panning_t panning ) int NotePlayHandle::midiKey() const { - return key() - m_origBaseNote + instrumentTrack()->baseNoteModel()->value(); + return key() - m_origBaseNote + instrumentTrack()->baseNote(); } diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 532431e6c..e661f4f4c 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -135,6 +135,11 @@ InstrumentTrack::InstrumentTrack( TrackContainer* tc ) : } +int InstrumentTrack::baseNote() const +{ + return m_baseNoteModel.value() - engine::getSong()->masterPitch(); +} + InstrumentTrack::~InstrumentTrack() @@ -537,7 +542,7 @@ void InstrumentTrack::updatePitchRange() int InstrumentTrack::masterKey( int _midi_key ) const { - int key = m_baseNoteModel.value() - engine::getSong()->masterPitch(); + int key = baseNote(); return tLimit( _midi_key - ( key - DefaultKey ), 0, NumKeys ); } From 9c584778d2076dd379bf639268da6139bd1cd1f9 Mon Sep 17 00:00:00 2001 From: Vesa Date: Fri, 13 Jun 2014 15:40:58 +0300 Subject: [PATCH 43/61] 5th: fix #563 - do not destroy IPH's on "All Notes Off" MIDI commands --- include/InstrumentTrack.h | 2 +- include/Mixer.h | 2 +- src/core/Mixer.cpp | 4 ++-- src/tracks/InstrumentTrack.cpp | 12 ++++++------ 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/include/InstrumentTrack.h b/include/InstrumentTrack.h index 20200e1a7..ea10447c5 100644 --- a/include/InstrumentTrack.h +++ b/include/InstrumentTrack.h @@ -74,7 +74,7 @@ public: virtual void processInEvent( const MidiEvent& event, const MidiTime& time = MidiTime(), f_cnt_t offset = 0 ); virtual void processOutEvent( const MidiEvent& event, const MidiTime& time = MidiTime(), f_cnt_t offset = 0 ); // silence all running notes played by this track - void silenceAllNotes(); + void silenceAllNotes( bool removeIPH = false ); bool isSustainPedalPressed() const { diff --git a/include/Mixer.h b/include/Mixer.h index 9a20cae5a..7007e1801 100644 --- a/include/Mixer.h +++ b/include/Mixer.h @@ -229,7 +229,7 @@ public: return m_playHandles; } - void removePlayHandles( track * _track ); + void removePlayHandles( track * _track, bool removeIPHs = true ); bool hasNotePlayHandles(); diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index 9c35ee852..c9fd9b83c 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -686,13 +686,13 @@ void Mixer::removePlayHandle( PlayHandle * _ph ) -void Mixer::removePlayHandles( track * _track ) +void Mixer::removePlayHandles( track * _track, bool removeIPHs ) { lock(); PlayHandleList::Iterator it = m_playHandles.begin(); while( it != m_playHandles.end() ) { - if( ( *it )->isFromTrack( _track ) ) + if( ( *it )->isFromTrack( _track ) && ( removeIPHs || ( *it )->type() != PlayHandle::TypeInstrumentPlayHandle ) ) { delete *it; it = m_playHandles.erase( it ); diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index e661f4f4c..be2de2497 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -144,8 +144,8 @@ int InstrumentTrack::baseNote() const InstrumentTrack::~InstrumentTrack() { - // kill all running notes - silenceAllNotes(); + // kill all running notes and the iph + silenceAllNotes( true ); // now we're save deleting the instrument delete m_instrument; @@ -402,7 +402,7 @@ void InstrumentTrack::processOutEvent( const MidiEvent& event, const MidiTime& t -void InstrumentTrack::silenceAllNotes() +void InstrumentTrack::silenceAllNotes( bool removeIPH ) { engine::mixer()->lock(); for( int i = 0; i < NumKeys; ++i ) @@ -413,7 +413,7 @@ void InstrumentTrack::silenceAllNotes() // invalidate all NotePlayHandles linked to this track m_processHandles.clear(); - engine::mixer()->removePlayHandles( this ); + engine::mixer()->removePlayHandles( this, removeIPH ); engine::mixer()->unlock(); } @@ -700,7 +700,7 @@ void InstrumentTrack::saveTrackSpecificSettings( QDomDocument& doc, QDomElement void InstrumentTrack::loadTrackSpecificSettings( const QDomElement & thisElement ) { - silenceAllNotes(); + silenceAllNotes( true ); engine::mixer()->lock(); @@ -776,7 +776,7 @@ void InstrumentTrack::loadTrackSpecificSettings( const QDomElement & thisElement Instrument * InstrumentTrack::loadInstrument( const QString & _plugin_name ) { - silenceAllNotes(); + silenceAllNotes( true ); engine::mixer()->lock(); delete m_instrument; From 3319380cf65ae50292816a31c2be3d46c4cf0c32 Mon Sep 17 00:00:00 2001 From: Vesa Date: Thu, 12 Jun 2014 22:34:32 +0300 Subject: [PATCH 44/61] FxMixer: Fix channel delete --- include/FxMixer.h | 4 ++-- src/core/FxMixer.cpp | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/FxMixer.h b/include/FxMixer.h index 7cecb7803..f8a7c86f6 100644 --- a/include/FxMixer.h +++ b/include/FxMixer.h @@ -22,8 +22,8 @@ * */ -#ifndef _FX_MIXER_H -#define _FX_MIXER_H +#ifndef FX_MIXER_H +#define FX_MIXER_H #include "Model.h" #include "Mixer.h" diff --git a/src/core/FxMixer.cpp b/src/core/FxMixer.cpp index d2c79a972..155be30cd 100644 --- a/src/core/FxMixer.cpp +++ b/src/core/FxMixer.cpp @@ -207,13 +207,13 @@ void FxMixer::deleteChannel(int index) } // delete all of this channel's sends and receives - for(int i=0; im_sends.size(); ++i) + while( ! m_fxChannels[index]->m_sends.isEmpty() ) { - deleteChannelSend(index, m_fxChannels[index]->m_sends[i]); + deleteChannelSend( index, m_fxChannels[index]->m_sends.first() ); } - for(int i=0; im_receives.size(); ++i) + while( ! m_fxChannels[index]->m_receives.isEmpty() ) { - deleteChannelSend(m_fxChannels[index]->m_receives[i], index); + deleteChannelSend( m_fxChannels[index]->m_receives.first(), index ); } for(int i=0; i Date: Sat, 14 Jun 2014 14:53:22 +0300 Subject: [PATCH 45/61] FxMixer: fix crashes on modifying sends Added a mutex so that the GUI thread can't change the sends around during the rendering loop. --- include/FxMixer.h | 1 + src/core/FxMixer.cpp | 12 ++++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/include/FxMixer.h b/include/FxMixer.h index f8a7c86f6..8136d9ed4 100644 --- a/include/FxMixer.h +++ b/include/FxMixer.h @@ -140,6 +140,7 @@ private: // make sure we have at least num channels void allocateChannelsTo(int num); + QMutex m_sendsMutex; void addChannelLeaf( int _ch, sampleFrame * _buf ); diff --git a/src/core/FxMixer.cpp b/src/core/FxMixer.cpp index 155be30cd..02a6d3d8a 100644 --- a/src/core/FxMixer.cpp +++ b/src/core/FxMixer.cpp @@ -252,7 +252,7 @@ void FxMixer::moveChannelLeft(int index) { return; } - + m_sendsMutex.lock(); // channels to swap int a = index - 1, b = index; @@ -314,6 +314,7 @@ void FxMixer::moveChannelLeft(int index) FxChannel * tmpChannel = m_fxChannels[a]; m_fxChannels[a] = m_fxChannels[b]; m_fxChannels[b] = tmpChannel; + m_sendsMutex.unlock(); } @@ -340,7 +341,7 @@ void FxMixer::createChannelSend(fx_ch_t fromChannel, fx_ch_t toChannel, } // connection does not exist. create a new one - + m_sendsMutex.lock(); // add to from's sends from->m_sends.push_back(toChannel); from->m_sendAmount.push_back(new FloatModel(amount, 0, 1, 0.001, NULL, @@ -348,7 +349,7 @@ void FxMixer::createChannelSend(fx_ch_t fromChannel, fx_ch_t toChannel, // add to to's receives m_fxChannels[toChannel]->m_receives.push_back(fromChannel); - + m_sendsMutex.unlock(); } @@ -359,7 +360,7 @@ void FxMixer::deleteChannelSend(fx_ch_t fromChannel, fx_ch_t toChannel) // delete the send FxChannel * from = m_fxChannels[fromChannel]; FxChannel * to = m_fxChannels[toChannel]; - + m_sendsMutex.lock(); // find and delete the send entry for(int i=0; im_sends.size(); ++i) { if( from->m_sends[i] == toChannel ) @@ -382,6 +383,7 @@ void FxMixer::deleteChannelSend(fx_ch_t fromChannel, fx_ch_t toChannel) break; } } + m_sendsMutex.unlock(); } @@ -480,6 +482,7 @@ void FxMixer::masterMix( sampleFrame * _buf ) // and add all channels to job list that have no dependencies // when the channel completes it will check its parent to see if it needs // to be processed. + m_sendsMutex.lock(); MixerWorkerThread::resetJobQueue( MixerWorkerThread::JobQueue::Dynamic ); addChannelLeaf( 0, _buf ); while( m_fxChannels[0]->state() != ThreadableJob::Done ) @@ -487,6 +490,7 @@ void FxMixer::masterMix( sampleFrame * _buf ) MixerWorkerThread::startAndWaitForJobs(); } //m_fxChannels[0]->doProcessing( NULL ); + m_sendsMutex.unlock(); const float v = m_fxChannels[0]->m_volumeModel.value(); MixHelpers::addMultiplied( _buf, m_fxChannels[0]->m_buffer, v, fpp ); From e733042cdbc29b3837448b36db190c6df1e83d35 Mon Sep 17 00:00:00 2001 From: Vesa Date: Sat, 14 Jun 2014 17:42:00 +0300 Subject: [PATCH 46/61] FxMixer: clearChannel had the same erroneous for loop as deleteChannel --- src/core/FxMixer.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/core/FxMixer.cpp b/src/core/FxMixer.cpp index 02a6d3d8a..961d6f8d6 100644 --- a/src/core/FxMixer.cpp +++ b/src/core/FxMixer.cpp @@ -538,9 +538,9 @@ void FxMixer::clearChannel(fx_ch_t index) if( index > 0) { // delete existing sends - for( int i=0; im_sends.size(); ++i) + while( ! ch->m_sends.isEmpty() ) { - deleteChannelSend(index, ch->m_sends[i]); + deleteChannelSend( index, ch->m_sends.first() ); } // add send to master @@ -548,11 +548,10 @@ void FxMixer::clearChannel(fx_ch_t index) } // delete receives - for( int i=0; im_receives.size(); ++i) + while( ! ch->m_receives.isEmpty() ) { - deleteChannelSend(ch->m_receives[i], index); + deleteChannelSend( ch->m_receives.first(), index ); } - } void FxMixer::saveSettings( QDomDocument & _doc, QDomElement & _this ) From ad1c6957b0c19e6150fbc0ffb9dd6e63e50a2f1d Mon Sep 17 00:00:00 2001 From: Vesa Date: Sat, 14 Jun 2014 18:36:17 +0300 Subject: [PATCH 47/61] AutomatableModel: prevent linking of model to itself There's no need to ever link a model to itself, allowing it can cause weird issues and crashes, plus it's easy to do by accident if you start a ctrl-drag and end it while still on the same widget --- src/core/AutomatableModel.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/AutomatableModel.cpp b/src/core/AutomatableModel.cpp index b11374e9a..e8e22e5c2 100644 --- a/src/core/AutomatableModel.cpp +++ b/src/core/AutomatableModel.cpp @@ -394,7 +394,7 @@ float AutomatableModel::fittedValue( float value ) const void AutomatableModel::linkModel( AutomatableModel* model ) { - if( !m_linkedModels.contains( model ) ) + if( !m_linkedModels.contains( model ) && model != this ) { m_linkedModels.push_back( model ); m_hasLinkedModels = true; @@ -426,8 +426,8 @@ void AutomatableModel::unlinkModel( AutomatableModel* model ) void AutomatableModel::linkModels( AutomatableModel* model1, AutomatableModel* model2 ) { - model1->linkModel( model2 ); - model2->linkModel( model1 ); + model1->linkModel( model2 ); + model2->linkModel( model1 ); } From 585f8b6d93f2630416f9ce52eef8ba5a075e128b Mon Sep 17 00:00:00 2001 From: Vesa Date: Sat, 14 Jun 2014 20:36:21 +0300 Subject: [PATCH 48/61] SF2 player: fix playback issues Changing the velocity after noteon doesn't really seem to work on fluidsynth (may be dependent on soundfont file) - seems like the panning changes when velocity is changed. So I disabled that, after which everything works fine. --- plugins/sf2_player/sf2_player.cpp | 6 +++--- plugins/sf2_player/sf2_player.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/sf2_player/sf2_player.cpp b/plugins/sf2_player/sf2_player.cpp index 55c199ca0..7ce0219fc 100644 --- a/plugins/sf2_player/sf2_player.cpp +++ b/plugins/sf2_player/sf2_player.cpp @@ -542,7 +542,7 @@ void sf2Instrument::playNote( NotePlayHandle * _n, sampleFrame * ) { SF2PluginData * pluginData = new SF2PluginData; pluginData->midiNote = midiNote; - pluginData->lastPanning = -1; + pluginData->lastPanning = 0; pluginData->lastVelocity = 127; pluginData->fluidVoice = NULL; @@ -588,7 +588,7 @@ void sf2Instrument::playNote( NotePlayHandle * _n, sampleFrame * ) m_notesRunningMutex.unlock(); } - SF2PluginData * pluginData = static_cast( +/* SF2PluginData * pluginData = static_cast( _n->m_pluginData ); #ifdef SOMEONE_FIXED_PER_NOTE_PANNING if( pluginData->fluidVoice && @@ -620,7 +620,7 @@ void sf2Instrument::playNote( NotePlayHandle * _n, sampleFrame * ) m_synthMutex.unlock(); pluginData->lastVelocity = currentVelocity; - } + }*/ } diff --git a/plugins/sf2_player/sf2_player.h b/plugins/sf2_player/sf2_player.h index 5c2f5beb8..728a717cc 100644 --- a/plugins/sf2_player/sf2_player.h +++ b/plugins/sf2_player/sf2_player.h @@ -24,8 +24,8 @@ */ -#ifndef _SF2_PLAYER_H -#define _SF2_PLAYER_H +#ifndef SF2_PLAYER_H +#define SF2_PLAYER_H #include From 8a2aeaa5957bfb94c79c58c64c03d57e2b4e003d Mon Sep 17 00:00:00 2001 From: Vesa Date: Sun, 15 Jun 2014 15:58:07 +0300 Subject: [PATCH 49/61] Monstro updates - Fix FM (use PM-based FM to prevent pitch drift) - Bunch of codepath optimizations - Somewhat saner min/max values for PW --- plugins/monstro/Monstro.cpp | 218 ++++++++++++++++++++++-------------- plugins/monstro/Monstro.h | 8 ++ 2 files changed, 143 insertions(+), 83 deletions(-) diff --git a/plugins/monstro/Monstro.cpp b/plugins/monstro/Monstro.cpp index f38b58400..96dff60bf 100644 --- a/plugins/monstro/Monstro.cpp +++ b/plugins/monstro/Monstro.cpp @@ -89,7 +89,7 @@ MonstroSynth::MonstroSynth( MonstroInstrument * _i, NotePlayHandle * _nph, m_lfo1_phase = 0.0f; m_lfo2_phase = 0.0f; - + m_lfo1_s = Oscillator::noiseSample( 0.0f ); m_lfo2_s = Oscillator::noiseSample( 0.0f ); @@ -103,15 +103,17 @@ MonstroSynth::MonstroSynth( MonstroInstrument * _i, NotePlayHandle * _nph, m_invert2r = false; m_invert3l = false; m_invert3r = false; - + m_integrator = 0.5f - ( 0.5f - INTEGRATOR ) * 44100.0f / m_samplerate; - + m_counter2l = 0; m_counter2r = 0; m_counter3l = 0; m_counter3r = 0; m_counterMax = ( m_samplerate * 10 ) / 44100; - + + m_minfreq_pd = 1.0f / ( m_samplerate / MIN_FREQ ); + m_fmCorrection = 44100.f / m_samplerate * FM_AMOUNT; } @@ -127,31 +129,35 @@ MonstroSynth::~MonstroSynth() void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) { + float modtmp; // temp variable for freq modulation // macros for modulating with env/lfos #define modulatefreq( car, mod ) \ - if( mod##_e1 != 0.0f ) car = qBound( MIN_FREQ, car * powf( 2.0f, m_env1_buf[f] * mod##_e1 * 2.0f ), MAX_FREQ ); \ - if( mod##_e2 != 0.0f ) car = qBound( MIN_FREQ, car * powf( 2.0f, m_env2_buf[f] * mod##_e2 * 2.0f ), MAX_FREQ ); \ - if( mod##_l1 != 0.0f ) car = qBound( MIN_FREQ, car * powf( 2.0f, m_lfo1_buf[f] * mod##_l1 ), MAX_FREQ ); \ - if( mod##_l2 != 0.0f ) car = qBound( MIN_FREQ, car * powf( 2.0f, m_lfo2_buf[f] * mod##_l2 ), MAX_FREQ ); + modtmp = 0.0f; \ + if( mod##_e1 != 0.0f ) modtmp += m_env1_buf[f] * mod##_e1; \ + if( mod##_e2 != 0.0f ) modtmp += m_env2_buf[f] * mod##_e2; \ + if( mod##_l1 != 0.0f ) modtmp += m_lfo1_buf[f] * mod##_l1; \ + if( mod##_l2 != 0.0f ) modtmp += m_lfo2_buf[f] * mod##_l2; \ + car = qBound( MIN_FREQ, car * powf( 2.0f, modtmp ), MAX_FREQ ); #define modulateabs( car, mod ) \ - if( mod##_e1 != 0.0f ) car = qBound( 0.0f, car + mod##_e1 * m_env1_buf[f], 1.0f ); \ - if( mod##_e2 != 0.0f ) car = qBound( 0.0f, car + mod##_e2 * m_env2_buf[f], 1.0f ); \ - if( mod##_l1 != 0.0f ) car = qBound( 0.0f, car + mod##_l1 * 0.5f * m_lfo1_buf[f], 1.0f ); \ - if( mod##_l2 != 0.0f ) car = qBound( 0.0f, car + mod##_l2 * 0.5f * m_lfo2_buf[f], 1.0f ); + if( mod##_e1 != 0.0f ) car += m_env1_buf[f] * mod##_e1; \ + if( mod##_e2 != 0.0f ) car += m_env2_buf[f] * mod##_e2; \ + if( mod##_l1 != 0.0f ) car += m_lfo1_buf[f] * mod##_l1; \ + if( mod##_l2 != 0.0f ) car += m_lfo2_buf[f] * mod##_l2; \ + car = qBound( 0.0f, car, 1.0f ); #define modulatephs( car, mod ) \ - if( mod##_e1 != 0.0f ) car += qBound( -1.0f, ( mod##_e1 * m_env1_buf[f] ), 1.0f ); \ - if( mod##_e2 != 0.0f ) car += qBound( -1.0f, ( mod##_e2 * m_env2_buf[f] ), 1.0f ); \ - if( mod##_l1 != 0.0f ) car += ( mod##_l1 * 0.5f * m_lfo1_buf[f] ); \ - if( mod##_l2 != 0.0f ) car += ( mod##_l2 * 0.5f * m_lfo2_buf[f] ); + if( mod##_e1 != 0.0f ) car += m_env1_buf[f] * mod##_e1; \ + if( mod##_e2 != 0.0f ) car += m_env2_buf[f] * mod##_e2; \ + if( mod##_l1 != 0.0f ) car += m_lfo1_buf[f] * mod##_l1; \ + if( mod##_l2 != 0.0f ) car += m_lfo2_buf[f] * mod##_l2; #define modulatevol( car, mod ) \ if( mod##_e1 > 0.0f ) car = qBound( -MODCLIP, car * ( 1.0f - mod##_e1 + mod##_e1 * m_env1_buf[f] ), MODCLIP ); \ if( mod##_e1 < 0.0f ) car = qBound( -MODCLIP, car * ( 1.0f + mod##_e1 * m_env1_buf[f] ), MODCLIP ); \ if( mod##_e2 > 0.0f ) car = qBound( -MODCLIP, car * ( 1.0f - mod##_e2 + mod##_e2 * m_env2_buf[f] ), MODCLIP ); \ if( mod##_e2 < 0.0f ) car = qBound( -MODCLIP, car * ( 1.0f + mod##_e2 * m_env2_buf[f] ), MODCLIP ); \ - if( mod##_l1 != 0.0f ) car = qBound( -MODCLIP, car * ( 1.0f + mod##_l1 * m_lfo1_buf[f] ), MODCLIP ); \ + if( mod##_l1 != 0.0f ) car = qBound( -MODCLIP, car * ( 1.0f + mod##_l1 * m_lfo1_buf[f] ), MODCLIP ); \ if( mod##_l2 != 0.0f ) car = qBound( -MODCLIP, car * ( 1.0f + mod##_l2 * m_lfo2_buf[f] ), MODCLIP ); // pre-render env's and lfo's @@ -162,32 +168,36 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) const float pw = ( m_parent->m_osc1Pw.value() / 100.0f ); const float o1pw_e1 = ( m_parent->m_pw1env1.value() ); const float o1pw_e2 = ( m_parent->m_pw1env2.value() ); - const float o1pw_l1 = ( m_parent->m_pw1lfo1.value() ); - const float o1pw_l2 = ( m_parent->m_pw1lfo2.value() ); + const float o1pw_l1 = ( m_parent->m_pw1lfo1.value() * 0.5f ); + const float o1pw_l2 = ( m_parent->m_pw1lfo2.value() * 0.5f ); + const bool o1pw_mod = o1pw_e1 != 0.0f || o1pw_e2 != 0.0f || o1pw_l1 != 0.0f || o1pw_l2 != 0.0f; // get phases const float o1lpo = m_parent->m_osc1l_po; const float o1rpo = m_parent->m_osc1r_po; const float o1p_e1 = ( m_parent->m_phs1env1.value() ); const float o1p_e2 = ( m_parent->m_phs1env2.value() ); - const float o1p_l1 = ( m_parent->m_phs1lfo1.value() ); - const float o1p_l2 = ( m_parent->m_phs1lfo2.value() ); + const float o1p_l1 = ( m_parent->m_phs1lfo1.value() * 0.5f ); + const float o1p_l2 = ( m_parent->m_phs1lfo2.value() * 0.5f ); + const bool o1p_mod = o1p_e1 != 0.0f || o1p_e2 != 0.0f || o1p_l1 != 0.0f || o1p_l2 != 0.0f; // get pitch const float o1lfb = ( m_parent->m_osc1l_freq * m_nph->frequency() ); const float o1rfb = ( m_parent->m_osc1r_freq * m_nph->frequency() ); - const float o1f_e1 = ( m_parent->m_pit1env1.value() ); - const float o1f_e2 = ( m_parent->m_pit1env2.value() ); + const float o1f_e1 = ( m_parent->m_pit1env1.value() * 2.0f ); + const float o1f_e2 = ( m_parent->m_pit1env2.value() * 2.0f ); const float o1f_l1 = ( m_parent->m_pit1lfo1.value() ); const float o1f_l2 = ( m_parent->m_pit1lfo2.value() ); + const bool o1f_mod = o1f_e1 != 0.0f || o1f_e2 != 0.0f || o1f_l1 != 0.0f || o1f_l2 != 0.0f; // get volumes const float o1lv = m_parent->m_osc1l_vol; const float o1rv = m_parent->m_osc1r_vol; - const float o1v_e1 = ( m_parent->m_vol1env1.value() ); - const float o1v_e2 = ( m_parent->m_vol1env2.value() ); + const float o1v_e1 = ( m_parent->m_vol1env1.value() * 2.0f ); + const float o1v_e2 = ( m_parent->m_vol1env2.value() * 2.0f ); const float o1v_l1 = ( m_parent->m_vol1lfo1.value() ); const float o1v_l2 = ( m_parent->m_vol1lfo2.value() ); + const bool o1v_mod = o1v_e1 != 0.0f || o1v_e2 != 0.0f || o1v_l1 != 0.0f || o1v_l2 != 0.0f; // update osc2 // get waveform @@ -198,25 +208,27 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) const float o2rpo = m_parent->m_osc2r_po; const float o2p_e1 = ( m_parent->m_phs2env1.value() ); const float o2p_e2 = ( m_parent->m_phs2env2.value() ); - const float o2p_l1 = ( m_parent->m_phs2lfo1.value() ); - const float o2p_l2 = ( m_parent->m_phs2lfo2.value() ); + const float o2p_l1 = ( m_parent->m_phs2lfo1.value() * 0.5f ); + const float o2p_l2 = ( m_parent->m_phs2lfo2.value() * 0.5f ); + const bool o2p_mod = o2p_e1 != 0.0f || o2p_e2 != 0.0f || o2p_l1 != 0.0f || o2p_l2 != 0.0f; // get pitch const float o2lfb = ( m_parent->m_osc2l_freq * m_nph->frequency() ); const float o2rfb = ( m_parent->m_osc2r_freq * m_nph->frequency() ); - const float o2f_e1 = ( m_parent->m_pit2env1.value() ); - const float o2f_e2 = ( m_parent->m_pit2env2.value() ); + const float o2f_e1 = ( m_parent->m_pit2env1.value() * 2.0f ); + const float o2f_e2 = ( m_parent->m_pit2env2.value() * 2.0f ); const float o2f_l1 = ( m_parent->m_pit2lfo1.value() ); const float o2f_l2 = ( m_parent->m_pit2lfo2.value() ); + const bool o2f_mod = o2f_e1 != 0.0f || o2f_e2 != 0.0f || o2f_l1 != 0.0f || o2f_l2 != 0.0f; // get volumes const float o2lv = m_parent->m_osc2l_vol; const float o2rv = m_parent->m_osc2r_vol; const float o2v_e1 = ( m_parent->m_vol2env1.value() ); const float o2v_e2 = ( m_parent->m_vol2env2.value() ); - const float o2v_l1 = ( m_parent->m_vol2lfo2.value() ); + const float o2v_l1 = ( m_parent->m_vol2lfo1.value() ); const float o2v_l2 = ( m_parent->m_vol2lfo2.value() ); - + const bool o2v_mod = o2v_e1 != 0.0f || o2v_e2 != 0.0f || o2v_l1 != 0.0f || o2v_l2 != 0.0f; // update osc3 @@ -229,8 +241,9 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) const float o3rpo = m_parent->m_osc3r_po; const float o3p_e1 = ( m_parent->m_phs3env1.value() ); const float o3p_e2 = ( m_parent->m_phs3env2.value() ); - const float o3p_l1 = ( m_parent->m_phs3lfo1.value() ); - const float o3p_l2 = ( m_parent->m_phs3lfo2.value() ); + const float o3p_l1 = ( m_parent->m_phs3lfo1.value() * 0.5f ); + const float o3p_l2 = ( m_parent->m_phs3lfo2.value() * 0.5f ); + const bool o3p_mod = o3p_e1 != 0.0f || o3p_e2 != 0.0f || o3p_l1 != 0.0f || o3p_l2 != 0.0f; // get pitch modulators const float o3fb = ( m_parent->m_osc3_freq * m_nph->frequency() ); @@ -238,6 +251,7 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) const float o3f_e2 = ( m_parent->m_pit3env2.value() ); const float o3f_l1 = ( m_parent->m_pit3lfo1.value() ); const float o3f_l2 = ( m_parent->m_pit3lfo2.value() ); + const bool o3f_mod = o3f_e1 != 0.0f || o3f_e2 != 0.0f || o3f_l1 != 0.0f || o3f_l2 != 0.0f; // get volumes const float o3lv = m_parent->m_osc3l_vol; @@ -246,13 +260,15 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) const float o3v_e2 = ( m_parent->m_vol3env2.value() ); const float o3v_l1 = ( m_parent->m_vol3lfo1.value() ); const float o3v_l2 = ( m_parent->m_vol3lfo2.value() ); + const bool o3v_mod = o3v_e1 != 0.0f || o3v_e2 != 0.0f || o3v_l1 != 0.0f || o3v_l2 != 0.0f; // get sub const float o3sub = ( m_parent->m_osc3Sub.value() + 100.0f ) / 200.0f; const float o3s_e1 = ( m_parent->m_sub3env1.value() ); const float o3s_e2 = ( m_parent->m_sub3env2.value() ); - const float o3s_l1 = ( m_parent->m_sub3lfo1.value() ); - const float o3s_l2 = ( m_parent->m_sub3lfo2.value() ); + const float o3s_l1 = ( m_parent->m_sub3lfo1.value() * 0.5f ); + const float o3s_l2 = ( m_parent->m_sub3lfo2.value() * 0.5f ); + const bool o3s_mod = o3s_e1 != 0.0f || o3s_e2 != 0.0f || o3s_l1 != 0.0f || o3s_l2 != 0.0f; //o2-o3 modulation @@ -284,12 +300,12 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) float pd_r; float len_l; float len_r; - + // osc1 vars float o1l_f; float o1r_f; float o1l_p = m_osc1l_phase + o1lpo; // we add phase offset here so we don't have to do it every frame - float o1r_p = m_osc1r_phase + o1rpo; // then substract it again after loop... + float o1r_p = m_osc1r_phase + o1rpo; // then substract it again after loop... float o1_pw; // osc2 vars @@ -327,18 +343,27 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) // calc and mod frequencies o1l_f = o1lfb; o1r_f = o1rfb; - modulatefreq( o1l_f, o1f ) - modulatefreq( o1r_f, o1f ) - + if( o1f_mod ) + { + modulatefreq( o1l_f, o1f ) + modulatefreq( o1r_f, o1f ) + } // calc and modulate pulse o1_pw = pw; - modulateabs( o1_pw, o1pw ) + if( o1pw_mod ) + { + modulateabs( o1_pw, o1pw ) + o1_pw = qBound( PW_MIN, o1_pw, PW_MAX ); + } // calc and modulate phase leftph = o1l_p; - rightph = o1r_p; - modulatephs( leftph, o1p ) - modulatephs( rightph, o1p ) + rightph = o1r_p; + if( o1p_mod ) + { + modulatephs( leftph, o1p ) + modulatephs( rightph, o1p ) + } // pulse wave osc sample_t O1L = ( absFraction( leftph ) < o1_pw ) ? 1.0f : -1.0f; @@ -395,7 +420,7 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) { if( O1L < m_osc1l_last ) { m_invert3l = !m_invert3l; m_counter3l = m_counterMax; } if( O1R < m_osc1r_last ) { m_invert3r = !m_invert3r; m_counter3r = m_counterMax; } - } + } } // update last before signal is touched @@ -412,8 +437,11 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) // modulate volume O1L *= o1lv; O1R *= o1rv; - modulatevol( O1L, o1v ) - modulatevol( O1R, o1v ) + if( o1v_mod ) + { + modulatevol( O1L, o1v ) + modulatevol( O1R, o1v ) + } // update osc1 phase working variable o1l_p += 1.0f / ( static_cast( m_samplerate ) / o1l_f ); @@ -428,14 +456,20 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) // calc and mod frequencies o2l_f = o2lfb; o2r_f = o2rfb; - modulatefreq( o2l_f, o2f ) - modulatefreq( o2r_f, o2f ) + if( o2f_mod ) + { + modulatefreq( o2l_f, o2f ) + modulatefreq( o2r_f, o2f ) + } // calc and modulate phase leftph = o2l_p; - rightph = o2r_p; - modulatephs( leftph, o2p ) - modulatephs( rightph, o2p ) + rightph = o2r_p; + if( o2p_mod ) + { + modulatephs( leftph, o2p ) + modulatephs( rightph, o2p ) + } leftph = absFraction( leftph ); rightph = absFraction( rightph ); @@ -456,8 +490,11 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) // modulate volume O2L *= o2lv; O2R *= o2rv; - modulatevol( O2L, o2v ) - modulatevol( O2R, o2v ) + if( o2v_mod ) + { + modulatevol( O2L, o2v ) + modulatevol( O2R, o2v ) + } // reverse sync - invert waveforms when needed if( m_invert2l ) O2L *= -1.0; @@ -478,26 +515,25 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) // calc and mod frequencies o3l_f = o3fb; o3r_f = o3fb; - modulatefreq( o3l_f, o3f ) - modulatefreq( o3r_f, o3f ) - // o2 modulation? - if( omod == MOD_FM ) + if( o3f_mod ) { - o3l_f = qBound( MIN_FREQ, o3l_f * powf( 2.0f, O2L ), MAX_FREQ ); - o3r_f = qBound( MIN_FREQ, o3r_f * powf( 2.0f, O2R ), MAX_FREQ ); + modulatefreq( o3l_f, o3f ) + modulatefreq( o3r_f, o3f ) } - // calc and modulate phase leftph = o3l_p; - rightph = o3r_p; - modulatephs( leftph, o3p ) - modulatephs( rightph, o3p ) - + rightph = o3r_p; + if( o3p_mod ) + { + modulatephs( leftph, o3p ) + modulatephs( rightph, o3p ) + } + // o2 modulation? if( omod == MOD_PM ) { - leftph += O2L/2; - rightph += O2R/2; + leftph += O2L * 0.5f; + rightph += O2R * 0.5f; } leftph = absFraction( leftph ); rightph = absFraction( rightph ); @@ -523,7 +559,10 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) // calc and modulate sub sub = o3sub; - modulateabs( sub, o3s ) + if( o3s_mod ) + { + modulateabs( sub, o3s ) + } sample_t O3L = linearInterpolate( O3AL, O3BL, sub ); sample_t O3R = linearInterpolate( O3AR, O3BR, sub ); @@ -531,8 +570,11 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) // modulate volume O3L *= o3lv; O3R *= o3rv; - modulatevol( O3L, o3v ) - modulatevol( O3R, o3v ) + if( o3v_mod ) + { + modulatevol( O3L, o3v ) + modulatevol( O3R, o3v ) + } // o2 modulation? if( omod == MOD_AM ) { @@ -547,8 +589,16 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) // update osc3 phases m_ph3l_last = leftph; m_ph3r_last = rightph; - o3l_p += 1.0f / ( static_cast( m_samplerate ) / o3l_f ); - o3r_p += 1.0f / ( static_cast( m_samplerate ) / o3r_f ); + len_l = 1.0f / ( static_cast( m_samplerate ) / o3l_f ); + len_r = 1.0f / ( static_cast( m_samplerate ) / o3r_f ); + // handle FM as PM + if( omod == MOD_FM ) + { + len_l += O2L * m_fmCorrection; + len_r += O2R * m_fmCorrection; + } + o3l_p += len_l; + o3r_p += len_r; // integrator - very simple filter sample_t L = O1L + O3L + ( omod == MOD_MIX ? O2L : 0.0f ); @@ -560,7 +610,7 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) m_l_last = L; m_r_last = R; } - + // update phases m_osc1l_phase = absFraction( o1l_p - o1lpo ); m_osc1r_phase = absFraction( o1r_p - o1rpo ); @@ -568,7 +618,7 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) m_osc2r_phase = absFraction( o2r_p - o2rpo ); m_osc3l_phase = absFraction( o3l_p - o3lpo ); m_osc3r_phase = absFraction( o3r_p - o3rpo ); - + } @@ -712,7 +762,7 @@ void MonstroSynth::renderModulators( fpp_t _frames ) const f_cnt_t tm = t % static_cast( lfo1_r ); const float p = static_cast( tm ) / lfo1_r; if( tm == 0 ) - { + { m_lfo1_last = m_lfo1_s; m_lfo1_s = Oscillator::noiseSample( 0.0f ); } @@ -845,7 +895,7 @@ void MonstroSynth::renderModulators( fpp_t _frames ) const f_cnt_t tm = t % static_cast( lfo2_r ); const float p = static_cast( tm ) / lfo2_r; if( tm == 0 ) - { + { m_lfo2_last = m_lfo2_s; m_lfo2_s = Oscillator::noiseSample( 0.0f ); } @@ -998,7 +1048,7 @@ MonstroInstrument::MonstroInstrument( InstrumentTrack * _instrument_track ) : m_osc1Ftl( 0.0, -100.0, 100.0, 1.0, this, tr( "Osc 1 Fine detune left" ) ), m_osc1Ftr( 0.0, -100.0, 100.0, 1.0, this, tr( "Osc 1 Fine detune right" ) ), m_osc1Spo( 0.0, -180.0, 180.0, 0.1, this, tr( "Osc 1 Stereo phase offset" ) ), - m_osc1Pw( 50.0, 0.0, 100.0, 0.01, this, tr( "Osc 1 Pulse width" ) ), + m_osc1Pw( 50.0, PW_MIN, PW_MAX, 0.01, this, tr( "Osc 1 Pulse width" ) ), m_osc1SSR( false, this, tr( "Osc 1 Sync send on rise" ) ), m_osc1SSF( false, this, tr( "Osc 1 Sync send on fall" ) ), @@ -1161,7 +1211,7 @@ MonstroInstrument::MonstroInstrument( InstrumentTrack * _instrument_track ) : connect( &m_env2Dec, SIGNAL( dataChanged() ), this, SLOT( updateEnvelope2() ) ); connect( &m_env2Rel, SIGNAL( dataChanged() ), this, SLOT( updateEnvelope2() ) ); connect( &m_env2Slope, SIGNAL( dataChanged() ), this, SLOT( updateSlope2() ) ); - + // updateLFOAtts connect( &m_lfo1Att, SIGNAL( dataChanged() ), this, SLOT( updateLFOAtts() ) ); @@ -1183,6 +1233,8 @@ MonstroInstrument::MonstroInstrument( InstrumentTrack * _instrument_track ) : updatePO1(); updatePO2(); updatePO3(); + updateSlope1(); + updateSlope2(); } @@ -1206,7 +1258,7 @@ void MonstroInstrument::playNote( NotePlayHandle * _n, ms->renderOutput( frames, _working_buffer ); - applyRelease( _working_buffer, _n ); + //applyRelease( _working_buffer, _n ); // we have our own release instrumentTrack()->processAudioBuffer( _working_buffer, frames, _n ); } @@ -1461,7 +1513,7 @@ QString MonstroInstrument::nodeName() const f_cnt_t MonstroInstrument::desiredReleaseFrames() const { - return 64; + return qMax( 64, qMax( m_env1_relF, m_env2_relF ) ); } @@ -1590,14 +1642,14 @@ void MonstroInstrument::updateSamplerate() void MonstroInstrument::updateSlope1() { const float slope = m_env1Slope.value(); - m_slope1 = powf( 10.0f, slope * -1.0f ); + m_slope1 = powf( 10.0f, slope * -1.0f ); } void MonstroInstrument::updateSlope2() { const float slope = m_env2Slope.value(); - m_slope2 = powf( 10.0f, slope * -1.0f ); + m_slope2 = powf( 10.0f, slope * -1.0f ); } @@ -1842,7 +1894,7 @@ QWidget * MonstroView::setupOperatorsView( QWidget * _parent ) maketinyled( m_osc3SyncHButton, 212, O3ROW - 3, "Hard sync oscillator 3" ) maketinyled( m_osc3SyncRButton, 191, O3ROW - 3, "Reverse sync oscillator 3" ) - + m_lfo1WaveBox = new comboBox( view ); m_lfo1WaveBox -> setGeometry( 2, LFOROW + 7, 42, 22 ); m_lfo1WaveBox->setFont( pointSize<8>( m_lfo1WaveBox->font() ) ); diff --git a/plugins/monstro/Monstro.h b/plugins/monstro/Monstro.h index 2b84a1678..1143ddcd1 100644 --- a/plugins/monstro/Monstro.h +++ b/plugins/monstro/Monstro.h @@ -178,6 +178,11 @@ const float MAX_FREQ = 48000.0f; const float INTEGRATOR = 3.0f / 7.0f; +const float FM_AMOUNT = 0.25f; + +const float PW_MIN = 0.25f; +const float PW_MAX = 100.0f - PW_MIN; + class MonstroInstrument; class MonstroView; @@ -338,6 +343,9 @@ private: int m_counter3l; int m_counter3r; int m_counterMax; + + float m_minfreq_pd; + float m_fmCorrection; }; class MonstroInstrument : public Instrument From b5d9286fdc6e3f5c7af0110003948bf370768d77 Mon Sep 17 00:00:00 2001 From: Vesa Date: Sun, 15 Jun 2014 16:01:12 +0300 Subject: [PATCH 50/61] Monstro - additional small fix... --- plugins/monstro/Monstro.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/monstro/Monstro.cpp b/plugins/monstro/Monstro.cpp index 96dff60bf..d3ebbf6b2 100644 --- a/plugins/monstro/Monstro.cpp +++ b/plugins/monstro/Monstro.cpp @@ -143,8 +143,7 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) if( mod##_e1 != 0.0f ) car += m_env1_buf[f] * mod##_e1; \ if( mod##_e2 != 0.0f ) car += m_env2_buf[f] * mod##_e2; \ if( mod##_l1 != 0.0f ) car += m_lfo1_buf[f] * mod##_l1; \ - if( mod##_l2 != 0.0f ) car += m_lfo2_buf[f] * mod##_l2; \ - car = qBound( 0.0f, car, 1.0f ); + if( mod##_l2 != 0.0f ) car += m_lfo2_buf[f] * mod##_l2; #define modulatephs( car, mod ) \ if( mod##_e1 != 0.0f ) car += m_env1_buf[f] * mod##_e1; \ @@ -562,6 +561,7 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) if( o3s_mod ) { modulateabs( sub, o3s ) + sub = qBound( 0.0f, sub, 1.0f ); } sample_t O3L = linearInterpolate( O3AL, O3BL, sub ); From dcfa4ebe43dc827e54c6d7f1b68604ca06646822 Mon Sep 17 00:00:00 2001 From: Vesa Date: Sun, 15 Jun 2014 17:29:24 +0300 Subject: [PATCH 51/61] Monstro: oops... corrected an error --- plugins/monstro/Monstro.cpp | 23 +++++++++++------------ plugins/monstro/Monstro.h | 1 - 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/plugins/monstro/Monstro.cpp b/plugins/monstro/Monstro.cpp index d3ebbf6b2..660a73476 100644 --- a/plugins/monstro/Monstro.cpp +++ b/plugins/monstro/Monstro.cpp @@ -112,7 +112,6 @@ MonstroSynth::MonstroSynth( MonstroInstrument * _i, NotePlayHandle * _nph, m_counter3r = 0; m_counterMax = ( m_samplerate * 10 ) / 44100; - m_minfreq_pd = 1.0f / ( m_samplerate / MIN_FREQ ); m_fmCorrection = 44100.f / m_samplerate * FM_AMOUNT; } @@ -152,12 +151,13 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) if( mod##_l2 != 0.0f ) car += m_lfo2_buf[f] * mod##_l2; #define modulatevol( car, mod ) \ - if( mod##_e1 > 0.0f ) car = qBound( -MODCLIP, car * ( 1.0f - mod##_e1 + mod##_e1 * m_env1_buf[f] ), MODCLIP ); \ - if( mod##_e1 < 0.0f ) car = qBound( -MODCLIP, car * ( 1.0f + mod##_e1 * m_env1_buf[f] ), MODCLIP ); \ - if( mod##_e2 > 0.0f ) car = qBound( -MODCLIP, car * ( 1.0f - mod##_e2 + mod##_e2 * m_env2_buf[f] ), MODCLIP ); \ - if( mod##_e2 < 0.0f ) car = qBound( -MODCLIP, car * ( 1.0f + mod##_e2 * m_env2_buf[f] ), MODCLIP ); \ - if( mod##_l1 != 0.0f ) car = qBound( -MODCLIP, car * ( 1.0f + mod##_l1 * m_lfo1_buf[f] ), MODCLIP ); \ - if( mod##_l2 != 0.0f ) car = qBound( -MODCLIP, car * ( 1.0f + mod##_l2 * m_lfo2_buf[f] ), MODCLIP ); + if( mod##_e1 > 0.0f ) car *= ( 1.0f - mod##_e1 + mod##_e1 * m_env1_buf[f] ); \ + if( mod##_e1 < 0.0f ) car *= ( 1.0f + mod##_e1 * m_env1_buf[f] ); \ + if( mod##_e2 > 0.0f ) car *= ( 1.0f - mod##_e2 + mod##_e2 * m_env2_buf[f] ); \ + if( mod##_e2 < 0.0f ) car *= ( 1.0f + mod##_e2 * m_env2_buf[f] ); \ + if( mod##_l1 != 0.0f ) car *= ( 1.0f + mod##_l1 * m_lfo1_buf[f] ); \ + if( mod##_l2 != 0.0f ) car *= ( 1.0f + mod##_l2 * m_lfo2_buf[f] ); \ + car = qBound( -MODCLIP, car, MODCLIP ); // pre-render env's and lfo's renderModulators( _frames ); @@ -192,8 +192,8 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) // get volumes const float o1lv = m_parent->m_osc1l_vol; const float o1rv = m_parent->m_osc1r_vol; - const float o1v_e1 = ( m_parent->m_vol1env1.value() * 2.0f ); - const float o1v_e2 = ( m_parent->m_vol1env2.value() * 2.0f ); + const float o1v_e1 = ( m_parent->m_vol1env1.value() ); + const float o1v_e2 = ( m_parent->m_vol1env2.value() ); const float o1v_l1 = ( m_parent->m_vol1lfo1.value() ); const float o1v_l2 = ( m_parent->m_vol1lfo2.value() ); const bool o1v_mod = o1v_e1 != 0.0f || o1v_e2 != 0.0f || o1v_l1 != 0.0f || o1v_l2 != 0.0f; @@ -246,8 +246,8 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) // get pitch modulators const float o3fb = ( m_parent->m_osc3_freq * m_nph->frequency() ); - const float o3f_e1 = ( m_parent->m_pit3env1.value() ); - const float o3f_e2 = ( m_parent->m_pit3env2.value() ); + const float o3f_e1 = ( m_parent->m_pit3env1.value() * 2.0f ); + const float o3f_e2 = ( m_parent->m_pit3env2.value() * 2.0f ); const float o3f_l1 = ( m_parent->m_pit3lfo1.value() ); const float o3f_l2 = ( m_parent->m_pit3lfo2.value() ); const bool o3f_mod = o3f_e1 != 0.0f || o3f_e2 != 0.0f || o3f_l1 != 0.0f || o3f_l2 != 0.0f; @@ -289,7 +289,6 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) // // /////////////////////////// - // declare working variables for for loop // phase manipulation vars - these can be reused by all oscs diff --git a/plugins/monstro/Monstro.h b/plugins/monstro/Monstro.h index 1143ddcd1..4b2066c88 100644 --- a/plugins/monstro/Monstro.h +++ b/plugins/monstro/Monstro.h @@ -344,7 +344,6 @@ private: int m_counter3r; int m_counterMax; - float m_minfreq_pd; float m_fmCorrection; }; From 9d3c8a98ae1de889c3cbb2cfa6ec5f7ea3f19b3d Mon Sep 17 00:00:00 2001 From: Vesa Date: Sun, 15 Jun 2014 22:38:25 +0300 Subject: [PATCH 52/61] Monstro: fix another silly error... --- plugins/monstro/Monstro.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/monstro/Monstro.cpp b/plugins/monstro/Monstro.cpp index 660a73476..aa61187bd 100644 --- a/plugins/monstro/Monstro.cpp +++ b/plugins/monstro/Monstro.cpp @@ -1008,7 +1008,7 @@ void MonstroSynth::renderModulators( fpp_t _frames ) { m_env2_buf[f] = s; m_env2_phase = qMin( 4.0f - env2_sus, m_env2_phase + m_parent->m_env2_dec ); - if( m_env1_phase == 4.0f ) m_env1_phase = 5.0f; // jump over release if sustain is zero - fix for clicking + if( m_env2_phase == 4.0f ) m_env2_phase = 5.0f; // jump over release if sustain is zero - fix for clicking } } else if( m_env2_phase < 5.0f ) // release phase From 0d2249828dac7ac5af9cc12b3d60e4511a3839c4 Mon Sep 17 00:00:00 2001 From: Vesa Date: Tue, 17 Jun 2014 12:39:52 +0300 Subject: [PATCH 53/61] Graphics updates --- data/themes/default/help.png | Bin 1222 -> 1287 bytes data/themes/default/soundfont_file.png | Bin 1162 -> 1631 bytes data/themes/default/vst_plugin_file.png | Bin 1228 -> 1761 bytes data/themes/default/whatsthis.png | Bin 943 -> 1416 bytes plugins/monstro/artwork_mat.png | Bin 61598 -> 65717 bytes plugins/monstro/logo.png | Bin 3335 -> 4199 bytes plugins/watsyn/logo.png | Bin 4425 -> 4772 bytes 7 files changed, 0 insertions(+), 0 deletions(-) diff --git a/data/themes/default/help.png b/data/themes/default/help.png index 86b64075fb5bada5d8814d598b6d9ccfb04e3748..f38f9a76bc26f5072a4045bc81e6ad03669912ff 100644 GIT binary patch delta 1247 zcmV<51R(py35N=hBo78+OGiWi000000Qp0^e~~d5e+P6)O+^RZ1`!D$31E!1EC2um zlu1NER5;6pm0NFARTRhnd!Ngkxpq2bdKm_Lp`8IK6q;zo2&9c*g2)X3!dLJ~ z{RHx$i4U3>AAB_uAvOxcq9W3Wg$l?_rx!ZY>CCj9YtNi>_Qi)@EHH(Yte3sl`em(^ zbs^YZe@Gzud~>k7y~`VH>4idD003Mp)rw2W;&gVVJb$+cKs0o2^w<)QML{^d-s3r zZ`(NlfXcdw;jRw6ckD1uzA%W9gZ(%h>%l;@9R_E3m|cXumN3!1zE-NzxKQY9Wq$6# zeDmaJ2Y>dRZF?47E_oh-9zk460Y7M=+qImhhK2XcVozyfK zD5MlbGrVC%(Sl~F@LRoDEGYnJ^u;4*gVD}&RMQN>IfUR~LSivrz{LH3abf&6exJ?Y zMk0l!LLLLXJ?P!F6aOTpuuxrv5CT$4e?k-`A{;iqGMyNw{z#Y{<#B~t-tg?$(WbguIyyDCyPtDL zz_;mWVFLgpXNW%+K}TyCw(X!?tAQ~Fve7jF(LLV1dULo})&2fHqN=UTw((Tqe;h+y z5xh103R;?*F*^1uZazqXae(muBO;m}as`@VDj-8b2#q;U0Skebx}*5u)N9z=*N4$x zuHnl|KVi|d0P^T4NGVi+gjK;gnB_pqhC>JmiN59l-aRpb`0m}f@beXX{o`fKmTLf^ zPbOwN;LKK3W;@HwG95`^Gy+pde+>3?VsL*y#{RsC&%gTt+0`c_-4Iqc8MmD!)hU;f zR<&Bt6~*7kP?11&wT4{2fa|v=uuv?6Q@U-{tV*S57gwg#QZ7B?i9{!o)2Le;`j2qMJVXmjSkPzdU)Ca(Q; z3zO4x;Ol>zHk`@&%2KNOe{kl!D6U)uAhs5a8eOrsUBTdonm@3I5K6XohFjNR+RhW_ zLP{Z>aw%mNa-Z4h*{=Xp9^c236_+NZkaLod5GaihN>zXm3BcwY@-ZN@EYn(9zENM8 zKkwu+-)=y+J52E-yIMwwKAyi!lGGSRoRyUKpMOwaGU(9_EXZ0Qc z`K1{*`rB9wAjfeS6r-haLReodR)NO|;|d~>+>96smVbH2Y*!8A?$ zA9COT34&k)P)c@_#Z=3Z$(t#MXkiIt5U)5B)CHivySw|PmX;P@6{)18qzWWSlKy6m zkB`p{4h~KMcz-~Qt$h#%r_D_A$(ov)%d@kycMZcZcXxM9S(eRkIBc%1t#QlG$@e^l z#{zhPELd6mU|s3So}QkzzP`Rro6Y8aDn~IizJ#ExU{6iJNF2bL;LG2| z%OwV!v2`eln(Q0AvxV^)3A(O}qobpjnZc|ym{rOL<@5Q@h2W;aS`yP_xP@OIe-}(o!SPTsf4Sa})tvPmc zq*PUfUs4ctn25#UZ zQkyRitj~T~gl5{1N$G@H!7^7A&sve6sXl?|&K|z|c?P$ag?-(}kLG~2zP=t{mKD6o zWq(R}#EGL$Af0Wp-6kL>OTe_8i>a_3dASZa>6v1MwCXAglV2MOg%$y9zzXKtcRHPT z@2m^YM1x7_pCG9%-CERX=4pwd3ewa;bB+2-(bVyv;`J>}1DZ*TvWp#c0QX&=}E z&jwINZtUpjsBdg+^wI=n9ukiY27^){5LlgWYerjJM)UO=0;=EL?A4yeE zb?QFM*si- diff --git a/data/themes/default/soundfont_file.png b/data/themes/default/soundfont_file.png index e5fb2a2cce4b661440f0498cb272cdd0be5c3645..774c82498d8e70205069f0201ba7ac0c21d5d968 100644 GIT binary patch delta 1594 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 diff --git a/data/themes/default/vst_plugin_file.png b/data/themes/default/vst_plugin_file.png index 3a9804d23687585cfff02a959ea6db5a1086d35c..caca1e4c573907bc41ac71048bac04941595155e 100644 GIT binary patch delta 1725 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 BD`)@! diff --git a/data/themes/default/whatsthis.png b/data/themes/default/whatsthis.png index 55cc0c9b74e1241897431888e82643b4fc5de2d7..7099e1d8dc0f31542f5e72e9d01e09da728942b2 100644 GIT binary patch delta 1408 zcmV-`1%LXl2Z#%h8Gi-<006|aY&!q|00v@9M??Ss00000`9r&Z00009a7bBm000XU z000XU0RWnu7ytkO2XskIMF-vn5eX$4nMDA%000FQNkl?$M!fEUuVYl+|Qh|_c@yf+lkY-WlO)8z1I4)*3#N*3%>k_ zrqu41<_EWR*EhHJV#!tj{9w6~U!Ka(EZ!*2UdaQ&mcd(Hw)XdTbqyYRx*^%|OkKQr zARMc2m$n@O2!FIzZncuFWpZrp|A9sK6Hh+bwSVYm4asfCBJ~Xo zLP~)#>sEmfYaxN}8@Ey}mokg*&R-t=)6EYqyuCSl3+Mt$fOz=3KX|Tl@4i=?Q{9I{ z(P-3ou4u-mBVyALwF&tOp%gWxz_x`Qjzpr3@xDky(|=$z(Oz7hy!ts{Hozxun5;Tv`bs| z2bR29n!R;>1N^uZjrQ~&Iex0KGj$k@416C;dmQb1kV8X*T%ArcdgU60a)sXQDZajM z57KoQPk+y#kr)$*P_#a2S)pd9ko%~X&lfDInSlZG|RaxgS|cUZhwIPPENB>t`YtKSuF zN%l&+E|!c&BI1{4PE(wprLvqud*1zW93JgTa`MRIw6?VH-lhLAay^aq{d@dGD4d8i z#ee&xkh0zwBYu41dpxpd7pv*(D7SV`=Gv|C==KhN`pi=d4ea6V_dnz>=l;c#>eU;rs4zkTUf2(2m1-a>l{?J1P!(cKv1)VGe(zjG&Voxi}J|Nc+Xt3|ZZ zclD@`;)(pyX@jXSkS|O9oaq-hJ7V<^3R$D@~@^DL~ zyq8~{wtdfC5rP1a0Jd%O`&VA(*vTJKSy~{PXyYFjN0_=j&(z#Jt`T3p4~;QSet%`E zvXYsW7*mx}`kU>0AMWSp&!42aw16s?*x%F5v4cY#c&LZK^X|_27vz>oj+0wDkL%7$ zz}S|hH-j^|92i4uJdT@Le}s z#c>)2cJFQ@2$10jR;&R(fZ>ZHyz|Kzj;FSO21XSNX(yNYgUT+x38*{Z&Fh*o<(G@^)Rr=5QPrz} z_f=oh8K4cA1V*Tt5dk{Jm73KdH(~dEfay@T!+8_ O00003R?**Q5mK)ZzFzKg_skWBqAmH5e^=!ad|3+L*$g@uKs zrKPpCwV|P*K)cGy$~rqcXU~~CXU-hS+fyK>R9`A<^+s|+BR@hgA!=lnU}OJ=<&UGTGJ(TAF)KY(7S zTl%GL*^kCme}T?xS^2GX&ENJl-}^WJp0MTL{9PZH9salc@ZS|j{;WFkYxTNSs}H_i zd-VIplfO5f`nwwl&i_1k`RAd_-;P}QcKYVm^LM^qy!Z1G5ZwQ9{rdG=Pk!8b_V4c9 zyANOeee~+rlQ(~!K7IP)#fz6OU%vhH`|YQ{?>_%|_xay9Ao%(3`}gm^e*OCW=kNdj z|08=USb>Qkyd=mkn1O|bg_V_+gG)$6T0uce-@w4c%)-V63<83KgHtj~8`^t%`zI}g zf@N#h@85s=_MJQTpy2-FCr@9&!0Y$#zx?_0_b+F!sW{LI#w2fdm!*0;z4U=>4o?@y z5Q(YD2@3oM-qJtXe!TEDYOH*9NFdOxvVGUPeVw{}MQarDI_>QvB2KMaS%2?OYq9lP zRfjuWOZ}7-qSmh{{59p*I@PzVQ34NH^_m=R?cT6w;kHfXQFU9aT`FD%i7)uIVat~< zcjif6HJrH6;32EuA0D}loF6NTvmPx{x|?vwd-^Z#*Dfk5Y1`6N)!MR^TEru@B9l4w@VfSm;OIFM8TD*VpSg0yMZ{7=YudS- zI0H{++ZL@f=}%VrrBB_2&l#qr2h23^mi3KjnB3T?U(h&TVA_VTc~*|1-3I+XFEQvG l;>nVAyU}8qvLoOJgH%l<<9}JLcfbH*@O1TaS?83{1OP@5=I{Uj diff --git a/plugins/monstro/artwork_mat.png b/plugins/monstro/artwork_mat.png index 1a4240b5102b959a79c8c0512a5a0778eaaf5b1d..2f783c655ee8b1e09699cf62e233fa5710573de5 100644 GIT binary patch literal 65717 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
OK?wJJ{EQD@-dhm@1z*^8`ULBX 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 literal 61598 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 z z1b|}0U@+io3g;XhXyNQVVcUJGkDO8IyOv<3_0m5FFU0FoRWrrBvBo6v%&4%aX0-s`ejgjaA%w{YRUOoU4b_C zDsD>~?~jxi&68zegJ=oR_vhh32yVEKH+}Go!ulTc24?Sz^NW`o+%Pisy7vn2R|$Kl zA%QV6Urb6kgaA2~mP2%!EY@m8zxJNug?uaujEv2}jof0B61Ko9TFs{eIy2yKc5FO6 zsIM1drzuc6H=K5TZ*+&Q zRguRT83Cp=5-_DP2v20VM$Gke!rtF}POz+Rue3f?mDV!T3F`+(QYjTpg$epyC1o7W ziUs-+wT$#)fZGd*n9ADPo>5UzDZC=evS5?F|Ar*Jpksgh7(}b#v{i74Q%xdso@cFm z7pjBw%97V0ido!W^QlH5HT_qI$L*x(3;KtcD03Bxal;jAQY~@WtJM7+5 z2xK7TVr7WhS1LTkM$G|Dtwe`P|x>?0K*HzYbU(CoU@Qkp-U$-W+j&M}-9u$pWC@9LmcQz5Y z5YXpPO)RiF(Ois1LkIrYbx`O87_rAQu&N5Py?ugLaAy#pihqLSWZy#h3on)jN3%?a zMn|FD&j_HOcn2pB_%q5KGG8gD*0(p|_|&3%;e1nI&Z)Aul=a}C_FfxBP z>{e4(l>@Ykd)Q;+4f6cTkGE>GcM*>(#I_U=5X3|*E$1;;rf+$NKT#w}YIqTdnl%~; z8fw5|@7YEcs8$}<3l7klpCn3aut?ZXi(ZKyJoVMmowv8%d@3FQ*3Bj46V#WK6umoc zW$>2qVoF;2LcKA6|l<($lVF+M0+htTyS#*4oud#FeSzwJN7bZc)1J= z-s7pQZ~Fs`z#qZFHdjnkiK0^iRnYvI8F>M4tb`<78mui)8&%q6I+Rqx2%bn&Q6<|q zJuO~uCzEB>b{%jKZKQI>tCD=a!Hp(_GRQ{1iLTQ!lJplH%aHsg7KXs_{^-n?c9aib zvvc#8SX@MQ||UtirQkrkm}@JK+<`? z3bz6|Z3`OR1M%Axd!o6cEFzaGg@RTLp*+=00KZz_{`t@~2^o~VVaHfsUyfdTi1bza zZQ=C(x}|p`o5r$8{6KlB33TN{=t-mm4Oj^>D)#`osHLT)zV%}ScmN$6A1{5`H*#PT z_jLg$@^Kf@%9kMp+Zo9l>19)iQmBpA zFXv<$VYNjvY3*yGkR9JZMh!$D)s% zH;g&8y4;NVJK}Ax?;8yIGCI~a* z&8~eoqOzBqW7}5WgpQ0zH(hhGLO^LQjq~8t)s|I`4O1iWDk=77Fx~*}Ie;!ATMD#L z%Bz}28`)fT2;Jsoy!?R^4Y-T|j0EqJ?TC6_)FhuIxzc2ASNSYrbZZGylkeP?a9SCB zJB6Gb85aIi(4qM8BavWpGuh9R!P#oVoZkUruB=#KQ3&Ig=;_cmF^^s0c_si%YFi_g zyW&ONtdcVsH@}*|(UPJK0f)qOcNt_rvgMQ68aaO{KXa&;0))N{9dqDax4r0GY!m78 z*sI12`6zl0tF8+utZ_u8BnG@B`S=pInS-+lV=s$@=j~MWZ_pb` z`o1G9f4yNcm^aWi82|o!)}E-ky1E#lu{C^F23Z}f8gS><6h#v^E*9fod-S0iX4>Gt zRZ~y(d-pX}o%Jp~FS7*~K(XA3yvFSwSApW6Rjd!H#RYT{H*NUGfO(K)Rd7=_o8ydonjj>E&&tyxQc4RlS11qXX!mN zQ6EOqxqhszCDqnG2N^v|VRsZk!R9l;>dMs;;!|HS;1TZI9f*nvbB9nSTVn#T+5cjz zBO?m)k*fAvO&uL@zBH3Yd{U`=E=Sht$_SueQ+@KJinp=J?KorfCnN|7ZSX(+npj&* zpGCbKbz(y{^}vmxxxC_@avC%NGqN^h*Zb$7g-u3AO&xBCWwuZ1P%1sih7c9aZ*NJz z-w|%ukb->ZIw1%Ss;Q}UWu%3Ng&|cFxhiTK`!OvSnsHW~7Y3>&d3*NI+HRaw4JF4i z{u=4^G&eIbK>RcqzVjaSwaaVfepg$YtubMR3(Il&tQd&~6_NcA8#UFW^zNNA3mZQ+ zoCMB%F%MiWMNx~@>;u9~+JBQ&=INJ)KpwwL33cK}jY_iw=P&65?fTI=CXZg3Rv9~x zDMI_Kwvhv(|Z@X(>ORdQtDQzW)H~Mp{6pk+`nD6{22(CDj z%XJPu!Uza>jmmP;ddmsm0|NV|PJ%7};Vz)PvrPM{5L`gBr|*`;%9+6L%m=Gd9>$y+ z)N9}w*V0w0p@7l%40?i{G!M{JYWh+Em{!ivBm4Uk!m4Uld-ezHdoc1&AyLIYHV=oi z6H7*6!S2}Spg#4LsdNam)$B2au5GRz3;*JOAQ8oL#qjok?tn~$g+6IpZ?CL%40?XwXoG+ma|b(eD^O!_hcFE{Km6SE)?0Xt(5 zhmpyD*Tqelo^9#rgt3y__3=wiPR?xBt^>E-F><+5?ZDG%yi>3a62;XlBQnvG*Mk|| zE*;7zLi?C_!#G+j2iRFP?)>B`0EnAQg2{k9Rv5lkED62uPG1(-$l2CO;lSYtOMU7GR+tb+TwXD@*LjPnD6-*(rNnSAot9uL0m@NhUEeh6%MmFo^Jfo^r8P@H z;V7#0<$8$`e=|Z92OCG*-o#47V`W=CqC`749opJ-j^gd(Lyqd}C!9!g5>c)VT+!Vd zu6?tLFG%N`jL&6r;GKcTq#hHe0!9vv9^4Mmzta z@Y8$90UrJ;DKj?w2?Vu?^WwQ-tPSD^*%yl#Kb=MB?v|Z4PP3=bnU(rJ9JI1 zKk=lL42}G3EEcrDFz^nDCG5rvKe@uy?<(pcl1boB6o!wbj6||W>h^H#Om~@O-i`&+ z5o`4!bre7fDgIK63+7iqyG_1TR@Umd1BYyWzq1D036VF#`E93h_Je;9v5!|iJA4H1 zEGGz1#bdGwfGIYNYdlKk7Pq3UX29Ii?bo4j-@LKv-!1pH(;rTC{U2^b1`*V}b}~s| z5*6v2Adx{!hEZB^_uRbQpDF?&iRNnkcSd#gnI?E^R2B`NP)8z$-us`Bx!BoRV(?72 z2@(Lz!tbKS0AP7>zr#_-KnZx??zd*2{c#Yw(-iSeM|K{6+zPBL>cvAq!BcNt$T02^Kk`!02QT|1$8iLIw>g#1i z0eBdGaU-1KgY#g0DW_dwA(s5nN=&CTOI zD(Z340C^;ri?{#SzC1VE{6E4#6l7pWv`rV~ow`_BS^`9J{~IvO!EACZJ`o;Jhz2cD zi9kkjdRIX!+L(Owd)@DZ1>$o?05Tg0GT>>mvbI_l?A2h<8JU~+DN5ceKDLO`{|2MX z?1BR6tPM!l)wmG-6l=$wXy+iZE^DEtgX7GCPUL+qiX?dg@_0Nt^{&kSeuq078*gfp}G(cV?X$D{NYIu8lKn0Q%Vk<_xIrDSA~^sBlq`q=8xs2fYOIeCJB2ha?9P?e308LL>|yy*~RxxMdh53n%7sGI1B)hP){a(NpJD7 z|9#M7AKFuUZ|CFVGe!TTDQhpH?0fj#LsWU>>Fpt>NIxga4_O*~G$U1rc223G)!@;=;Flk(mZu*cYY(_aM6ya@bzh`B ze%R|^9Q=@kG|YRH=FE`Nvo$L~*)yL^BD2h+^}#@Usfw=X8+{Jt)<5~>_Rvql*=1_} zxU?xsmd=7)8WOU(Kp?yxuY%gVBA!i77~4k{Et8ukxujfgk#ZqTD_xOyuD+$rF7r1T zeNuobAu?U=p>LyzJ&$pEX98RiQ`*R)vsjL8g4^FX6XZsOp!s)9Ip{hiT)*o(Prnp6X|&A?+GCsv_w}j> zFUB&fA!bpu8M=roilkX|@JG>ZK8Qj`evD*!85$0m<|7j@uM`rZ@2?_|?5ozPzHZj( zj*KV8r>2Z>$ZZX{er{ggbZm{Lj8aM>!A;!o@l^3yl)46TJrB=hl7g(PO@OK%@prF; z0i5kI9I-7|O>wjav9=WFH_n-Ht!Jw=2ndp*FTP>oqG{F5Ywwn$Kton5pfgHcW3^k0 zwomPtnY*M|vp%`)&8pvCcwt*bc_mxnD`f$NnkLSw43XSgFK^qn$t3!EgbTkX|4 zMN1WHCcXO}ZLlx3P)3)oG21`c8mwmM(%6*U!VYo;~St=C>ydBI^6dETCj+- zM85TXxo)Kk%b@{UBR+jqX}SKL_*(onLCzifDL?0X!*T>TBVwbH#;b2O6JA*b!>@~H z8(nWk-XL}PqHp#eJFFoiiih&_-7QzK7IBA2kxBYt?MHJYcRfw50&g>Slg)?M>+9N^ zh@E6{b;MEnv|olAW&O{vu5Wr!<=+80zDTvqB(|a{TcL1nQ?9RWHw9Agtzsd_8ctHe zCQS8BJj=&_GlS+!Fifh@(JZdJP41Ov31hd@Ay*4_0v`-i*`DcrVk&iE!cd_8dEDbP ziaa5nf{(>oU$Q#rbG$xr!o9T%%d0mbF)*N}x7*cP`rsy88L7~WD$RkjN75LcgNZm@H|ZDDZ_g&wl*rVM&4VQT766CDLkRF7}T=BA~Gx0_`VM7Bhdj zKadls5!{R|kLA@dN zQfMZDCAHFEGzLHhOJZ2#N}FcSGU8A>$9G7S%FkO@zr}uw~%r1pjG0bHrd&j3n=N^?w2Dl9D`3?WD$KPkG$QKaQVG) z#VaO)MTEHqJc~PNWEoa@)k{o1&{Av0)Vx2=_K(Frl85WDTR2#n7w}u>1Ww}d`FvjJB=cl(Ol0-d$C8Wf3+y67AxE#E zHxL5p@i8ku2Sgb7INGb_qy_O0|9fd`E8BHpSZ@0+(kPeP**dznW$*oYkbrk~UV9J? z22xkhUEA7p*E+&29#vTF0sW|LTL|&4k1L)liuPKA30HT`m*#fo=&D<8)Frv^J&HFo zRnO;Y)du(4Gxr#i#Wq`L*^8OwTQ zwz6O?bT{2U?gO8U8vcbAFs63$cyXMI#jV~ua{b};x~M;J-l)edFGg%^n_W!&MJCSn z_mjm2Gr?D|77O(%O06kt^bYT-IY*j2Hr7-b6ZuqO_`z0u=3Ku&c)D2RvgQ|h*kJ+t zzVZ|}eG0q}!VhPT@|0Ix)!u0CJ5B#c%!`s`*kQbPJq%=t4y>N-c|b6tf^-;F-%TTc Of6DS2a{2?h}eEecKP@a&OECw~vmNkl)F(_xj9gSu`alZ>S}3JhI7n>;dOMe%)4kXFE_04Cd>C`Bb574Tf#^zh z)_1=3UB;MW{Qu)W#yrB=AAbS3^pcCj9o!8w$K6o%_HV<@v36{3n0lOdL(On!*N+I~ zln_azlt@`ft7Az>5>op;XKB~Pw+Qh*bDnzo=;{qFtA`&vc;MQc(g#w?H>M=}SLe;c zVE5*LI)-B!2Aey+a>Q0n?(RTJtc?nT6G@t(Igt=jUKuRm5Gj_`!GAGS?K5U}hvWC1 zI<;K|U~6mh+WBmL*A3VI)WLVZ`<=Y>nrpf4l{fIrGbhh7;Jot=@$f_6ILEMOPo3nB z_q>U>-uxomjam&iqc$f~YO9PuN_^~dkMPGI{zncRI&{vnUV6>TcYW{uU%rQLJ$OHN z-uc&j@xE_v_rvg}aeth?lmHoq=>xC6?wW%i{^*@t_sZ9@wRays&gUz4e~y$Axtoz^ zGrIYVJnQJXj;@>0k9_p6c;&S(+h0n(9XOoY z?>F9d+q>Ai@4)(oTi*DFa~`tWxd-n1694eAk8ssx2gx~+bAO`CiLT4!d8V6%;j`Su zZ(ZiammJ{ZfAbf7{i|R6k=}9UxxM=jaNBL~0=OQyI0H$<@A%*cKg4W4Utjq8pTCLY zCrL@K;*dnvY?4G!gPo!9@AvC$alWUV~>27eOoiGy!0T~UHyDsc;R05ZgnJg%pFt3%rULhVu(OW z0?3+$#KCa3`^sZaFZlX*kMZae&$2xfUU22rT>X-tgz`?B< z`?oqaJ0Sz&hN)7`a8;@)RuqwzPK`2yHU(U$?hM7)9xBf+CjR^A4o@80;l#r7~$7$x@yf3Ie%p&33=8ro6VSQbZl(S+1i}5xiM#B zCd|7;hm&yJ6^fE1(W#*#!Q zlv?pt?zu^nztlcJPFBhHJtx zI?qwzT`}9u0XJ%$nCT{Ime=}2B!$M4NDbCeh_p#b!>9^$0a8~Xxd!*AFivt)bAOWK z(J6(~-kyu$o&d!WNZ^)maTEaoHDj786+72~B!X(C=tO5T(yR$8In7EdXI9MO-a&Rm z1P8G2T7oYzoGwXQ^#tO0TXmNVIPM7-iwL+xWK#%ZNnjqruevi$g{q~|@^c-?In-Vm zsq;DAY~I)-~{ zHwRLea1$KIQA!=?>O8`gBGgzS<%Y;skR&C{LFgc9IN=HcDUXnYc7?dd69G~KCu#&P zr+X_6iuNpsK`9eu8l!^eAb)_I(k>B59fsqgxPxh>l#y<>N%AHKvd1l}l}ZLp9yl#U zMDb*ZuF@~9SOS+EmpB1v(_o**GETyi;+7gEJ9QdxGjdM28$$lyK`c3P(mdg!Xq~8K zBzGM$%TawX@D>4+0AupD!XA#A;8coB#h7jBXHnNKYt|5@T;lZp$qRoZ0jtqpH zn9XK!q12X24msgcA$990xCzt=pUqprQm7?X+pMKf0e4hGarTRzu}o`P^_8)Hx*o1< zeU6xO#G);934fzksYM%V4gC@!!JaL;SS33i^8kJuI zE437s%LPNfK;75WZR?bgwG-@?LS8+b_DF$Xr9g}~N8BpCFB%U!DRoiPw1Zs1x)5%y z%96xPwZb?I^vj-73rV`Lu`SNpUVrzXV)NZu2nplOb)C0Ct-jXa zWgJ<0l+Mg zyis!Km>`4aIXcUX%gEMD-IN_I#rEf7+EfQwAK)f7HOi{f(opqHL1;68!pdfp;b9wt$w?E zO{pFBErMBZ~sw~HW<#tc48tH2e z)lu59#h~o7Uwd*rMsYKw{dR5ys*@y|`&HUJabn=UBggsa7oU$?!$V^wZH>r)A}0m* z1M?Z#LlR3#m^pECW{x&OaFMk$XQj}3@5>A~MK!d@MSquF z$-mt9IJE?SW7cG^uSHm?g~g(eRGKDgQL0Aebu-iyE0t2GNS&P}Qz^K5C{T0Mn{3h8 z+4zkM7v!%T2(`(~EVYFKr~ zVPv^8GWHX-R&6g@5JFz%Z8RF!+mf-8CBo8QLQzV{4|A6uXr1+S{&s_WIM)mSWh7Q?{QPa%!1 zVhz}1Usx;#mdk-!SMTuHG}HjDne)W)B@aA$id)|D4laA)iyEN4?S3{7cYjMEH*14h z522;DX4_x9^*6cdW!Lg=4;*EjCQKtz)s$Mjt&B01%3`}`(GQfVP)nuMicTf+elajs z4TIG}T{lGdlz>!IUZb@~{5Z8nlsKx^A-AEdl|~DDxrQS`}?uIB$K=`Nl(p*X^xegQSan&bHjg~H(>9$0q!A5A%_-H`Sx)Ti z^wg=KTG(0iY%fPj1FV@v3blP@H{+3~794qe!CT((`#k^R%T7x)kADb+D%K`-c1fWV zI}@(4tKv0MyjT>qMz_`-jjV7s5%R+2`3w#l(-6sql=p5=0+-x+y!r)L^t zr^VDzwRHn;YV0fvUp#V>>uv z$z^GPbhH?(faXw(QLDCMWb5nPgE~(wDqsDtZC-ctExh7}8+YGN^;L~9KJ)DbANceS zIeKzfi12s7Nq+%k|Nf1cYW`W=Z+G|W9p4I%SK7nZy=Zi4XPouAe`QhIP)B5 z|9-C|`MbXF?>Fn%3oNC?NV`hhOE_U}r4s+Zjg0M1pW%TLp?EmUS%)Mm2_pmm+ qjql@hI@6)a;hDZ)KH<)>{{fsJc>R+Y5+ncs002ovP6b4+LSTXoQY7^N delta 3296 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 Q1poj507*qoM6N<$f|*|F=Kufz delta 4388 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 eKe&4*um1tu5h~A88+gV50000 Date: Tue, 17 Jun 2014 14:35:53 +0300 Subject: [PATCH 54/61] LB302: Correct slide for samplerate --- plugins/lb302/lb302.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/lb302/lb302.cpp b/plugins/lb302/lb302.cpp index fce7c9f07..91a8119a2 100644 --- a/plugins/lb302/lb302.cpp +++ b/plugins/lb302/lb302.cpp @@ -464,6 +464,7 @@ inline float GET_INC(float freq) { int lb302Synth::process(sampleFrame *outbuf, const int size) { + const float sampleRatio = 44100.f / engine::mixer()->processingSampleRate(); float w; float samp; @@ -506,9 +507,9 @@ int lb302Synth::process(sampleFrame *outbuf, const int size) vcf_envpos = 0; if (vco_slide) { - vco_inc=vco_slidebase-vco_slide; + vco_inc = vco_slidebase - vco_slide; // Calculate coeff from dec_knob on knob change. - vco_slide*= 0.9+(slide_dec_knob.value()*0.0999); // TODO: Adjust for Hz and ENVINC + vco_slide -= vco_slide * ( 0.1f - slide_dec_knob.value() * 0.0999f ) * sampleRatio; // TODO: Adjust for ENVINC } } From 73bd963a3f69265b3785c55984c3bbd51c6f967d Mon Sep 17 00:00:00 2001 From: tresf Date: Wed, 18 Jun 2014 02:54:29 -0400 Subject: [PATCH 55/61] Allow vertical resize for VST Plugin Control Window --- plugins/vestige/vestige.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/vestige/vestige.cpp b/plugins/vestige/vestige.cpp index 7ae8dbcdd..8f41b36c9 100644 --- a/plugins/vestige/vestige.cpp +++ b/plugins/vestige/vestige.cpp @@ -882,8 +882,9 @@ manageVestigeInstrumentView::manageVestigeInstrumentView( Instrument * _instrume m_vi->m_subWindow = engine::mainWindow()->workspace()->addSubWindow(new QMdiSubWindow, Qt::SubWindow | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowSystemMenuHint); - m_vi->m_subWindow->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ); - m_vi->m_subWindow->setFixedSize( 960, 300); + m_vi->m_subWindow->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::MinimumExpanding ); + m_vi->m_subWindow->setFixedWidth( 960 ); + m_vi->m_subWindow->setMinimumHeight( 300 ); m_vi->m_subWindow->setWidget(m_vi->m_scrollArea); m_vi->m_subWindow->setWindowTitle( m_vi->instrumentTrack()->name() + tr( " - VST plugin control" ) ); From 0f03219c93fe12941fdd8e3e7072199581af6d55 Mon Sep 17 00:00:00 2001 From: Vesa Date: Thu, 19 Jun 2014 00:30:48 +0300 Subject: [PATCH 56/61] Fix stuck notes on notestacking Fixes #865. Added a check so we don't add subnotes to a note that is already released (can happen with very short midinotes, eg. sliding the mouse accross the gui piano). I also added a mutex to incoming midievent handling in instrumenttrack. Not sure if strictly necessary, but seems like this would prevent problems in the long run. Also fixed a glitch in noteplayhandle where silent master notes got stuck playing indefinitely ( isMasternote() returns true even if the nph just hadChildren, so it never gets ended if it did - instead we check if we still have subnotes). --- include/InstrumentTrack.h | 1 + src/core/InstrumentFunctions.cpp | 2 +- src/core/NotePlayHandle.cpp | 6 +++--- src/tracks/InstrumentTrack.cpp | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/include/InstrumentTrack.h b/include/InstrumentTrack.h index ea10447c5..8eafc2723 100644 --- a/include/InstrumentTrack.h +++ b/include/InstrumentTrack.h @@ -230,6 +230,7 @@ private: NotePlayHandle* m_notes[NumKeys]; int m_runningMidiNotes[NumKeys]; bool m_sustainPedalPressed; + QMutex m_notesMutex; bool m_silentBuffersProcessed; diff --git a/src/core/InstrumentFunctions.cpp b/src/core/InstrumentFunctions.cpp index 7ffb4a3bb..5549a0d7e 100644 --- a/src/core/InstrumentFunctions.cpp +++ b/src/core/InstrumentFunctions.cpp @@ -235,7 +235,7 @@ void InstrumentFunctionNoteStacking::processNote( NotePlayHandle * _n ) // time an audio-buffer is rendered... if( ( _n->origin() == NotePlayHandle::OriginArpeggio || ( _n->hasParent() == false && _n->instrumentTrack()->isArpeggioEnabled() == false ) ) && _n->totalFramesPlayed() == 0 && - m_chordsEnabledModel.value() == true ) + m_chordsEnabledModel.value() == true && ! _n->isReleased() ) { // then insert sub-notes for chord const int selected_chord = m_chordsModel.value(); diff --git a/src/core/NotePlayHandle.cpp b/src/core/NotePlayHandle.cpp index 8806d65e3..0a3107acd 100644 --- a/src/core/NotePlayHandle.cpp +++ b/src/core/NotePlayHandle.cpp @@ -101,7 +101,7 @@ NotePlayHandle::NotePlayHandle( InstrumentTrack* instrumentTrack, m_instrumentTrack->midiNoteOn( *this ); } - if( hasParent() || !instrumentTrack->isArpeggioEnabled() ) + if( hasParent() || ! m_instrumentTrack->isArpeggioEnabled() ) { const int baseVelocity = m_instrumentTrack->midiPort()->baseVelocity(); @@ -229,7 +229,7 @@ void NotePlayHandle::play( sampleFrame * _working_buffer ) // because we do not allow NotePlayHandle::isFinished() to be true // until all sub-notes are completely played and no new ones // are inserted by arpAndChordsTabWidget::processNote() - if( isMasterNote() ) + if( ! m_subNotes.isEmpty() ) { m_releaseFramesToDo = m_releaseFramesDone + 2 * engine::mixer()->framesPerPeriod(); } @@ -349,7 +349,7 @@ void NotePlayHandle::noteOff( const f_cnt_t _s ) m_framesBeforeRelease = _s; m_releaseFramesToDo = qMax( 0, actualReleaseFramesToDo() ); - if( hasParent() || !instrumentTrack()->isArpeggioEnabled() ) + if( hasParent() || ! m_instrumentTrack->isArpeggioEnabled() ) { // send MidiNoteOff event f_cnt_t realOffset = offset() + _s; // get actual frameoffset of release, in global time diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index be2de2497..59e0d1352 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -240,7 +240,7 @@ MidiEvent InstrumentTrack::applyMasterKey( const MidiEvent& event ) void InstrumentTrack::processInEvent( const MidiEvent& event, const MidiTime& time, f_cnt_t offset ) { engine::mixer()->lock(); - + QMutexLocker locker( &m_notesMutex ); bool eventHandled = false; switch( event.type() ) From 0237da44b5cfea82ee103e5c9dc5e40463407471 Mon Sep 17 00:00:00 2001 From: Vesa Date: Thu, 19 Jun 2014 00:38:48 +0300 Subject: [PATCH 57/61] ... somehow didn't notice the already existing engine::mixer()->lock() there... --- include/InstrumentTrack.h | 1 - src/tracks/InstrumentTrack.cpp | 1 - 2 files changed, 2 deletions(-) diff --git a/include/InstrumentTrack.h b/include/InstrumentTrack.h index 8eafc2723..ea10447c5 100644 --- a/include/InstrumentTrack.h +++ b/include/InstrumentTrack.h @@ -230,7 +230,6 @@ private: NotePlayHandle* m_notes[NumKeys]; int m_runningMidiNotes[NumKeys]; bool m_sustainPedalPressed; - QMutex m_notesMutex; bool m_silentBuffersProcessed; diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 59e0d1352..b9e1e21b1 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -240,7 +240,6 @@ MidiEvent InstrumentTrack::applyMasterKey( const MidiEvent& event ) void InstrumentTrack::processInEvent( const MidiEvent& event, const MidiTime& time, f_cnt_t offset ) { engine::mixer()->lock(); - QMutexLocker locker( &m_notesMutex ); bool eventHandled = false; switch( event.type() ) From 29c7894993b16909729f00d57aff599f435e2d82 Mon Sep 17 00:00:00 2001 From: Vesa Date: Thu, 19 Jun 2014 17:58:38 +0300 Subject: [PATCH 58/61] FxMixer GUI updates: graphics Also fixed size of whatsthis --- data/themes/default/fader_background.png | Bin 1618 -> 1391 bytes data/themes/default/mixer_send_off.png | Bin 916 -> 1022 bytes data/themes/default/mixer_send_on.png | Bin 1207 -> 1578 bytes data/themes/default/new_channel.png | Bin 0 -> 479 bytes data/themes/default/whatsthis.png | Bin 1416 -> 1321 bytes 5 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 data/themes/default/new_channel.png diff --git a/data/themes/default/fader_background.png b/data/themes/default/fader_background.png index 2c0d0dd49380fa41d119604ead0c8b9002d7202f..682ff4c92815efe638b9adfd9b7ef723639ccd3d 100644 GIT binary patch delta 1366 zcmV-c1*!Vd4DSk%Dt`a~0002_L%V+f000SaNLh0L01FcU01FcV0GgZ_00007bV*G` z2i^t~3k(Ag7S}=R1H80RL|MzQ?)0R)6QW&VJPMzs2E?)64ix zSU^Hx78EN`Rj6iMFK_<<_#^)Kp8!6_>HLjZz|2ULpqgRXkTv7|cCF`u9Te-|8u?S_ zf3JW2WgJ1wU~)8NF0ian%ecI~{ZPm0dFiHN{xX7@9lZ#O z8B7(bip%8=@_*^v&L<*h&h7l|)*rdoP>4~AA)7&S#`O;JaXN!VAVf%skWKx6r1=2k z!~zkoW3d9$jI6qeT$n*DNR(iz$XQ|ik&k2RaT0Fbl1*{F)92&)456i4yx!jH2lTlJ zh!`xj=1)v$-7Q&RrqFyy&DoI)Gi)x`E-5-6M3Jf1T}@_3{}JJcIk-xH2PNbUuB{U+d)p`tW}vvV=KOQt@&v+ zq0EFb&y5!^mpjO(*T%PL7@%rxLOUaW86oTw$IO_EdGGEp5wXw2kO&%QgZ;Zs=;RX@ zTX8l=u75lGoGbEATTyYlUOLyDgFlG{b19De!EW)ICuc2FXx8pEAD1mhf_W~;F?Cx^ zLMNZj*cY|trg^8&rPW+xgZgf{9I#tN7(}jeRrR6bVs@2l=DOvW z-BOWAFj2M)%R9S87(&iO*|fcB|2`)YFh{q{(SI#@r&}btWvEPKu>Oi`4EC>{s95L_ z-Bw)eot5f7w_yM7Te0>yvxIJWQY*%U)?R<_?}@@yFp2xn;KWUR9-Nzo)I6x>-fr#` zKD170DXwxKZAF$^bDvJt-ZgjK;+?|Guu@#P>UOsfyCSBFJlx+A$X9Nzl%`zwIFv)5 zSAX4dgyLHC`DgaGZQa83nf+^OaZKJKF`=bELyK&4sGoIDlv~|9PiWL!BDY#R(e^&C z8#Ix3OOCqtX8*}2wB;?<+`^u-;F?;*M)V22bnX_C*ey+QWti^xP_Ayy9kjc@BlfvO zI_GY#_-&$OIvA_K(DEJ1L4cP03w|+7Y?pI)$dC&uvHLRxO{>;^z9N z(5F@2BH=7l?V&zrj^tmLyrr*$UiSHl{g)fAjihL`TY^9P@AHbhvj1!)lAlMnEq{z* z#r_8%uXl6oXgojn3}rjxBA@D^djBKt=G=!$bHz13e|*~_Z9-KQxqE7HiaU!srKR3k zsN#Ajg&wEZaDVIjP_O&@LHgX$FNx^3gJxQ#bM4OJsQXZN3ydP`pMSWPaYd@Ur*cVF8JFe*k|O6&YFcrQ)IxVsi#pMs z{JU0Ev+f)^x!PK*T+PVYHg}6i+$yeBZvR`w*yj|zYi0f)T5&*D3)OXqCz2)OD#f7L zyjwQE5)rUa>vKJ*&&QVfllV<;O@H=N=$cyOmi`}bXYoa!n}wU(%yI+yN>87w9>M++ z`&?Ms7Yom1x&FmMi_@%07*qoM6N<$g5>4JXaE2J delta 1595 zcmV-B2E_UA3epUaDu4d~{{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G` z2i^e@3@I1?sxAEh00rMkL_t(&-tAhgcHCAF{*n{0nwh``d$sG3fRGTQvXa8Wp29vr zpDDPoq^!uq#2_TGw0;NQnJdc^i@zyE;0{``!efB6mV*DtvK=kLAu62HaAPgkhl zfAELj-dy9|yB{FD1POsz5G_Jgp&D>|bB+4_hw^~in`_joHJAm=jEX9#23RnJ-u-U? z!1Mw4n}?%c*MIZ@ZS!zkTL55L*C1vvc{Q<%u%J*2XzuR5`-iLb8cYHbMzyH?EiJ%Q zv1!}K56?e1_S*Lghbv#!U}mpg1kntp3ROkZ?5TXUF85bN&=AV~o6TotV7)8hU1S%31Jx0B~w1Vjv$-18$gG-FFpm?<>O z(DP{xXX*L3DLr3-nLr|7V#Mfku4ZWV zJZQDP1b-9xoL3dp6cz$h4Vz7~+w*2(&nHxVQ9CO7pUgx7Hc~l}vsPvzO{jRk+w=R$ zcs{lAw4uy|*mZ>$n`TettINW-)nWlvD;xUs%9|;bFKY<<#xXOxXg<3mOhoKEv8V`| z?hP7nzq_IL&&ovg$~P{dVrO2tj^H`x${(SkVt>=_&UxEBAD&+*5!h>5)Cg2keOStuxaUM9MzSH7JIFLKXK!^oUV z>A5BZb!=&NH?(=aInUT4!XR>$tEvYT7qhEeGuJJ%V9N<}?v+SlqF@0QMzBQ~Le50N zw12$mxv`}Nk$^c(OP8i4j7*E9X<1|@GT0o7YdR`2rRrUuTk7MW;$okyD&x5&_J1lW zPEuSK%eu@svn1Veq*hEDnrHp#(=uJcUrRIDsC>uqFl!~l#@Qs zx@8u{)lTD=8ZZcehBi;mAD)8cwwlFIdTZXP#x3M%Hx9TksMxpPJFll>8hzZDA~W?EeCl=d(HXYCJ#p3}rauBH!vo z_Wm=S&9##`G%*YH^7F%|EmAgART09u_4!3Qv&dT-^O=Pz+C8Cgy}C^9uYZ3Y>V2Of zDLP4?d-dBybl5>N_0qX=W^rx@ozFwvEihtdj?V}5xd@|LkoSA8^U&rLH<#UlC;xUt z3QZ~b4`tS0Vnco7O2(B^NLdEOwZP`0XeY5x@QJ^E4O}<@;X)z{gKl t-#wszef)Ga`g!-k`R`x-|7FO1*MFxSPe^5#ijM#Q002ovPDHLkV1lZ9B@O@p diff --git a/data/themes/default/mixer_send_off.png b/data/themes/default/mixer_send_off.png index 0adafe29633cc0224c6b91bf07be427a4c262448..1be1ad54f20a570b743b38e04939c58705777d5d 100644 GIT binary patch delta 999 zcmVz6!r1wU)B}+^+F1p?AZ}2bi z&P(q|%)D}jq!<>>NFbzuS%B39yC$uz&?*Fv14_?1uNSA3)=@6z<(}l^JkN8^`+VQ; z^9x=T5uL{EPw##8_x_)wQ6~~bNTd)ny(WK7G>X^sh{xjuzK?G$f#;#L!S|XN6CoOn zA|&{pPqZ(Fk_v4MhtHp*oxZ2D-+cY$DUR+0{j2uJsMg9p`|a2FP8yAbR1(p;my|7C z0G6{iHq?Ev1c1aR02^AL-@E_46N`;@;>a%EHi+(2N*T{;|`oH=1nkR|t*RGRDBp4eTd+EAu zZ*NnrR(Z1VBmrz*2&$AKnM{&Sr~g;8jE|3_wPs^u0~^-i{PbEZNXg{nB#lOc*>7ig z^z$Q(F)S}Hlbz3!ozLR?K1)kW936ihVT_?tsbGxZ!FLbH&Sxo=N*o^_GchrNP>LX+ zH)s$9C?U{V^KkAVw{F~G=EE7Z*6i)?k(thL^Ttga$Dv-YQz#UWQnIkHfYur(;xKe& zh)ShGxm-qTjS>PSyN0AYy^)B6>$>Fgd1|{g78e(pdVdOlot+(OwHmJL0$*fD<^ra^-_|o9WGIzOEG;j!eUBF(lgs5e zJUj$o?ANHdTN@rU)IhpGM%BnzrSs#QYnNGY;A3w z+eoK!blm98v{TCEGHdH=TupypZToVoxi-_&G!G9CbJ9Ekz;#_#S69j9atsU(bd=5X zW-5fhS|}EajEszsOeWjkWdjPXbDVr9oioO%o(8p@O=bhEwPDa!(^)K*pyi_l94>roEw?}ZBo}ca$32<$4-7r~ z=U{I%J$Y^O%3E)5Ub_4`N_TI{m=ifSoyLU!IT1rF8X+Ew0)lwFFIKMBp7Kh{zn$S? VDU}6j-~a#s07*qoM6LruV1k>M&0qik delta 892 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 JPDHLkV1nQq>aqX; delta 1185 zcmV;S1YY~947UkeiBL{Q4GJ0x0000DNk~Le0000N0000G2nGNE0R1oI7ytkO24YJ` zL;!IB{{Wy>zvTr0000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2i^l84HgZ-%dp>( zTPJ@6A4x<(R5;6BluL+}WdMes@Am)aKXcAF zXy-jM({+MyB&``~ONpdfB27x@#GtiCX@O800mKMCM51>%=WsDBB}$bNDv@ZDB#hR_>F?`fa=6Zw{5O9AXzyCV|D$7wL>~ywaaU&t49A$E(#>B1Ld>HdE@p=oi}qrJ6gp_%HfGcz>7$dz7_%%IZ*ofwqTC@B$2AP~eD zi6Ig~zxi-g>vQj0bkWfW2>gi;6* zAqqn9gy8YTq7g&ku+|a^PjG>Co42C0Mt3Y*#>DtIm9}=;?ruFNEmzP+Bb8jVp^_wN zf{@~0#9~;SMhZdni~2R%kZJ`;N~M(P=_&pOKmQv%zwc&x00000NkvXXu0mjfK@}vf diff --git a/data/themes/default/new_channel.png b/data/themes/default/new_channel.png new file mode 100644 index 0000000000000000000000000000000000000000..8a27695df8ef862d618eec3247a9896465d68264 GIT binary patch literal 479 zcmV<50U-W~P)48)Q+Ibi zME4AJa1eqzh=QUaJPCPSnwY0HX{nT+DeuoY_q@xw5v?`%#KT?H{#;N*Mz(El9miQX zjpLK3#keriBL{Q4GJ0x0000DNk~Le0000K0000K2nGNE0F8+q4Ur)ne+}0F z01ejxLMWSf00007bV*G`2i^t~3JDPC?)23F00g#4L_t(I%XO7&Xk1kg$A9PCyLUIc zo84|qvN1|(qXw!dNVG+5sfyMYh^Y8NrM~b(K`K_z4=O&2s8y;|#QOSBZLL-tMHIB6 z7T=H7N7WMJM$>M(**rG8+3enXf6qDh_@SoM*TBHQFf;#|`7^iqK-$kq? zg|!i?(O{-rqFye&?^mm9cMoj-2ncgMy|OY=hz=$^Bw2p(&9^?3>FT~de|uyPfr(75 zQi+1u8IjE7NVK%rRNRx+T4%brmzn+hHh%g1`a6NqT+aeo85xemA!zfbt-Ry4-2C39 zPCRadT9rNz(Z8^dwrrM>{UwI?kMZqzmDY|Lt7;=*N1 z5dJKY)`ZQvNVaznOQ-KbIC0l)Nv4vS%%Z80;V9MKDG`7LAq4sEZj9D6>ov3$q>?Vl zR2pd`jPGNFgEmG)*6NnF!%l7M>+6=T=k>0+{WfMN%C=rEp#y~u6)Fg5*6S$0Nra@W zG0lB9UW@B_JiYlGD)GwW50h?9vuWE~ys+a-WJ?OP`fINi>Bf+;*nEk#0$}xuYvfsr`>BoY!>`Yv zRfvuvRB4o#9=r!H5ohzjTddi#4eP}Z_?1Gd5EX_(g(1f1e}pt)Fb*K4?v^8v-`~G{ z!-fraFTe5{v2&<^+nUuJ4cyq#@s2#wjbSZVqtT5zx>nt-XKGLSW5qXs$wX(j z@XMoi4xtOot!~MxRjW=}w{G2Uz@(eb)MPAnB97aOwH`(lB4c)$dc9z6RQsofK*Ybec}NL@c& zN^uZHX?mlLf?c(aOA^QSI2T`Mf5!IQ&z!UOIhzODiPN}cOTU-B*7~&8(%NeazWj)$ z)b5t%2e)BrzE_)5-G@Wb zXw-PFXvU`_V$%_|3Hb`46g8#5wuK#zM52xHzDPsUU^LNQT%Nr8Ibb%xCxC0)pEz=~ zbJyNi8ao~s1f;1s9O>@le@EYVjHeGC;OPDV9_#C2Ftv@SuerUrgtu0(2-i2XOI!8_ zmb_V-y>)#9{J0g3_VgY(eyXuEbr_5cd>>1D9PN9MLqmgHolY})K51E@W~Y$*sFu$cEZ|Tqk^FXB->#=3jg67OfA19e}Ml^PP0(15(ELp7$GdHD^PlNb!Ku@3MpgXfA++| z!tBkMsyX;dt;zREmmEI0F;7+nXalaWxHOq&ZgGjG#zs*CHIN-xY32 z_DZ`hmW)Os;+JPmQ=FfrvYbPE-u-eM9_>nU^2p<~wzTlxrT;K;J&pGLd;CNwoQO2V z`=pSv-WVf(eBygNvS$~o>FX%Bc2DNot?}sg4u1N~Qw$C4f8p)-Kjbgx{>75x-mPX` z#soHqq%_8004XKEed$*SttrgjLVF7BDU|2Y-5BH4w~o@kb0=?|zrdgW{!h}YMYPg) z{5H$io+SgVD`I`9dv|<|7fwG@%A(PE<@zXID@ea~GHf&h>Jwr%tKS6=4W$sbZ#S|FNe;~y7Cn7TdB)Z9F-5nsL!jWJGsWva50 znU)w+l~Vef?Ry{Y=jYF#q`I_#Dwo*b)6KDiLmYUhe}};H?#}ub&{ES z*p{U?gEP4t7(;73j+8Ay|xYS_84IJ z`~`mZ+FuDZ#Ra7c$tOQ)k^kn>wBFI@V_S}CMJN` z*x1-l#>dC6oPFbsQI*TI)Iy;|sHtU#42Kg!RY-dsr~}u{>zXs=my7SzmNI8i)vJK_ zRbSH?pbeM=MyRVZRyg*M9josXf_A_%evs2nWy*J}Q@HLt;A}N{{{yNm6M^7dhrj>; N002ovPDHLkV1f^@xnKYQ From 4bcbb1abcc693b4acf4e3d5ea192bb61e9dae314 Mon Sep 17 00:00:00 2001 From: Vesa Date: Thu, 19 Jun 2014 17:59:15 +0300 Subject: [PATCH 59/61] FxMixer GUI updates: code --- data/themes/default/style.css | 13 +++++ include/FxLine.h | 5 ++ include/FxMixerView.h | 4 +- include/SendButtonIndicator.h | 25 ++++----- include/fader.h | 20 +++++--- src/gui/FxMixerView.cpp | 11 ++-- src/gui/widgets/FxLine.cpp | 40 ++++++++------- src/gui/widgets/SendButtonIndicator.cpp | 20 ++++++-- src/gui/widgets/fader.cpp | 67 +++++++++++++++++++------ 9 files changed, 141 insertions(+), 64 deletions(-) diff --git a/data/themes/default/style.css b/data/themes/default/style.css index 82e72ec6a..ccd666189 100644 --- a/data/themes/default/style.css +++ b/data/themes/default/style.css @@ -482,6 +482,19 @@ FxMixerView QPushButton, EffectRackView QPushButton, ControllerRackView QPushBut font-size: 10px; } +FxLine { + background: #5b6571; + color: #e0e0e0; + qproperty-backgroundActive: qlineargradient(spread:reflect, x1:0, y1:0, x2:1, y2:0, + stop:0 #7b838d, stop:1 #6b7581 ); +} + +/* persistent peak markers for fx peak meters */ +fader { + qproperty-peakGreen: rgb( 74, 253, 133); + qproperty-peakRed: rgb( 255, 100, 100); +} + timeLine { font-size: 8px; } diff --git a/include/FxLine.h b/include/FxLine.h index 5ee4d2ec2..6fbe8161e 100644 --- a/include/FxLine.h +++ b/include/FxLine.h @@ -40,6 +40,7 @@ class FxLine : public QWidget { Q_OBJECT public: + Q_PROPERTY( QBrush backgroundActive READ backgroundActive WRITE setBackgroundActive ) FxLine( QWidget * _parent, FxMixerView * _mv, int _channelIndex); ~FxLine(); @@ -54,10 +55,14 @@ public: knob * m_sendKnob; SendButtonIndicator * m_sendBtn; + QBrush backgroundActive() const; + void setBackgroundActive( const QBrush & c ); + private: FxMixerView * m_mv; LcdWidget* m_lcd; int m_channelIndex; + QBrush m_backgroundActive; private slots: void renameChannel(); diff --git a/include/FxMixerView.h b/include/FxMixerView.h index 6449a0306..c81d257d5 100644 --- a/include/FxMixerView.h +++ b/include/FxMixerView.h @@ -22,8 +22,8 @@ * */ -#ifndef _FX_MIXER_VIEW_H -#define _FX_MIXER_VIEW_H +#ifndef FX_MIXER_VIEW_H +#define FX_MIXER_VIEW_H #include #include diff --git a/include/SendButtonIndicator.h b/include/SendButtonIndicator.h index 2b0819791..8615bc392 100644 --- a/include/SendButtonIndicator.h +++ b/include/SendButtonIndicator.h @@ -11,22 +11,23 @@ class FxLine; class FxMixerView; -class SendButtonIndicator : public QLabel { - public: - SendButtonIndicator( QWidget * _parent, FxLine * _owner, - FxMixerView * _mv); +class SendButtonIndicator : public QLabel +{ +public: + SendButtonIndicator( QWidget * _parent, FxLine * _owner, + FxMixerView * _mv); - virtual void mousePressEvent( QMouseEvent * e ); - void updateLightStatus(); + virtual void mousePressEvent( QMouseEvent * e ); + void updateLightStatus(); - private: +private: - FxLine * m_parent; - FxMixerView * m_mv; - QPixmap qpmOn; - QPixmap qpmOff; + FxLine * m_parent; + FxMixerView * m_mv; + static QPixmap * s_qpmOn; + static QPixmap * s_qpmOff; - FloatModel * getSendModel(); + FloatModel * getSendModel(); }; #endif // SENDBUTTONINDICATOR_H diff --git a/include/fader.h b/include/fader.h index 02bc475c2..500c5e49d 100644 --- a/include/fader.h +++ b/include/fader.h @@ -45,8 +45,8 @@ */ -#ifndef _FADER_H -#define _FADER_H +#ifndef FADER_H +#define FADER_H #include #include @@ -61,6 +61,8 @@ class fader : public QWidget, public FloatModelView { Q_OBJECT public: + Q_PROPERTY( QColor peakGreen READ peakGreen WRITE setPeakGreen ) + Q_PROPERTY( QColor peakRed READ peakRed WRITE setPeakRed ) fader( FloatModel * _model, const QString & _name, QWidget * _parent ); virtual ~fader(); @@ -70,6 +72,10 @@ public: void setPeak_R( float fPeak ); float getPeak_R() { return m_fPeakValue_R; } + QColor peakGreen() const; + QColor peakRed() const; + void setPeakGreen( const QColor & c ); + void setPeakRed( const QColor & c ); private: virtual void contextMenuEvent( QContextMenuEvent * _me ); @@ -85,7 +91,7 @@ private: float fRange = m_model->maxValue() - m_model->minValue(); float realVal = m_model->value() - m_model->minValue(); - return height() - ( ( height() - m_knob.height() ) * ( realVal / fRange ) ); + return height() - ( ( height() - ( *s_knob ).height() ) * ( realVal / fRange ) ); } FloatModel * m_model; @@ -103,9 +109,9 @@ private: QTime m_lastPeakTime_L; QTime m_lastPeakTime_R; - QPixmap m_back; - QPixmap m_leds; - QPixmap m_knob; + static QPixmap * s_back; + static QPixmap * s_leds; + static QPixmap * s_knob; int m_moveStartPoint; float m_startValue; @@ -113,6 +119,8 @@ private: static textFloat * s_textFloat; void updateTextFloat(); + QColor m_peakGreen; + QColor m_peakRed; } ; diff --git a/src/gui/FxMixerView.cpp b/src/gui/FxMixerView.cpp index 466807c4b..25332a64d 100644 --- a/src/gui/FxMixerView.cpp +++ b/src/gui/FxMixerView.cpp @@ -48,7 +48,6 @@ #include "song.h" #include "bb_track_container.h" - FxMixerView::FxMixerView() : QWidget(), ModelView( NULL, this ), @@ -118,10 +117,10 @@ FxMixerView::FxMixerView() : ml->addWidget(channelArea); // show the add new effect channel button - QPushButton * newChannelBtn = new QPushButton("new", this ); - newChannelBtn->setFont(QFont("sans-serif", 10, 1, false)); - newChannelBtn->setFixedSize(fxLineSize); - connect( newChannelBtn, SIGNAL(clicked()), this, SLOT(addNewChannel())); + QPushButton * newChannelBtn = new QPushButton( embed::getIconPixmap( "new_channel" ), QString::null, this ); + newChannelBtn->setObjectName( "newChannelBtn" ); + newChannelBtn->setFixedSize( fxLineSize ); + connect( newChannelBtn, SIGNAL( clicked() ), this, SLOT( addNewChannel() ) ); ml->addWidget( newChannelBtn, 0, Qt::AlignTop ); @@ -257,7 +256,7 @@ FxMixerView::FxChannelView::FxChannelView(QWidget * _parent, FxMixerView * _mv, FxMixer * m = engine::fxMixer(); m_fader = new fader( &m->effectChannel(_chIndex)->m_volumeModel, tr( "FX Fader %1" ).arg( _chIndex ), m_fxLine ); - m_fader->move( 15-m_fader->width()/2, + m_fader->move( 16-m_fader->width()/2, m_fxLine->height()- m_fader->height()-5 ); diff --git a/src/gui/widgets/FxLine.cpp b/src/gui/widgets/FxLine.cpp index c200c1001..a8e30f45e 100644 --- a/src/gui/widgets/FxLine.cpp +++ b/src/gui/widgets/FxLine.cpp @@ -45,19 +45,18 @@ FxLine::FxLine( QWidget * _parent, FxMixerView * _mv, int _channelIndex) : m_mv( _mv ), m_channelIndex( _channelIndex ) { - setFixedSize( 32, 287 ); + setFixedSize( 33, 287 ); setAttribute( Qt::WA_OpaquePaintEvent, true ); setCursor( QCursor( embed::getIconPixmap( "hand" ), 0, 0 ) ); // mixer sends knob m_sendKnob = new knob( knobBright_26, this, tr("Channel send amount") ); - m_sendKnob->move(3, 22); + m_sendKnob->move( 3, 22 ); m_sendKnob->setVisible(false); // send button indicator - m_sendBtn = new SendButtonIndicator(this, this, m_mv); - m_sendBtn->setPixmap(embed::getIconPixmap("mixer_send_off", 23, 16)); - m_sendBtn->move(4,4); + m_sendBtn = new SendButtonIndicator( this, this, m_mv ); + m_sendBtn->move( 2, 2 ); // channel number m_lcd = new LcdWidget( 2, this ); @@ -97,37 +96,34 @@ void FxLine::setChannelIndex(int index) { } -static void drawFxLine( QPainter* p, const QWidget *fxLine, const QString& name, bool isActive, bool sendToThis ) +static void drawFxLine( QPainter* p, const FxLine *fxLine, const QString& name, bool isActive, bool sendToThis ) { int width = fxLine->rect().width(); int height = fxLine->rect().height(); - QColor bg_color = QApplication::palette().color( QPalette::Active, - QPalette::Background ); QColor sh_color = QApplication::palette().color( QPalette::Active, QPalette::Shadow ); - QColor te_color = QApplication::palette().color( QPalette::Active, - QPalette::Text ); + QColor te_color = p->pen().brush().color(); QColor bt_color = QApplication::palette().color( QPalette::Active, QPalette::BrightText ); - p->fillRect( fxLine->rect(), isActive ? bg_color.lighter(130) : bg_color ); + p->fillRect( fxLine->rect(), isActive ? fxLine->backgroundActive() : p->background() ); - p->setPen( bg_color.darker(130) ); + p->setPen( QColor( 0, 0, 0, 75 ) ); p->drawRect( 0, 0, width-2, height-2 ); - p->setPen( bg_color.lighter(150) ); - p->drawRect( 1, 1, width-2, height-2 ); + p->setPen( QColor( 255, 255, 255, 75 ) ); + p->drawRect( 1, 1, width-3, height-3 ); - p->setPen( isActive ? sh_color : bg_color.darker(130) ); + p->setPen( isActive ? sh_color : QColor( 0, 0, 0, 50 ) ); p->drawRect( 0, 0, width-1, height-1 ); // draw the mixer send background if( sendToThis ) { - p->drawPixmap(2, 0, 28, 56, - embed::getIconPixmap("send_bg_arrow", 28, 56)); + p->drawPixmap( 3, 0, 28, 56, + embed::getIconPixmap("send_bg_arrow", 28, 56 ) ); } // draw the channel name @@ -241,5 +237,15 @@ void FxLine::displayHelp() whatsThis() ); } +QBrush FxLine::backgroundActive() const +{ + return m_backgroundActive; +} + +void FxLine::setBackgroundActive( const QBrush & c ) +{ + m_backgroundActive = c; +} + #include "moc_FxLine.cxx" diff --git a/src/gui/widgets/SendButtonIndicator.cpp b/src/gui/widgets/SendButtonIndicator.cpp index a932f136a..e77c0e965 100644 --- a/src/gui/widgets/SendButtonIndicator.cpp +++ b/src/gui/widgets/SendButtonIndicator.cpp @@ -4,19 +4,29 @@ #include "FxMixer.h" #include "Model.h" +QPixmap * SendButtonIndicator::s_qpmOff = NULL; +QPixmap * SendButtonIndicator::s_qpmOn = NULL; + SendButtonIndicator:: SendButtonIndicator( QWidget * _parent, FxLine * _owner, FxMixerView * _mv) : QLabel( _parent ), m_parent( _owner ), m_mv( _mv ) { - qpmOff = embed::getIconPixmap("mixer_send_off", 23, 16); - qpmOn = embed::getIconPixmap("mixer_send_on", 23, 16); - + if( ! s_qpmOff ) + { + s_qpmOff = new QPixmap( embed::getIconPixmap( "mixer_send_off", 29, 20 ) ); + } + + if( ! s_qpmOn ) + { + s_qpmOn = new QPixmap( embed::getIconPixmap( "mixer_send_on", 29, 20 ) ); + } + // don't do any initializing yet, because the FxMixerView and FxLine // that were passed to this constructor are not done with their constructors // yet. - + setPixmap( *s_qpmOff ); } void SendButtonIndicator::mousePressEvent( QMouseEvent * e ) @@ -49,5 +59,5 @@ FloatModel * SendButtonIndicator::getSendModel() void SendButtonIndicator::updateLightStatus() { - setPixmap( getSendModel() == NULL ? qpmOff : qpmOn ); + setPixmap( getSendModel() == NULL ? *s_qpmOff : *s_qpmOn ); } diff --git a/src/gui/widgets/fader.cpp b/src/gui/widgets/fader.cpp index f2dc4c5fd..d12112f82 100644 --- a/src/gui/widgets/fader.cpp +++ b/src/gui/widgets/fader.cpp @@ -60,7 +60,9 @@ textFloat * fader::s_textFloat = NULL; - +QPixmap * fader::s_back = NULL; +QPixmap * fader::s_leds = NULL; +QPixmap * fader::s_knob = NULL; fader::fader( FloatModel * _model, const QString & _name, QWidget * _parent ) : QWidget( _parent ), @@ -72,18 +74,30 @@ fader::fader( FloatModel * _model, const QString & _name, QWidget * _parent ) : m_persistentPeak_R( 0.0 ), m_fMinPeak( 0.01f ), m_fMaxPeak( 1.1 ), - m_back( embed::getIconPixmap( "fader_background" ) ), - m_leds( embed::getIconPixmap( "fader_leds" ) ), - m_knob( embed::getIconPixmap( "fader_knob" ) ), m_moveStartPoint( -1 ), - m_startValue( 0 ) + m_startValue( 0 ), + m_peakGreen( 0, 0, 0 ), + m_peakRed( 0, 0, 0 ) { if( s_textFloat == NULL ) { s_textFloat = new textFloat; } + if( ! s_back ) + { + s_back = new QPixmap( embed::getIconPixmap( "fader_background" ) ); + } + if( ! s_leds ) + { + s_leds = new QPixmap( embed::getIconPixmap( "fader_leds" ) ); + } + if( ! s_knob ) + { + s_knob = new QPixmap( embed::getIconPixmap( "fader_knob" ) ); + } + setWindowTitle( _name ); - setAttribute( Qt::WA_OpaquePaintEvent, true ); + setAttribute( Qt::WA_OpaquePaintEvent, false ); setMinimumSize( 23, 116 ); setMaximumSize( 23, 116); resize( 23, 116 ); @@ -116,7 +130,7 @@ void fader::mouseMoveEvent( QMouseEvent *mouseEvent ) { int dy = m_moveStartPoint - mouseEvent->globalY(); - float delta = dy * ( m_model->maxValue() - m_model->minValue() ) / (float) ( height() - m_knob.height() ); + float delta = dy * ( m_model->maxValue() - m_model->minValue() ) / (float) ( height() - ( *s_knob ).height() ); model()->setValue( m_startValue + delta ); @@ -132,7 +146,7 @@ void fader::mousePressEvent( QMouseEvent* mouseEvent ) if( mouseEvent->button() == Qt::LeftButton && ! ( mouseEvent->modifiers() & Qt::ControlModifier ) ) { - if( mouseEvent->y() >= knobPosY() - m_knob.height() && mouseEvent->y() < knobPosY() ) + if( mouseEvent->y() >= knobPosY() - ( *s_knob ).height() && mouseEvent->y() < knobPosY() ) { updateTextFloat(); s_textFloat->show(); @@ -260,7 +274,7 @@ void fader::updateTextFloat() { s_textFloat->setText( QString("Volume: %1 %").arg( m_model->value() * 100 ) ); } - s_textFloat->moveGlobal( this, QPoint( width() - m_knob.width() - 5, knobPosY() - 46 ) ); + s_textFloat->moveGlobal( this, QPoint( width() - ( *s_knob ).width() - 5, knobPosY() - 46 ) ); } @@ -277,8 +291,7 @@ void fader::paintEvent( QPaintEvent * ev) QPainter painter(this); // background -// painter.drawPixmap( rect(), m_back, QRect( 0, 0, 23, 116 ) ); - painter.drawPixmap( ev->rect(), m_back, ev->rect() ); + painter.drawPixmap( ev->rect(), *s_back, ev->rect() ); // peak leds @@ -286,28 +299,50 @@ void fader::paintEvent( QPaintEvent * ev) int peak_L = calculateDisplayPeak( m_fPeakValue_L - m_fMinPeak ); int persistentPeak_L = qMax( 3, calculateDisplayPeak( m_persistentPeak_L - m_fMinPeak ) ); - painter.drawPixmap( QRect( 0, peak_L, 11, 116 - peak_L ), m_leds, QRect( 0, peak_L, 11, 116 - peak_L ) ); + painter.drawPixmap( QRect( 0, peak_L, 11, 116 - peak_L ), *s_leds, QRect( 0, peak_L, 11, 116 - peak_L ) ); if( m_persistentPeak_L > 0.05 ) { - painter.fillRect( QRect( 2, persistentPeak_L, 7, 1 ), (m_persistentPeak_L < 1.0 )? QColor( 74, 253, 133) : QColor( 255, 100, 100)); + painter.fillRect( QRect( 2, persistentPeak_L, 7, 1 ), ( m_persistentPeak_L < 1.0 ) + ? peakGreen() + : peakRed() ); } int peak_R = calculateDisplayPeak( m_fPeakValue_R - m_fMinPeak ); int persistentPeak_R = qMax( 3, calculateDisplayPeak( m_persistentPeak_R - m_fMinPeak ) ); - painter.drawPixmap( QRect( 11, peak_R, 11, 116 - peak_R ), m_leds, QRect( 11, peak_R, 11, 116 - peak_R ) ); + painter.drawPixmap( QRect( 11, peak_R, 11, 116 - peak_R ), *s_leds, QRect( 11, peak_R, 11, 116 - peak_R ) ); if( m_persistentPeak_R > 0.05 ) { - painter.fillRect( QRect( 14, persistentPeak_R, 7, 1 ), (m_persistentPeak_R < 1.0 )? QColor( 74, 253, 133) : QColor( 255, 100, 100)); + painter.fillRect( QRect( 14, persistentPeak_R, 7, 1 ), ( m_persistentPeak_R < 1.0 ) + ? peakGreen() + : peakRed() ); } // knob - painter.drawPixmap( 0, knobPosY() - m_knob.height(), m_knob ); + painter.drawPixmap( 0, knobPosY() - ( *s_knob ).height(), *s_knob ); } +QColor fader::peakGreen() const +{ + return m_peakGreen; +} +QColor fader::peakRed() const +{ + return m_peakRed; +} + +void fader::setPeakGreen( const QColor & c ) +{ + m_peakGreen = c; +} + +void fader::setPeakRed( const QColor & c ) +{ + m_peakRed = c; +} #include "moc_fader.cxx" From 83cc446807790bf3c7089c7dcad8a734cbcefde8 Mon Sep 17 00:00:00 2001 From: Vesa Date: Thu, 19 Jun 2014 22:17:59 +0300 Subject: [PATCH 60/61] FxMixerView: fix disappearing effects --- include/FxLine.h | 2 ++ include/FxMixerView.h | 9 +++++++-- src/gui/FxMixerView.cpp | 37 ++++++++++++++++++++++++++----------- src/gui/widgets/FxLine.cpp | 3 ++- 4 files changed, 37 insertions(+), 14 deletions(-) diff --git a/include/FxLine.h b/include/FxLine.h index 6fbe8161e..2445e2aac 100644 --- a/include/FxLine.h +++ b/include/FxLine.h @@ -58,6 +58,8 @@ public: QBrush backgroundActive() const; void setBackgroundActive( const QBrush & c ); + static const int FxLineHeight; + private: FxMixerView * m_mv; LcdWidget* m_lcd; diff --git a/include/FxMixerView.h b/include/FxMixerView.h index c81d257d5..8e96797c6 100644 --- a/include/FxMixerView.h +++ b/include/FxMixerView.h @@ -27,6 +27,7 @@ #include #include +#include #include #include "FxLine.h" @@ -54,6 +55,7 @@ public: FxLine * m_fxLine; pixmapButton * m_muteBtn; fader * m_fader; + EffectRackView * m_rackView; }; @@ -94,7 +96,7 @@ public: // make sure the display syncs up with the fx mixer. // useful for loading projects void refreshDisplay(); - + private slots: void updateFaders(); void addNewChannel(); @@ -108,9 +110,12 @@ private: QScrollArea * channelArea; QHBoxLayout * chLayout; QWidget * m_channelAreaWidget; - EffectRackView * m_rackView; + QStackedLayout * m_racksLayout; + QWidget * m_racksWidget; void updateMaxChannelSelector(); + + friend class FxChannelView; } ; #endif diff --git a/src/gui/FxMixerView.cpp b/src/gui/FxMixerView.cpp index 25332a64d..f55112e26 100644 --- a/src/gui/FxMixerView.cpp +++ b/src/gui/FxMixerView.cpp @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include @@ -76,10 +75,18 @@ FxMixerView::FxMixerView() : chLayout->setMargin( 0 ); m_channelAreaWidget->setLayout(chLayout); + // create rack layout before creating the first channel + m_racksWidget = new QWidget; + m_racksLayout = new QStackedLayout( m_racksWidget ); + m_racksLayout->setContentsMargins( 0, 0, 0, 0 ); + m_racksWidget->setLayout( m_racksLayout ); + // add master channel m_fxChannelViews.resize( m->numChannels() ); m_fxChannelViews[0] = new FxChannelView( this, this, 0 ); + m_racksLayout->addWidget( m_fxChannelViews[0]->m_rackView ); + FxChannelView * masterView = m_fxChannelViews[0]; ml->addWidget( masterView->m_fxLine, 0, Qt::AlignTop ); @@ -124,10 +131,8 @@ FxMixerView::FxMixerView() : ml->addWidget( newChannelBtn, 0, Qt::AlignTop ); - // Create EffectRack and set initial index to master channel - m_rackView = new EffectRackView( &m->m_fxChannels[0]->m_fxChain, this ); - m_rackView->setFixedSize( 245, fxLineSize.height() ); - ml->addWidget( m_rackView, 0, Qt::AlignTop ); + // add the stacked layout for the effect racks of fx channels + ml->addWidget( m_racksWidget, 0, Qt::AlignTop ); setCurrentFxLine( m_fxChannelViews[0]->m_fxLine ); @@ -169,7 +174,8 @@ void FxMixerView::addNewChannel() int newChannelIndex = mix->createChannel(); m_fxChannelViews.push_back(new FxChannelView(m_channelAreaWidget, this, newChannelIndex)); - chLayout->addWidget(m_fxChannelViews[newChannelIndex]->m_fxLine); + chLayout->addWidget( m_fxChannelViews[newChannelIndex]->m_fxLine ); + m_racksLayout->addWidget( m_fxChannelViews[newChannelIndex]->m_rackView ); updateFxLine(newChannelIndex); @@ -187,6 +193,7 @@ void FxMixerView::refreshDisplay() delete m_fxChannelViews[i]->m_muteBtn; delete m_fxChannelViews[i]->m_fxLine; delete m_fxChannelViews[i]; + m_racksLayout->removeWidget( m_fxChannelViews[i]->m_rackView ); } m_channelAreaWidget->adjustSize(); @@ -196,6 +203,7 @@ void FxMixerView::refreshDisplay() { m_fxChannelViews[i] = new FxChannelView(m_channelAreaWidget, this, i); chLayout->addWidget(m_fxChannelViews[i]->m_fxLine); + m_racksLayout->addWidget( m_fxChannelViews[i]->m_rackView ); } // set selected fx line to 0 @@ -269,6 +277,10 @@ FxMixerView::FxChannelView::FxChannelView(QWidget * _parent, FxMixerView * _mv, m_muteBtn->setCheckable( true ); m_muteBtn->move( 9, m_fader->y()-16); toolTip::add( m_muteBtn, tr( "Mute this FX channel" ) ); + + // Create EffectRack for the channel + m_rackView = new EffectRackView( &m->effectChannel(_chIndex)->m_fxChain, _mv->m_racksWidget ); + m_rackView->setFixedSize( 245, FxLine::FxLineHeight ); } @@ -276,7 +288,7 @@ void FxMixerView::setCurrentFxLine( FxLine * _line ) { // select m_currentFxLine = _line; - m_rackView->setModel( &engine::fxMixer()->m_fxChannels[_line->channelIndex()]->m_fxChain ); + m_racksLayout->setCurrentWidget( m_fxChannelViews[ _line->channelIndex() ]->m_rackView ); // set up send knob for(int i = 0; i < m_fxChannelViews.size(); ++i) @@ -332,6 +344,9 @@ void FxMixerView::deleteChannel(int index) delete m_fxChannelViews[index]; m_channelAreaWidget->adjustSize(); + // delete the fx rack + m_racksLayout->removeWidget( m_fxChannelViews[index]->m_rackView ); + // make sure every channel knows what index it is for(int i=0; im_muteBtn; delete m_fxChannelViews[i]->m_fxLine; delete m_fxChannelViews[i]; + m_racksLayout->removeWidget( m_fxChannelViews[i]->m_rackView ); // add it again - m_fxChannelViews[i] = new FxChannelView(m_channelAreaWidget, this, i); - chLayout->insertWidget(replaceIndex, m_fxChannelViews[i]->m_fxLine); + m_fxChannelViews[i] = new FxChannelView( m_channelAreaWidget, this, i ); + chLayout->insertWidget( replaceIndex, m_fxChannelViews[i]->m_fxLine ); + m_racksLayout->insertWidget( replaceIndex, m_fxChannelViews[i]->m_rackView ); } // keep selected channel @@ -448,8 +465,6 @@ void FxMixerView::setCurrentFxLine( int _line ) void FxMixerView::clear() { - m_rackView->clearViews(); - engine::fxMixer()->clear(); refreshDisplay(); diff --git a/src/gui/widgets/FxLine.cpp b/src/gui/widgets/FxLine.cpp index a8e30f45e..ac051d799 100644 --- a/src/gui/widgets/FxLine.cpp +++ b/src/gui/widgets/FxLine.cpp @@ -39,13 +39,14 @@ #include "gui_templates.h" #include "caption_menu.h" +const int FxLine::FxLineHeight = 287; FxLine::FxLine( QWidget * _parent, FxMixerView * _mv, int _channelIndex) : QWidget( _parent ), m_mv( _mv ), m_channelIndex( _channelIndex ) { - setFixedSize( 33, 287 ); + setFixedSize( 33, FxLineHeight ); setAttribute( Qt::WA_OpaquePaintEvent, true ); setCursor( QCursor( embed::getIconPixmap( "hand" ), 0, 0 ) ); From b4f0c73beb51e193c243c673ac50626e0f6e08c9 Mon Sep 17 00:00:00 2001 From: Vesa Date: Fri, 20 Jun 2014 02:57:33 +0300 Subject: [PATCH 61/61] Watsyn updates --- plugins/watsyn/Watsyn.cpp | 4 ++-- plugins/watsyn/Watsyn.h | 14 +++++++++++--- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/plugins/watsyn/Watsyn.cpp b/plugins/watsyn/Watsyn.cpp index e088e0931..72af13771 100644 --- a/plugins/watsyn/Watsyn.cpp +++ b/plugins/watsyn/Watsyn.cpp @@ -153,8 +153,8 @@ void WatsynObject::renderOutput( fpp_t _frames ) const float xt = m_parent->m_xtalk.value(); if( xt > 0.0 ) { - B2_L += ( A1_L * xt ) / 100.0f; - B2_R += ( A1_R * xt ) / 100.0f; + B2_L += ( A1_L * xt ) * 0.01f; + B2_R += ( A1_R * xt ) * 0.01f; } // if phase mod, add to phases diff --git a/plugins/watsyn/Watsyn.h b/plugins/watsyn/Watsyn.h index e863f4991..3e0992144 100644 --- a/plugins/watsyn/Watsyn.h +++ b/plugins/watsyn/Watsyn.h @@ -183,17 +183,25 @@ private: inline void srccpy( float * _dst, float * _src ) { int err; + const int margin = 64; + + // copy to temp array + float * tmp = new float [ GRAPHLEN + margin ]; + memcpy( tmp, _src, sizeof( float ) * GRAPHLEN ); + memcpy( tmp + GRAPHLEN, _src, sizeof( float ) * margin ); SRC_STATE * src_state = src_new( SRC_SINC_FASTEST, 1, &err ); SRC_DATA src_data; - src_data.data_in = _src; - src_data.input_frames = GRAPHLEN; + src_data.data_in = tmp; + src_data.input_frames = GRAPHLEN + margin; src_data.data_out = _dst; src_data.output_frames = WAVELEN; src_data.src_ratio = static_cast( WAVERATIO ); - src_data.end_of_input = 1; + src_data.end_of_input = 0; err = src_process( src_state, &src_data ); if( err ) { qDebug( "Watsyn SRC error: %s", src_strerror( err ) ); } src_delete( src_state ); + + delete tmp; } // memcpy utilizing cubic interpolation