diff --git a/AUTHORS b/AUTHORS index 086d6c3a2..579d21dd9 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,6 +1,6 @@ Tobias Doerffel - Maintainer, main-development, artwork etc. + Development Manager Jonathan Aquilina @@ -17,6 +17,10 @@ Danny McRae Javier Serrano Polo Development + +Lukas Wohlschläger + + Development Andrew Kelley @@ -28,7 +32,7 @@ Andreas Brandmaier Juan Fabián Simón - Version 4.0 plugin artwork + Version 0.4 plugin artwork Sebastian Tilsch diff --git a/data/themes/default/add.png b/data/themes/default/add.png index e029787c7..f79fdfdba 100644 Binary files a/data/themes/default/add.png and b/data/themes/default/add.png differ diff --git a/data/themes/default/apply.png b/data/themes/default/apply.png index f547bf179..1ae48682e 100644 Binary files a/data/themes/default/apply.png and b/data/themes/default/apply.png differ diff --git a/data/themes/default/arp_down.png b/data/themes/default/arp_down.png index b0ce4a5cc..85586f7da 100644 Binary files a/data/themes/default/arp_down.png and b/data/themes/default/arp_down.png differ diff --git a/data/themes/default/arp_up.png b/data/themes/default/arp_up.png index 78e7ad37f..07a4ecc7e 100644 Binary files a/data/themes/default/arp_up.png and b/data/themes/default/arp_up.png differ diff --git a/data/themes/default/arp_up_and_down.png b/data/themes/default/arp_up_and_down.png index f72c0c940..513331df7 100644 Binary files a/data/themes/default/arp_up_and_down.png and b/data/themes/default/arp_up_and_down.png differ diff --git a/data/themes/default/autoscroll_off.png b/data/themes/default/autoscroll_off.png index c0a4f37c8..a2d56e672 100644 Binary files a/data/themes/default/autoscroll_off.png and b/data/themes/default/autoscroll_off.png differ diff --git a/data/themes/default/autoscroll_on.png b/data/themes/default/autoscroll_on.png index 29da5c1dc..8c4bb5690 100644 Binary files a/data/themes/default/autoscroll_on.png and b/data/themes/default/autoscroll_on.png differ diff --git a/data/themes/default/back_to_start.png b/data/themes/default/back_to_start.png index 5eb2c12bc..d8b8b73fe 100644 Binary files a/data/themes/default/back_to_start.png and b/data/themes/default/back_to_start.png differ diff --git a/data/themes/default/back_to_zero.png b/data/themes/default/back_to_zero.png index b89c2107a..dfde88b4e 100644 Binary files a/data/themes/default/back_to_zero.png and b/data/themes/default/back_to_zero.png differ diff --git a/data/themes/default/chord.png b/data/themes/default/chord.png index 8aa83cdbe..42165f6b0 100644 Binary files a/data/themes/default/chord.png and b/data/themes/default/chord.png differ diff --git a/data/themes/default/combobox_bg.png b/data/themes/default/combobox_bg.png index 92430c252..83bdb4140 100644 Binary files a/data/themes/default/combobox_bg.png and b/data/themes/default/combobox_bg.png differ diff --git a/data/themes/default/cpuload_bg.png b/data/themes/default/cpuload_bg.png index e0f4a1581..f05db1a06 100644 Binary files a/data/themes/default/cpuload_bg.png and b/data/themes/default/cpuload_bg.png differ diff --git a/data/themes/default/cpuload_leds.png b/data/themes/default/cpuload_leds.png index cbb3bd478..900cd5b46 100644 Binary files a/data/themes/default/cpuload_leds.png and b/data/themes/default/cpuload_leds.png differ diff --git a/data/themes/default/dont_know.png b/data/themes/default/dont_know.png index 21a0cab62..3924a9173 100644 Binary files a/data/themes/default/dont_know.png and b/data/themes/default/dont_know.png differ diff --git a/data/themes/default/edit_select.png b/data/themes/default/edit_select.png index 5019cd89a..11b674a60 100644 Binary files a/data/themes/default/edit_select.png and b/data/themes/default/edit_select.png differ diff --git a/data/themes/default/exp_wave_active.png b/data/themes/default/exp_wave_active.png index 48b4b5a89..22682a150 100644 Binary files a/data/themes/default/exp_wave_active.png and b/data/themes/default/exp_wave_active.png differ diff --git a/data/themes/default/home.png b/data/themes/default/home.png index 647e75338..84051dbb6 100644 Binary files a/data/themes/default/home.png and b/data/themes/default/home.png differ diff --git a/data/themes/default/keep_stop_position.png b/data/themes/default/keep_stop_position.png index 060297da2..561fead25 100644 Binary files a/data/themes/default/keep_stop_position.png and b/data/themes/default/keep_stop_position.png differ diff --git a/data/themes/default/lfo_d100_active.png b/data/themes/default/lfo_d100_active.png index f2a05b555..bb966c579 100644 Binary files a/data/themes/default/lfo_d100_active.png and b/data/themes/default/lfo_d100_active.png differ diff --git a/data/themes/default/lfo_x100_active.png b/data/themes/default/lfo_x100_active.png index 479ff38c1..cb563f432 100644 Binary files a/data/themes/default/lfo_x100_active.png and b/data/themes/default/lfo_x100_active.png differ diff --git a/data/themes/default/lfo_x1_active.png b/data/themes/default/lfo_x1_active.png index 3a44b3e28..2c54a6ab1 100644 Binary files a/data/themes/default/lfo_x1_active.png and b/data/themes/default/lfo_x1_active.png differ diff --git a/data/themes/default/moog_saw_wave_active.png b/data/themes/default/moog_saw_wave_active.png index 9a530a1b3..f6230f6d4 100644 Binary files a/data/themes/default/moog_saw_wave_active.png and b/data/themes/default/moog_saw_wave_active.png differ diff --git a/data/themes/default/note.png b/data/themes/default/note.png index f81425dae..9e80341e0 100644 Binary files a/data/themes/default/note.png and b/data/themes/default/note.png differ diff --git a/data/themes/default/note_double_whole.png b/data/themes/default/note_double_whole.png index 4b1e934bd..f55150f46 100644 Binary files a/data/themes/default/note_double_whole.png and b/data/themes/default/note_double_whole.png differ diff --git a/data/themes/default/note_eighth.png b/data/themes/default/note_eighth.png index f81425dae..f7cac8689 100644 Binary files a/data/themes/default/note_eighth.png and b/data/themes/default/note_eighth.png differ diff --git a/data/themes/default/note_half.png b/data/themes/default/note_half.png index aff73e593..1444bcf11 100644 Binary files a/data/themes/default/note_half.png and b/data/themes/default/note_half.png differ diff --git a/data/themes/default/note_quarter.png b/data/themes/default/note_quarter.png index 6c3acf2cd..acd47baab 100644 Binary files a/data/themes/default/note_quarter.png and b/data/themes/default/note_quarter.png differ diff --git a/data/themes/default/note_sixteenth.png b/data/themes/default/note_sixteenth.png index 661bcb7be..44c900ceb 100644 Binary files a/data/themes/default/note_sixteenth.png and b/data/themes/default/note_sixteenth.png differ diff --git a/data/themes/default/note_thirtysecond.png b/data/themes/default/note_thirtysecond.png index a3daee579..204325edc 100644 Binary files a/data/themes/default/note_thirtysecond.png and b/data/themes/default/note_thirtysecond.png differ diff --git a/data/themes/default/note_tripleteighth.png b/data/themes/default/note_tripleteighth.png index 4e4d214de..3cd7ea452 100644 Binary files a/data/themes/default/note_tripleteighth.png and b/data/themes/default/note_tripleteighth.png differ diff --git a/data/themes/default/note_triplethalf.png b/data/themes/default/note_triplethalf.png index 5c8a7e90c..a2c80fe19 100644 Binary files a/data/themes/default/note_triplethalf.png and b/data/themes/default/note_triplethalf.png differ diff --git a/data/themes/default/note_tripletquarter.png b/data/themes/default/note_tripletquarter.png index 39c037b2a..029a50300 100644 Binary files a/data/themes/default/note_tripletquarter.png and b/data/themes/default/note_tripletquarter.png differ diff --git a/data/themes/default/note_tripletsixteenth.png b/data/themes/default/note_tripletsixteenth.png index a307b542a..31ce41942 100644 Binary files a/data/themes/default/note_tripletsixteenth.png and b/data/themes/default/note_tripletsixteenth.png differ diff --git a/data/themes/default/note_tripletthirtysecond.png b/data/themes/default/note_tripletthirtysecond.png index 20e2ab65a..9f8b31122 100644 Binary files a/data/themes/default/note_tripletthirtysecond.png and b/data/themes/default/note_tripletthirtysecond.png differ diff --git a/data/themes/default/note_whole.png b/data/themes/default/note_whole.png index f178b5023..36c2308b9 100644 Binary files a/data/themes/default/note_whole.png and b/data/themes/default/note_whole.png differ diff --git a/data/themes/default/output_graph.png b/data/themes/default/output_graph.png index b1405a63b..46ec86d44 100644 Binary files a/data/themes/default/output_graph.png and b/data/themes/default/output_graph.png differ diff --git a/data/themes/default/plugins.png b/data/themes/default/plugins.png index b7cff0117..5ba9bc3c9 100644 Binary files a/data/themes/default/plugins.png and b/data/themes/default/plugins.png differ diff --git a/data/themes/default/preset_file.png b/data/themes/default/preset_file.png index c9897ae40..53a0d1159 100644 Binary files a/data/themes/default/preset_file.png and b/data/themes/default/preset_file.png differ diff --git a/data/themes/default/project_file.png b/data/themes/default/project_file.png index db0fe6e1f..724ab5cfb 100644 Binary files a/data/themes/default/project_file.png and b/data/themes/default/project_file.png differ diff --git a/data/themes/default/round_square_wave_active.png b/data/themes/default/round_square_wave_active.png index b2d794d39..0dfe2093a 100644 Binary files a/data/themes/default/round_square_wave_active.png and b/data/themes/default/round_square_wave_active.png differ diff --git a/data/themes/default/sample_file.png b/data/themes/default/sample_file.png index 30814a1b9..f2ed8d46e 100644 Binary files a/data/themes/default/sample_file.png and b/data/themes/default/sample_file.png differ diff --git a/data/themes/default/saw_wave_active.png b/data/themes/default/saw_wave_active.png index 648910b6b..62bffcc33 100644 Binary files a/data/themes/default/saw_wave_active.png and b/data/themes/default/saw_wave_active.png differ diff --git a/data/themes/default/scale.png b/data/themes/default/scale.png index fa680ab76..4b6e1427f 100644 Binary files a/data/themes/default/scale.png and b/data/themes/default/scale.png differ diff --git a/data/themes/default/sin_wave_active.png b/data/themes/default/sin_wave_active.png index 57e06d408..ec7bf0a7d 100644 Binary files a/data/themes/default/sin_wave_active.png and b/data/themes/default/sin_wave_active.png differ diff --git a/data/themes/default/square_wave_active.png b/data/themes/default/square_wave_active.png index a79a22b98..487b5aff7 100644 Binary files a/data/themes/default/square_wave_active.png and b/data/themes/default/square_wave_active.png differ diff --git a/data/themes/default/style.css b/data/themes/default/style.css index 0d199ba12..d1c741e95 100644 --- a/data/themes/default/style.css +++ b/data/themes/default/style.css @@ -104,6 +104,15 @@ QScrollBar:vertical { margin: 13px 0px; } +visualizationWidget { + background: none; + border: none; +} + +cpuloadWidget { + border: none; + background: url(resources:cpuload_bg.png); +} /* scrollbar: trough clicky things */ QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal, @@ -472,6 +481,14 @@ sf2InstrumentView knob { qproperty-lineWidth: 2; } +sfxrInstrumentView knob { + color: #b06319; + qproperty-outerColor: rgb(194, 177, 145); + qproperty-innerRadius: 2; + qproperty-outerRadius: 10; + qproperty-lineWidth: 2; +} + opl2instrumentView knob { color: rgb(128,128,128); qproperty-outerColor: rgb(255,255,255); diff --git a/data/themes/default/trackop.png b/data/themes/default/trackop.png index dcb8036e2..bc089652e 100644 Binary files a/data/themes/default/trackop.png and b/data/themes/default/trackop.png differ diff --git a/data/themes/default/trackop_c.png b/data/themes/default/trackop_c.png index fbd6343dd..418e4f8eb 100644 Binary files a/data/themes/default/trackop_c.png and b/data/themes/default/trackop_c.png differ diff --git a/data/themes/default/trackop_h.png b/data/themes/default/trackop_h.png index df1ad5642..b88839a0d 100644 Binary files a/data/themes/default/trackop_h.png and b/data/themes/default/trackop_h.png differ diff --git a/data/themes/default/triangle_wave_active.png b/data/themes/default/triangle_wave_active.png index 79a4c6807..f3ef94abc 100644 Binary files a/data/themes/default/triangle_wave_active.png and b/data/themes/default/triangle_wave_active.png differ diff --git a/data/themes/default/usr_wave_active.png b/data/themes/default/usr_wave_active.png index 336ca87c6..2309967d5 100644 Binary files a/data/themes/default/usr_wave_active.png and b/data/themes/default/usr_wave_active.png differ diff --git a/data/themes/default/white_noise_wave_active.png b/data/themes/default/white_noise_wave_active.png index 8c8fa9d7f..38b089c63 100644 Binary files a/data/themes/default/white_noise_wave_active.png and b/data/themes/default/white_noise_wave_active.png differ diff --git a/include/preset_preview_play_handle.h b/include/preset_preview_play_handle.h index 3e4d4e53c..e5185cfbe 100644 --- a/include/preset_preview_play_handle.h +++ b/include/preset_preview_play_handle.h @@ -51,6 +51,8 @@ public: static ConstNotePlayHandleList nphsOfInstrumentTrack( const InstrumentTrack * _ct ); + static bool isPreviewing(); + private: static previewTrackContainer * s_previewTC; diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 0cbdc4359..6f315b792 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -15,6 +15,7 @@ ADD_SUBDIRECTORY(papu) ADD_SUBDIRECTORY(patman) ADD_SUBDIRECTORY(peak_controller_effect) ADD_SUBDIRECTORY(sf2_player) +ADD_SUBDIRECTORY(sfxr) ADD_SUBDIRECTORY(sid) ADD_SUBDIRECTORY(spectrum_analyzer) ADD_SUBDIRECTORY(stereo_enhancer) diff --git a/plugins/ladspa_effect/swh/vocoder_1337.c b/plugins/ladspa_effect/swh/vocoder_1337.c new file mode 100644 index 000000000..086faffb5 --- /dev/null +++ b/plugins/ladspa_effect/swh/vocoder_1337.c @@ -0,0 +1,456 @@ +/* vocoder.c + Version 0.3 + + LADSPA Unique ID: 1337 + + Version 0.31 + Added stereo output, renamed input/output ports, added, + added a control for stereo balance + + Version 0.3 + Added support for changing bands in real time 2003-12-09 + + Version 0.2 + Adapted to LADSPA by Josh Green + 15.6.2001 (for the LinuxTag 2001!) + + Original program can be found at: + http://www.sirlab.de/linux/ + Author: Achim Settelmeier + + Adapted to LMMS by Hexasoft (hexasoft.corp@free.fr) + + + Licence: GPL + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +*/ + + +/* not familiar with WINDOWS stuff. Saw this in other sources, it should be needed */ + +#ifdef WIN32 +#define _WINDOWS_DLL_EXPORT_ __declspec(dllexport) +int bIsFirstTime = 1; +void _init(); // forward declaration +#else +#define _WINDOWS_DLL_EXPORT_ +#endif + + +/*****************************************************************************/ +/* general includes */ +#include +#include +#include +#include + +/*****************************************************************************/ +/* LADSPA headers */ +#include + +/*****************************************************************************/ + + +#define LADSPA_UNIQUE_ID 1337 + +#define MAX_BANDS 16 /* max 16 bandsn should be increased */ +#define AMPLIFIER 16.0 + +struct bandpass +{ + LADSPA_Data c, f, att; + + LADSPA_Data freq; + LADSPA_Data low1, low2; + LADSPA_Data mid1, mid2; + LADSPA_Data high1, high2; + LADSPA_Data y; +}; + +struct bands_out{ + LADSPA_Data decay; + LADSPA_Data oldval; + LADSPA_Data level; /* 0.0 - 1.0 level of this output band */ +}; + +const LADSPA_Data decay_table[] = +{ + 1/100.0, + 1/100.0, 1/100.0, 1/100.0, + 1/125.0, 1/125.0, 1/125.0, + 1/166.0, 1/166.0, 1/166.0, + 1/200.0, 1/200.0, 1/200.0, + 1/250.0, 1/250.0, 1/250.0 +}; + +/* The port numbers for the plugin: */ + +#define PORT_FORMANT 0 /* the track to "vocodify */ +#define PORT_CARRIER 1 /* the track to control 1st track */ +#define PORT_OUTPUT 2 /* left output */ +#define PORT_OUTPUT2 3 /* right output */ +#define CTRL_BANDCOUNT 4 /* selected # of bands to use */ +#define CTRL_PAN 5 /* stereo balance for outputs */ +#define CTRL_BAND1LVL 6 /* start of bands level */ + +#define PORT_COUNT 6 + MAX_BANDS /* bands level */ + + +/* useful macros */ +#undef CLAMP +#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x))) + +/* Instance data for the vocoder plugin */ +typedef struct { + LADSPA_Data SampleRate; + + int num_bands; /* current number of bands */ + float mainvol; /* main volume */ + + struct bandpass bands_formant[MAX_BANDS]; /* one structure per band */ + struct bandpass bands_carrier[MAX_BANDS]; /* one structure per band */ + struct bands_out bands_out[MAX_BANDS]; /* one structure per band */ + + /* Ports */ + + LADSPA_Data * portFormant; /* Formant signal port data location */ + LADSPA_Data * portCarrier; /* Carrier signal port data location */ + LADSPA_Data * portOutput; /* Output audio port data location */ + LADSPA_Data * portOutput2; /* Output audio port data location (copy of previous one) */ + LADSPA_Data * ctrlPan; /* PAN for output */ + LADSPA_Data * ctrlBandCount; /* Band count control */ + LADSPA_Data * ctrlBandLevels[MAX_BANDS]; /* level controls for each band */ + +} VocoderInstance; + +/*****************************************************************************/ + +/* Construct a new plugin instance. */ +LADSPA_Handle +instantiateVocoder(const LADSPA_Descriptor * Descriptor, + unsigned long SampleRate) { + VocoderInstance * vocoder; + + vocoder = (VocoderInstance *)malloc(sizeof(VocoderInstance)); + + if (vocoder == NULL) + return NULL; + + vocoder->SampleRate = (LADSPA_Data)SampleRate; + vocoder->num_bands = -1; + + return vocoder; +} + +/*****************************************************************************/ + +/* Initialise and activate a plugin instance. */ +void +activateVocoder(LADSPA_Handle Instance) { + VocoderInstance *vocoder = (VocoderInstance *)Instance; + int i; + + vocoder->mainvol = 1.0 * AMPLIFIER; + + for (i = 0; i < MAX_BANDS; i++) + vocoder->bands_out[i].oldval = 0.0; +} + +/*****************************************************************************/ + +/* Connect a port to a data location. */ +void +connectPortToVocoder(LADSPA_Handle Instance, + unsigned long Port, + LADSPA_Data * DataLocation) { + + VocoderInstance * vocoder; + + vocoder = (VocoderInstance *)Instance; + switch (Port) { + case PORT_FORMANT: /* formant port? */ + vocoder->portFormant = DataLocation; + break; + case PORT_CARRIER: /* carrier port? */ + vocoder->portCarrier = DataLocation; + break; + case PORT_OUTPUT: /* output port? */ + vocoder->portOutput = DataLocation; + break; + case PORT_OUTPUT2: /* output port? */ + vocoder->portOutput2 = DataLocation; + break; + case CTRL_BANDCOUNT: /* band count control? */ + vocoder->ctrlBandCount = DataLocation; + break; + case CTRL_PAN: /* Pan control? */ + vocoder->ctrlPan = DataLocation; + break; + default: /* a band level control? */ + if (Port >= CTRL_BAND1LVL && Port < CTRL_BAND1LVL + MAX_BANDS) + vocoder->ctrlBandLevels[Port - CTRL_BAND1LVL] = DataLocation; + break; + } +} + +/*****************************************************************************/ + +// vocoder_do_bandpasses /*fold00*/ +void vocoder_do_bandpasses(struct bandpass *bands, LADSPA_Data sample, + VocoderInstance *vocoder) +{ + int i; + for (i=0; i < vocoder->num_bands; i++) + { + bands[i].high1 = sample - bands[i].f * bands[i].mid1 - bands[i].low1; + bands[i].mid1 += bands[i].high1 * bands[i].c; + bands[i].low1 += bands[i].mid1; + + bands[i].high2 = bands[i].low1 - bands[i].f * bands[i].mid2 + - bands[i].low2; + bands[i].mid2 += bands[i].high2 * bands[i].c; + bands[i].low2 += bands[i].mid2; + bands[i].y = bands[i].high2 * bands[i].att; + } +} + +/* Run a vocoder instance for a block of SampleCount samples. */ +void +runVocoder(LADSPA_Handle Instance, + unsigned long SampleCount) +{ + VocoderInstance *vocoder = (VocoderInstance *)Instance; + int i, j, numbands, pan; + float a; + LADSPA_Data x, c; + float fl, fr; + + numbands = (int)(*vocoder->ctrlBandCount); + if (numbands < 1 || numbands > MAX_BANDS) numbands = MAX_BANDS; + + /* initialize bandpass information if num_bands control has changed, + or on first run */ + if (vocoder->num_bands != numbands) + { + vocoder->num_bands = numbands; + + for(i=0; i < numbands; i++) + { + memset(&vocoder->bands_formant[i], 0, sizeof(struct bandpass)); + + a = 16.0 * i/(double)numbands; // stretch existing bands + + if (a < 4.0) + vocoder->bands_formant[i].freq = 150 + 420 * a / 4.0; + else + vocoder->bands_formant[i].freq = 600 * pow (1.23, a - 4.0); + + c = vocoder->bands_formant[i].freq * 2 * M_PI / vocoder->SampleRate; + vocoder->bands_formant[i].c = c * c; + + vocoder->bands_formant[i].f = 0.4/c; + vocoder->bands_formant[i].att = + 1/(6.0 + ((exp (vocoder->bands_formant[i].freq + / vocoder->SampleRate) - 1) * 10)); + + memcpy(&vocoder->bands_carrier[i], + &vocoder->bands_formant[i], sizeof(struct bandpass)); + + vocoder->bands_out[i].decay = decay_table[(int)a]; + vocoder->bands_out[i].level = + CLAMP (*vocoder->ctrlBandLevels[i], 0.0, 1.0); + } + } + else /* get current values of band level controls */ + { + for (i = 0; i < numbands; i++) + vocoder->bands_out[i].level = CLAMP (*vocoder->ctrlBandLevels[i], + 0.0, 1.0); + } + + for (i=0; i < SampleCount; i++) + { + vocoder_do_bandpasses (vocoder->bands_carrier, + vocoder->portCarrier[i], vocoder); + vocoder_do_bandpasses (vocoder->bands_formant, + vocoder->portFormant[i], vocoder); + + vocoder->portOutput[i] = 0.0; + vocoder->portOutput2[i] = 0.0; + for (j=0; j < numbands; j++) + { + vocoder->bands_out[j].oldval = vocoder->bands_out[j].oldval + + (fabs (vocoder->bands_formant[j].y) + - vocoder->bands_out[j].oldval) + * vocoder->bands_out[j].decay; + x = vocoder->bands_carrier[j].y * vocoder->bands_out[j].oldval; + vocoder->portOutput[i] += x * vocoder->bands_out[j].level; + vocoder->portOutput2[i] += x * vocoder->bands_out[j].level; + } + /* treat paning + main volume */ + pan = (int)(*vocoder->ctrlPan); + fl = fr = 1.; + if (pan != 0) { /* no paning, don't compute useless values */ + if (pan > 0) { /* reduce left */ + fl = (100.-pan)/100.; + } else { + fr = (100.+pan)/100.; + } + } + /* apply volume and paning */ + vocoder->portOutput[i] *= vocoder->mainvol * fl; + vocoder->portOutput2[i] *= vocoder->mainvol * fr; + } +} + + +/*****************************************************************************/ + +/* Throw away a vocoder instance. */ +void +cleanupVocoder(LADSPA_Handle Instance) +{ + VocoderInstance * Vocoder; + Vocoder = (VocoderInstance *)Instance; + free(Vocoder); +} + +/*****************************************************************************/ + +LADSPA_Descriptor * g_psDescriptor = NULL; + +/*****************************************************************************/ + +/* _init() is called automatically when the plugin library is first + loaded. */ +void +_init() { + char ** pcPortNames; + LADSPA_PortDescriptor * piPortDescriptors; + LADSPA_PortRangeHint * psPortRangeHints; + int i; + + g_psDescriptor = (LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor)); + + if (g_psDescriptor) { + g_psDescriptor->UniqueID = LADSPA_UNIQUE_ID; + g_psDescriptor->Label = strdup("vocoder-lmms"); + g_psDescriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE; + g_psDescriptor->Name = strdup("Vocoder for LMMS"); + g_psDescriptor->Maker = strdup("Achim Settelmeier (adapted to LADSPA by Josh Green, adapted to LMMS by Hexasoft)"); + g_psDescriptor->Copyright = strdup("GPL"); + g_psDescriptor->PortCount = PORT_COUNT; + piPortDescriptors = (LADSPA_PortDescriptor *)calloc(PORT_COUNT, + sizeof(LADSPA_PortDescriptor)); + g_psDescriptor->PortDescriptors + = (const LADSPA_PortDescriptor *)piPortDescriptors; + piPortDescriptors[PORT_FORMANT] + = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO; + piPortDescriptors[PORT_CARRIER] + = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO; + piPortDescriptors[PORT_OUTPUT] + = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO; + piPortDescriptors[PORT_OUTPUT2] + = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO; + piPortDescriptors[CTRL_BANDCOUNT] + = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL; + piPortDescriptors[CTRL_PAN] + = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL; + + pcPortNames = (char **)calloc(PORT_COUNT, sizeof(char *)); + g_psDescriptor->PortNames = (const char **)pcPortNames; + pcPortNames[PORT_FORMANT] = strdup("Formant-in"); + pcPortNames[PORT_CARRIER] = strdup("Carrier-in"); + pcPortNames[PORT_OUTPUT] = strdup("Output-out"); + pcPortNames[PORT_OUTPUT2] = strdup("Output2-out"); + pcPortNames[CTRL_BANDCOUNT] = strdup("Number of bands"); + pcPortNames[CTRL_PAN] = strdup("Left/Right"); + + psPortRangeHints = ((LADSPA_PortRangeHint *) + calloc(PORT_COUNT, sizeof(LADSPA_PortRangeHint))); + g_psDescriptor->PortRangeHints + = (const LADSPA_PortRangeHint *)psPortRangeHints; + psPortRangeHints[PORT_FORMANT].HintDescriptor = 0; + psPortRangeHints[PORT_CARRIER].HintDescriptor = 0; + psPortRangeHints[PORT_OUTPUT].HintDescriptor = 0; + psPortRangeHints[PORT_OUTPUT2].HintDescriptor = 0; + psPortRangeHints[CTRL_BANDCOUNT].HintDescriptor + = LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE + | LADSPA_HINT_INTEGER; + psPortRangeHints[CTRL_BANDCOUNT].LowerBound = 1; + psPortRangeHints[CTRL_BANDCOUNT].UpperBound = MAX_BANDS; + psPortRangeHints[CTRL_PAN].HintDescriptor + = LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE + | LADSPA_HINT_INTEGER; + psPortRangeHints[CTRL_PAN].LowerBound = -100; + psPortRangeHints[CTRL_PAN].UpperBound = +100; + + for (i=CTRL_BAND1LVL; i < CTRL_BAND1LVL + MAX_BANDS; i++) + { + piPortDescriptors[i] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL; + pcPortNames[i] = malloc (sizeof ("Band 99 Level")); + sprintf(pcPortNames[i], "Band %d Level", i - CTRL_BAND1LVL + 1); + psPortRangeHints[i].HintDescriptor + = LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE; + psPortRangeHints[i].LowerBound = 0; + psPortRangeHints[i].UpperBound = 1; + } + + g_psDescriptor->instantiate = instantiateVocoder; + g_psDescriptor->connect_port = connectPortToVocoder; + g_psDescriptor->activate = activateVocoder; + g_psDescriptor->run = runVocoder; + g_psDescriptor->run_adding = NULL; + g_psDescriptor->set_run_adding_gain = NULL; + g_psDescriptor->deactivate = NULL; + g_psDescriptor->cleanup = cleanupVocoder; + } +} + +/*****************************************************************************/ + +/* _fini() is called automatically when the library is unloaded. */ +void +_fini() { + long lIndex; + if (g_psDescriptor) { + free((char *)g_psDescriptor->Label); + free((char *)g_psDescriptor->Name); + free((char *)g_psDescriptor->Maker); + free((char *)g_psDescriptor->Copyright); + free((LADSPA_PortDescriptor *)g_psDescriptor->PortDescriptors); + for (lIndex = 0; lIndex < g_psDescriptor->PortCount; lIndex++) + free((char *)(g_psDescriptor->PortNames[lIndex])); + free((char **)g_psDescriptor->PortNames); + free((LADSPA_PortRangeHint *)g_psDescriptor->PortRangeHints); + free(g_psDescriptor); + } +} + +/*****************************************************************************/ + +/* Return a descriptor of the requested plugin type. Only one plugin + type is available in this library. */ +const LADSPA_Descriptor * +ladspa_descriptor(unsigned long Index) { + if (Index == 0) + return g_psDescriptor; + else + return NULL; +} + +/*****************************************************************************/ + +/* EOF */ diff --git a/plugins/peak_controller_effect/artwork.png b/plugins/peak_controller_effect/artwork.png index 1c5d5defb..31296ca90 100644 Binary files a/plugins/peak_controller_effect/artwork.png and b/plugins/peak_controller_effect/artwork.png differ diff --git a/plugins/peak_controller_effect/peak_controller_effect.cpp b/plugins/peak_controller_effect/peak_controller_effect.cpp index f9b4049c5..4069c941b 100644 --- a/plugins/peak_controller_effect/peak_controller_effect.cpp +++ b/plugins/peak_controller_effect/peak_controller_effect.cpp @@ -81,6 +81,7 @@ PeakControllerEffect::~PeakControllerEffect() if( idx >= 0 ) { PeakController::s_effects.remove( idx ); + engine::getSong()->removeController( m_autoController ); } } diff --git a/plugins/peak_controller_effect/peak_controller_effect_controls.cpp b/plugins/peak_controller_effect/peak_controller_effect_controls.cpp index eb7e5191d..34ee79a11 100644 --- a/plugins/peak_controller_effect/peak_controller_effect_controls.cpp +++ b/plugins/peak_controller_effect/peak_controller_effect_controls.cpp @@ -29,6 +29,7 @@ #include "PeakController.h" #include "peak_controller_effect_controls.h" #include "peak_controller_effect.h" +#include "preset_preview_play_handle.h" PeakControllerEffectControls:: @@ -66,7 +67,7 @@ void PeakControllerEffectControls::loadSettings( const QDomElement & _this ) } m_effect->m_effectId = effectId; - if( m_effect->m_autoController ) + if( m_effect->m_autoController && presetPreviewPlayHandle::isPreviewing() == false ) { delete m_effect->m_autoController; m_effect->m_autoController = 0; diff --git a/plugins/sfxr/CMakeLists.txt b/plugins/sfxr/CMakeLists.txt new file mode 100644 index 000000000..2fe490d1e --- /dev/null +++ b/plugins/sfxr/CMakeLists.txt @@ -0,0 +1,3 @@ +INCLUDE(BuildPlugin) + +BUILD_PLUGIN(sfxr sfxr.cpp sfxr.h MOCFILES sfxr.h EMBEDDED_RESOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.png) diff --git a/plugins/sfxr/artwork.png b/plugins/sfxr/artwork.png new file mode 100644 index 000000000..15f313d45 Binary files /dev/null and b/plugins/sfxr/artwork.png differ diff --git a/plugins/sfxr/blip_active.png b/plugins/sfxr/blip_active.png new file mode 100644 index 000000000..f3113f772 Binary files /dev/null and b/plugins/sfxr/blip_active.png differ diff --git a/plugins/sfxr/blip_inactive.png b/plugins/sfxr/blip_inactive.png new file mode 100644 index 000000000..e8e5ca112 Binary files /dev/null and b/plugins/sfxr/blip_inactive.png differ diff --git a/plugins/sfxr/explosion_active.png b/plugins/sfxr/explosion_active.png new file mode 100644 index 000000000..b6af2a916 Binary files /dev/null and b/plugins/sfxr/explosion_active.png differ diff --git a/plugins/sfxr/explosion_inactive.png b/plugins/sfxr/explosion_inactive.png new file mode 100644 index 000000000..67c89f013 Binary files /dev/null and b/plugins/sfxr/explosion_inactive.png differ diff --git a/plugins/sfxr/hit_active.png b/plugins/sfxr/hit_active.png new file mode 100644 index 000000000..5bc6c9a14 Binary files /dev/null and b/plugins/sfxr/hit_active.png differ diff --git a/plugins/sfxr/hit_inactive.png b/plugins/sfxr/hit_inactive.png new file mode 100644 index 000000000..a16f7eca3 Binary files /dev/null and b/plugins/sfxr/hit_inactive.png differ diff --git a/plugins/sfxr/jump_active.png b/plugins/sfxr/jump_active.png new file mode 100644 index 000000000..6f1ff1ee5 Binary files /dev/null and b/plugins/sfxr/jump_active.png differ diff --git a/plugins/sfxr/jump_inactive.png b/plugins/sfxr/jump_inactive.png new file mode 100644 index 000000000..cc67812eb Binary files /dev/null and b/plugins/sfxr/jump_inactive.png differ diff --git a/plugins/sfxr/laser_active.png b/plugins/sfxr/laser_active.png new file mode 100644 index 000000000..04a5de94c Binary files /dev/null and b/plugins/sfxr/laser_active.png differ diff --git a/plugins/sfxr/laser_inactive.png b/plugins/sfxr/laser_inactive.png new file mode 100644 index 000000000..bf7eb18d1 Binary files /dev/null and b/plugins/sfxr/laser_inactive.png differ diff --git a/plugins/sfxr/logo.png b/plugins/sfxr/logo.png new file mode 100644 index 000000000..a39e4e865 Binary files /dev/null and b/plugins/sfxr/logo.png differ diff --git a/plugins/sfxr/mutate_active.png b/plugins/sfxr/mutate_active.png new file mode 100644 index 000000000..31cf797b1 Binary files /dev/null and b/plugins/sfxr/mutate_active.png differ diff --git a/plugins/sfxr/mutate_inactive.png b/plugins/sfxr/mutate_inactive.png new file mode 100644 index 000000000..31afa4c0e Binary files /dev/null and b/plugins/sfxr/mutate_inactive.png differ diff --git a/plugins/sfxr/pickup_active.png b/plugins/sfxr/pickup_active.png new file mode 100644 index 000000000..69c81b33c Binary files /dev/null and b/plugins/sfxr/pickup_active.png differ diff --git a/plugins/sfxr/pickup_inactive.png b/plugins/sfxr/pickup_inactive.png new file mode 100644 index 000000000..a4502ce56 Binary files /dev/null and b/plugins/sfxr/pickup_inactive.png differ diff --git a/plugins/sfxr/powerup_active.png b/plugins/sfxr/powerup_active.png new file mode 100644 index 000000000..6be7826cc Binary files /dev/null and b/plugins/sfxr/powerup_active.png differ diff --git a/plugins/sfxr/powerup_inactive.png b/plugins/sfxr/powerup_inactive.png new file mode 100644 index 000000000..c12fc18f9 Binary files /dev/null and b/plugins/sfxr/powerup_inactive.png differ diff --git a/plugins/sfxr/randomize_active.png b/plugins/sfxr/randomize_active.png new file mode 100644 index 000000000..e730c42fe Binary files /dev/null and b/plugins/sfxr/randomize_active.png differ diff --git a/plugins/sfxr/randomize_inactive.png b/plugins/sfxr/randomize_inactive.png new file mode 100644 index 000000000..147c75f70 Binary files /dev/null and b/plugins/sfxr/randomize_inactive.png differ diff --git a/plugins/sfxr/readme.txt b/plugins/sfxr/readme.txt new file mode 100644 index 000000000..27882c77f --- /dev/null +++ b/plugins/sfxr/readme.txt @@ -0,0 +1,170 @@ +This is a port of sfxr to LMMS, ported by Wong Cho Ching. + +NOTE: Do NOT remove the MIT license below to prevent legal problem. +Original Readme File: + +(http://www.drpetter.se/project_sfxr.html) + +----------------------------- +sfxr - sound effect generator +----------------------------- + by DrPetter, 2007-12-14 + developed for LD48#10 +----------------------------- + + +Basic usage: + +Start the application, then hit +some of the buttons on the left +side to generate random sounds +matching the button descriptions. + +Press "Export .WAV" to save the +current sound as a WAV audio file. +Click the buttons below to change +WAV format in terms of bits per +sample and sample rate. + +If you find a sound that is sort +of interesting but not quite what +you want, you can drag some sliders +around until it sounds better. + +The Randomize button generates +something completely random. + +Mutate slightly alters the current +parameters to automatically create +a variation of the sound. + + + +Advanced usage: + +Figure out what each slider does and +use them to adjust particular aspects +of the current sound... + +Press the right mouse button on a slider +to reset it to a value of zero. + +Press Space or Enter to play the current sound. + +The Save/Load sound buttons allow saving +and loading of program parameters to work +on a sound over several sessions. + +Volume setting is saved with the sound and +exported to WAV. If you increase it too much +there's a risk of clipping. + +Some parameters influence the sound during +playback (particularly when using a non-zero +repeat speed), and dragging these sliders +can cause some interesting effects. +To record this you will need to use an external +recording application, for instance Audacity. +Set the recording source in that application +to "Wave", "Stereo Mix", "Mixed Output" or similar. + +Using an external sound editor to capture and edit +sound can also be used to string several sounds +together for more complex results. + +Parameter description: +- The top four buttons select base waveform +- First four parameters control the volume envelope + Attack is the beginning of the sound, + longer attack means a smoother start. + Sustain is how long the volume is held constant + before fading out. + Increase Sustain Punch to cause a popping + effect with increased (and falling) volume + during the sustain phase. + Decay is the fade-out time. +- Next six are for controlling the sound pitch or + frequency. + Start frequency is pretty obvious. Has a large + impact on the overall sound. + Min frequency represents a cutoff that stops all + sound if it's passed during a downward slide. + Slide sets the speed at which the frequency should + be swept (up or down). + Delta slide is the "slide of slide", or rate of change + in the slide speed. + Vibrato depth/speed makes for an oscillating + frequency effect at various strengths and rates. +- Then we have two parameters for causing an abrupt + change in pitch after a ceratin delay. + Amount is pitch change (up or down) + and Speed indicates time to wait before changing + the pitch. +- Following those are two parameters specific to the + squarewave waveform. + The duty cycle of a square describes its shape + in terms of how large the positive vs negative + sections are. It can be swept up or down by + changing the second parameter. +- Repeat speed, when not zero, causes the frequency + and duty parameters to be reset at regular intervals + while the envelope and filter continue unhindered. + This can make for some interesting pulsating effects. +- Phaser offset overlays a delayed copy of the audio + stream on top of itself, resulting in a kind of tight + reverb or sci-fi effect. + This parameter can also be swept like many others. +- Finally, the bottom five sliders control two filters + which are applied after all other effects. + The first one is a resonant lowpass filter which has + a sweepable cutoff frequency. + The other is a highpass filter which can be used to + remove undesired low frequency hum in "light" sounds. + + +---------------------- + + +License +------- + +Basically, I don't care what you do with it, anything goes. + +To please all the troublesome folks who request a formal license, +I attach the "MIT license" as follows: + +-- + +Copyright (c) 2007 Tomas Pettersson + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + + + +---------------------- + +http://www.drpetter.se + + drpetter@gmail.com + +---------------------- + diff --git a/plugins/sfxr/sfxr.cpp b/plugins/sfxr/sfxr.cpp new file mode 100644 index 000000000..01beac525 --- /dev/null +++ b/plugins/sfxr/sfxr.cpp @@ -0,0 +1,1052 @@ +/* + * sfxr.cpp - port of sfxr to LMMS + * Originally written by Tomas Pettersson. For the original license, + * please read readme.txt in this directory + * + * Copyright (c) 2014 Wong Cho Ching + * + * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + */ + +#include + +#define rnd(n) (rand()%(n+1)) + +#define PI 3.14159265f + +float frnd(float range) +{ + return (float)rnd(10000)/10000*range; +} + + +#include + +#include "sfxr.h" +#include "engine.h" +#include "InstrumentTrack.h" +#include "knob.h" +#include "note_play_handle.h" +#include "pixmap_button.h" +#include "song_editor.h" +#include "templates.h" +#include "tooltip.h" +#include "song.h" + +#include "embed.cpp" + +extern "C" +{ + +Plugin::Descriptor PLUGIN_EXPORT sfxr_plugin_descriptor = +{ + STRINGIFY( PLUGIN_NAME ), + "sfxr", + QT_TRANSLATE_NOOP( "pluginBrowser", + "LMMS port of sfxr" ), + "Wong Cho Ching", + 0x0100, + Plugin::Instrument, + new PluginPixmapLoader( "logo" ), + NULL, + NULL +} ; + +} + + + + +SfxrSynth::SfxrSynth( const sfxrInstrument * s ): + s(s), + playing_sample( true ) +{ + resetSample( false ); +} + + + + +SfxrSynth::~SfxrSynth() +{ + +} + + + + +void SfxrSynth::resetSample( bool restart ) +{ + if(!restart) + { + phase=0; + } + fperiod=100.0/(s->m_startFreqModel.value()*s->m_startFreqModel.value()+0.001); + period=(int)fperiod; + fmaxperiod=100.0/(s->m_minFreqModel.value()*s->m_minFreqModel.value()+0.001); + fslide=1.0-pow((double)s->m_slideModel.value(), 3.0)*0.01; + fdslide=-pow((double)s->m_dSlideModel.value(), 3.0)*0.000001; + square_duty=0.5f-s->m_sqrDutyModel.value()*0.5f; + square_slide=-s->m_sqrSweepModel.value()*0.00005f; + if(s->m_changeAmtModel.value()>=0.0f) + arp_mod=1.0-pow((double)s->m_changeAmtModel.value(), 2.0)*0.9; + else + arp_mod=1.0+pow((double)s->m_changeAmtModel.value(), 2.0)*10.0; + arp_time=0; + arp_limit=(int)(pow(1.0f-s->m_changeSpeedModel.value(), 2.0f)*20000+32); + if(s->m_changeSpeedModel.value()==1.0f) + arp_limit=0; + if(!restart) + { + // reset filter + fltp=0.0f; + fltdp=0.0f; + fltw=pow(s->m_lpFilCutModel.value(), 3.0f)*0.1f; + fltw_d=1.0f+s->m_lpFilCutSweepModel.value()*0.0001f; + fltdmp=5.0f/(1.0f+pow(s->m_lpFilResoModel.value(), 2.0f)*20.0f)*(0.01f+fltw); + if(fltdmp>0.8f) fltdmp=0.8f; + fltphp=0.0f; + flthp=pow(s->m_hpFilCutModel.value(), 2.0f)*0.1f; + flthp_d=1.0+s->m_hpFilCutSweepModel.value()*0.0003f; + // reset vibrato + vib_phase=0.0f; + vib_speed=pow(s->m_vibSpeedModel.value(), 2.0f)*0.01f; + vib_amp=s->m_vibDepthModel.value()*0.5f; + // reset envelope + env_vol=0.0f; + env_stage=0; + env_time=0; + env_length[0]=(int)(s->m_attModel.value()*s->m_attModel.value()*100000.0f); + env_length[1]=(int)(s->m_holdModel.value()*s->m_holdModel.value()*100000.0f); + env_length[2]=(int)(s->m_decModel.value()*s->m_decModel.value()*100000.0f); + + fphase=pow(s->m_phaserOffsetModel.value(), 2.0f)*1020.0f; + if(s->m_phaserOffsetModel.value()<0.0f) fphase=-fphase; + fdphase=pow(s->m_phaserSweepModel.value(), 2.0f)*1.0f; + if(s->m_phaserSweepModel.value()<0.0f) fdphase=-fdphase; + iphase=abs((int)fphase); + ipp=0; + for(int i=0;i<1024;i++) + phaser_buffer[i]=0.0f; + + for(int i=0;i<32;i++) + noise_buffer[i]=frnd(2.0f)-1.0f; + + rep_time=0; + rep_limit=(int)(pow(1.0f-s->m_repeatSpeedModel.value(), 2.0f)*20000+32); + if(s->m_repeatSpeedModel.value()==0.0f) + rep_limit=0; + } +} + + + + +void SfxrSynth::update( sampleFrame * buffer, const fpp_t frameNum ) +{ + for(int i=0;i=rep_limit) + { + rep_limit=0; + resetSample(true); + } + + // frequency envelopes/arpeggios + arp_time++; + if(arp_limit!=0 && arp_time>=arp_limit) + { + arp_limit=0; + fperiod*=arp_mod; + } + fslide+=fdslide; + fperiod*=fslide; + if(fperiod>fmaxperiod) + { + fperiod=fmaxperiod; + if(s->m_minFreqModel.value()>0.0f) + playing_sample=false; + } + float rfperiod=fperiod; + if(vib_amp>0.0f) + { + vib_phase+=vib_speed; + rfperiod=fperiod*(1.0+sin(vib_phase)*vib_amp); + } + period=(int)rfperiod; + if(period<8) period=8; + square_duty+=square_slide; + if(square_duty<0.0f) square_duty=0.0f; + if(square_duty>0.5f) square_duty=0.5f; + // volume envelope + env_time++; + if(env_time>env_length[env_stage]) + { + env_time=0; + env_stage++; + if(env_stage==3) + playing_sample=false; + } + if(env_stage==0) + env_vol=(float)env_time/env_length[0]; + if(env_stage==1) + env_vol=1.0f+pow(1.0f-(float)env_time/env_length[1], 1.0f)*2.0f*s->m_susModel.value(); + if(env_stage==2) + env_vol=1.0f-(float)env_time/env_length[2]; + + // phaser step + fphase+=fdphase; + iphase=abs((int)fphase); + if(iphase>1023) iphase=1023; + + if(flthp_d!=0.0f) + { + flthp*=flthp_d; + if(flthp<0.00001f) flthp=0.00001f; + if(flthp>0.1f) flthp=0.1f; + } + + float ssample=0.0f; + for(int si=0;si<8;si++) // 8x supersampling + { + float sample=0.0f; + phase++; + if(phase>=period) + { +// phase=0; + phase%=period; + if(s->m_waveFormModel.value()==3) + for(int i=0;i<32;i++) + noise_buffer[i]=frnd(2.0f)-1.0f; + } + // base waveform + float fp=(float)phase/period; + switch(s->m_waveFormModel.value()) + { + case 0: // square + if(fp0.1f) fltw=0.1f; + if(s->m_lpFilCutModel.value()!=1.0f) + { + fltdp+=(sample-fltp)*fltw; + fltdp-=fltdp*fltdmp; + } + else + { + fltp=sample; + fltdp=0.0f; + } + fltp+=fltdp; + // hp filter + fltphp+=fltp-pp; + fltphp-=fltphp*flthp; + sample=fltphp; + // phaser + phaser_buffer[ipp&1023]=sample; + sample+=phaser_buffer[(ipp-iphase+1024)&1023]; + ipp=(ipp+1)&1023; + // final accumulation and envelope application + ssample+=sample*env_vol; + } + //ssample=ssample/8*master_vol; + + //ssample*=2.0f*sound_vol; + ssample*=0.05f; + + if(buffer!=NULL) + { + if(ssample>1.0f) ssample=1.0f; + if(ssample<-1.0f) ssample=-1.0f; + for( ch_cnt_t j=0; j < DEFAULT_CHANNELS; j++ ) + { + buffer[i][j]=ssample; + } + } + } +} + + + + +bool SfxrSynth::isPlaying() const +{ + return playing_sample; +} + + +sfxrInstrument::sfxrInstrument( InstrumentTrack * _instrument_track ) : + Instrument( _instrument_track, &sfxr_plugin_descriptor ), + m_attModel(0.0f, this), + m_holdModel(0.3f, this), + m_susModel(0.0f, this), + m_decModel(0.4f, this), + + m_startFreqModel(0.3f, this), + m_minFreqModel(0.0f, this), + m_slideModel(0.0f, this), + m_dSlideModel(0.0f, this), + m_vibDepthModel(0.0f, this), + m_vibSpeedModel(0.0f, this), + + m_changeAmtModel(0.0f, this), + m_changeSpeedModel(0.0f, this), + + m_sqrDutyModel(0.0f, this), + m_sqrSweepModel(0.0f, this), + + m_repeatSpeedModel(0.0f, this), + + m_phaserOffsetModel(0.0f, this), + m_phaserSweepModel(0.0f, this), + + m_lpFilCutModel(1.0f, this), + m_lpFilCutSweepModel(0.0f, this), + m_lpFilResoModel(0.0f, this), + m_hpFilCutModel(0.0f, this), + m_hpFilCutSweepModel(0.0f, this), + m_waveFormModel( SQR_WAVE, 0, WAVES_NUM-1, this, tr( "Wave Form" ) ) +{ +} + + + + +sfxrInstrument::~sfxrInstrument() +{ +} + + + + +void sfxrInstrument::saveSettings( QDomDocument & _doc, QDomElement & _this ) +{ + _this.setAttribute( "version", "1" ); + m_attModel.saveSettings( _doc, _this, "att" ); + m_holdModel.saveSettings( _doc, _this, "hold" ); + m_susModel.saveSettings( _doc, _this, "sus" ); + m_decModel.saveSettings( _doc, _this, "dec" ); + + m_startFreqModel.saveSettings( _doc, _this, "startFreq" ); + m_minFreqModel.saveSettings( _doc, _this, "minFreq" ); + m_slideModel.saveSettings( _doc, _this, "slide" ); + m_dSlideModel.saveSettings( _doc, _this, "dSlide" ); + m_vibDepthModel.saveSettings( _doc, _this, "vibDepth" ); + m_vibSpeedModel.saveSettings( _doc, _this, "vibSpeed" ); + + m_changeAmtModel.saveSettings( _doc, _this, "changeAmt" ); + m_changeSpeedModel.saveSettings( _doc, _this, "changeSpeed" ); + + m_sqrDutyModel.saveSettings( _doc, _this, "sqrDuty" ); + m_sqrSweepModel.saveSettings( _doc, _this, "sqrSweep" ); + + m_repeatSpeedModel.saveSettings( _doc, _this, "repeatSpeed" ); + + m_phaserOffsetModel.saveSettings( _doc, _this, "phaserOffset" ); + m_phaserSweepModel.saveSettings( _doc, _this, "phaserSweep" ); + + m_lpFilCutModel.saveSettings( _doc, _this, "lpFilCut" ); + m_lpFilCutSweepModel.saveSettings( _doc, _this, "lpFilCutSweep" ); + m_lpFilResoModel.saveSettings( _doc, _this, "lpFilReso" ); + m_hpFilCutModel.saveSettings( _doc, _this, "hpFilCut" ); + m_hpFilCutSweepModel.saveSettings( _doc, _this, "hpFilCutSweep" ); + + m_waveFormModel.saveSettings( _doc, _this, "waveForm" ); +} + + + + +void sfxrInstrument::loadSettings( const QDomElement & _this ) +{ + + m_attModel.loadSettings(_this, "att" ); + m_holdModel.loadSettings( _this, "hold" ); + m_susModel.loadSettings( _this, "sus" ); + m_decModel.loadSettings( _this, "dec" ); + + m_startFreqModel.loadSettings( _this, "startFreq" ); + m_minFreqModel.loadSettings( _this, "minFreq" ); + m_slideModel.loadSettings( _this, "slide" ); + m_dSlideModel.loadSettings( _this, "dSlide" ); + m_vibDepthModel.loadSettings( _this, "vibDepth" ); + m_vibSpeedModel.loadSettings( _this, "vibSpeed" ); + + m_changeAmtModel.loadSettings( _this, "changeAmt" ); + m_changeSpeedModel.loadSettings( _this, "changeSpeed" ); + + m_sqrDutyModel.loadSettings( _this, "sqrDuty" ); + m_sqrSweepModel.loadSettings( _this, "sqrSweep" ); + + m_repeatSpeedModel.loadSettings( _this, "repeatSpeed" ); + + m_phaserOffsetModel.loadSettings( _this, "phaserOffset" ); + m_phaserSweepModel.loadSettings( _this, "phaserSweep" ); + + m_lpFilCutModel.loadSettings( _this, "lpFilCut" ); + m_lpFilCutSweepModel.loadSettings( _this, "lpFilCutSweep" ); + m_lpFilResoModel.loadSettings( _this, "lpFilReso" ); + m_hpFilCutModel.loadSettings( _this, "hpFilCut" ); + m_hpFilCutSweepModel.loadSettings( _this, "hpFilCutSweep" ); + + m_waveFormModel.loadSettings( _this, "waveForm" ); + +} + + + + +QString sfxrInstrument::nodeName() const +{ + return( sfxr_plugin_descriptor.name ); +} + + + + +void sfxrInstrument::playNote(notePlayHandle * _n, sampleFrame * _working_buffer ) +{ + m_synthMutex.lock(); + fpp_t frameNum = _n->framesLeftForCurrentPeriod(); + if ( _n->totalFramesPlayed() == 0 ) + { + _n->m_pluginData = new SfxrSynth( this ); + } + else if( static_cast(_n->m_pluginData)->isPlaying() == false ) + { + _n->noteOff(); + } + + static_cast(_n->m_pluginData)->update( _working_buffer, frameNum ); + m_synthMutex.unlock(); + + instrumentTrack()->processAudioBuffer( _working_buffer, frameNum, NULL ); +} + + + + +void sfxrInstrument::deleteNotePluginData( notePlayHandle * _n ) +{ + delete static_cast( _n->m_pluginData ); +} + + + + +PluginView * sfxrInstrument::instantiateView( QWidget * _parent ) +{ + return( new sfxrInstrumentView( this, _parent ) ); +} + + + + +void sfxrInstrument::resetModels() +{ + + m_attModel.reset(); + m_holdModel.reset(); + m_susModel.reset(); + m_decModel.reset(); + + m_startFreqModel.reset(); + m_minFreqModel.reset(); + m_slideModel.reset(); + m_dSlideModel.reset(); + m_vibDepthModel.reset(); + m_vibSpeedModel.reset(); + + m_changeAmtModel.reset(); + m_changeSpeedModel.reset(); + + m_sqrDutyModel.reset(); + m_sqrSweepModel.reset(); + + m_repeatSpeedModel.reset(); + + m_phaserOffsetModel.reset(); + m_phaserSweepModel.reset(); + + m_lpFilCutModel.reset(); + m_lpFilCutSweepModel.reset(); + m_lpFilResoModel.reset(); + m_hpFilCutModel.reset(); + m_hpFilCutSweepModel.reset(); + + m_waveFormModel.reset(); +} + + + + +class sfxrKnob : public knob +{ +public: + sfxrKnob( QWidget * _parent ) : + knob( knobStyled, _parent ) + { + setFixedSize( 20, 20 ); + setCenterPointX( 10.0 ); + setCenterPointY( 10.0 ); + setTotalAngle( 270.0 ); + setLineWidth( 1 ); + } +}; + + + + +#define createKnob(_knob, _x, _y, _name)\ + _knob = new sfxrKnob( this ); \ + _knob->setHintText( tr( _name ":" ), "" ); \ + _knob->move( _x, _y ); \ + toolTip::add( _knob, tr( _name ) ); + + + + +#define createButton(_button, _x, _y, _name, _resName)\ + _button = new pixmapButton( this, tr( "Sine wave" ) );\ + _button->move( _x, _y );\ + _button->setActiveGraphic( embed::getIconPixmap( _resName "_active" ) );\ + _button->setInactiveGraphic( embed::getIconPixmap( _resName "_inactive" ) );\ + toolTip::add( _button, tr( _name ) ); + + + + +#define createButtonLocalGraphic(_button, _x, _y, _name, _resName)\ + _button = new pixmapButton( this, tr( "Sine wave" ) );\ + _button->move( _x, _y );\ + _button->setActiveGraphic( PLUGIN_NAME::getIconPixmap( _resName "_active" ) );\ + _button->setInactiveGraphic( PLUGIN_NAME::getIconPixmap( _resName "_inactive" ) );\ + toolTip::add( _button, tr( _name ) ); + + + + +sfxrInstrumentView::sfxrInstrumentView( Instrument * _instrument, + QWidget * _parent ) : + InstrumentView( _instrument, _parent ) +{ + srand(time(NULL)); + setAutoFillBackground( true ); + QPalette pal; + pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap( "artwork" ) ); + setPalette( pal ); + + createKnob(m_attKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*0, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*0, "Attack Time"); + createKnob(m_holdKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*1, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*0, "Sustain Time"); + createKnob(m_susKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*2, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*0, "Sustain Punch"); + createKnob(m_decKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*3, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*0, "Decay Time"); + + createKnob(m_startFreqKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*0, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*1, "Start Frequency"); + createKnob(m_minFreqKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*1, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*1, "Min Frequency"); + createKnob(m_slideKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*2, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*1, "Slide"); + createKnob(m_dSlideKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*3, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*1, "Delta Slide"); + createKnob(m_vibDepthKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*4, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*1, "Vibrato Depth"); + createKnob(m_vibSpeedKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*5, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*1, "Vibrato Speed"); + + createKnob(m_changeAmtKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*0, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*2, "Change Amount"); + createKnob(m_changeSpeedKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*1, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*2, "Change Speed"); + + createKnob(m_sqrDutyKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*3, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*2, "Squre Duty(Square wave only)"); + createKnob(m_sqrSweepKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*4, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*2, "Squre Sweep(Square wave only)"); + + createKnob(m_repeatSpeedKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*0, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*3, "Repeat Speed"); + + createKnob(m_phaserOffsetKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*2, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*3, "Phaser Offset"); + createKnob(m_phaserSweepKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*3, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*3, "Phaser Sweep"); + + createKnob(m_lpFilCutKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*0, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*4, "LP Filter Cutoff"); + createKnob(m_lpFilCutSweepKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*1, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*4, "LP Filter Cutoff Sweep"); + createKnob(m_lpFilResoKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*2, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*4, "LP Filter Resonance"); + createKnob(m_hpFilCutKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*3, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*4, "HP Filter Cutoff"); + createKnob(m_hpFilCutSweepKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*4, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*4, "HP Filter Cutoff Sweep"); + + createButton(m_sqrWaveBtn, KNOBS_BASE_X+WAVEFORM_BUTTON_WIDTH*0, WAVEFORM_BASE_Y, "Square Wave", "square_wave"); + createButton(m_sawWaveBtn, KNOBS_BASE_X+WAVEFORM_BUTTON_WIDTH*1, WAVEFORM_BASE_Y, "Saw Wave", "saw_wave"); + createButton(m_sinWaveBtn, KNOBS_BASE_X+WAVEFORM_BUTTON_WIDTH*2, WAVEFORM_BASE_Y, "Sine Wave", "sin_wave"); + createButton(m_noiseWaveBtn, KNOBS_BASE_X+WAVEFORM_BUTTON_WIDTH*3, WAVEFORM_BASE_Y, "Noise", "white_noise_wave"); + + m_waveBtnGroup = new automatableButtonGroup( this ); + m_waveBtnGroup->addButton(m_sqrWaveBtn); + m_waveBtnGroup->addButton(m_sawWaveBtn); + m_waveBtnGroup->addButton(m_sinWaveBtn); + m_waveBtnGroup->addButton(m_noiseWaveBtn); + + + createButtonLocalGraphic(m_pickupBtn, GENERATOR_BASE_X+GENERATOR_BUTTON_WIDTH*0, GENERATOR_BASE_Y, "Generate pick up/coin sfx", "pickup"); + createButtonLocalGraphic(m_laserBtn, GENERATOR_BASE_X+GENERATOR_BUTTON_WIDTH*1, GENERATOR_BASE_Y, "Generate laser/shoot sfx", "laser"); + createButtonLocalGraphic(m_explosionBtn, GENERATOR_BASE_X+GENERATOR_BUTTON_WIDTH*2, GENERATOR_BASE_Y, "Generate explosion sfx", "explosion"); + createButtonLocalGraphic(m_powerupBtn, GENERATOR_BASE_X+GENERATOR_BUTTON_WIDTH*3, GENERATOR_BASE_Y, "Generate power up sfx", "powerup"); + createButtonLocalGraphic(m_hitBtn, GENERATOR_BASE_X+GENERATOR_BUTTON_WIDTH*4, GENERATOR_BASE_Y, "Generate hit/hurt sfx", "hit"); + createButtonLocalGraphic(m_jumpBtn, GENERATOR_BASE_X+GENERATOR_BUTTON_WIDTH*5, GENERATOR_BASE_Y, "Generate jump sfx", "jump"); + createButtonLocalGraphic(m_blipBtn, GENERATOR_BASE_X+GENERATOR_BUTTON_WIDTH*6, GENERATOR_BASE_Y, "Generate blip/select sfx", "blip"); + connect( m_pickupBtn, SIGNAL ( clicked() ), this, SLOT ( genPickup() ) ); + connect( m_laserBtn, SIGNAL ( clicked() ), this, SLOT ( genLaser() ) ); + connect( m_explosionBtn, SIGNAL ( clicked() ), this, SLOT ( genExplosion() ) ); + connect( m_powerupBtn, SIGNAL ( clicked() ), this, SLOT ( genPowerup() ) ); + connect( m_hitBtn, SIGNAL ( clicked() ), this, SLOT ( genHit() ) ); + connect( m_jumpBtn, SIGNAL ( clicked() ), this, SLOT ( genJump() ) ); + connect( m_blipBtn, SIGNAL ( clicked() ), this, SLOT ( genBlip() ) ); + + + createButtonLocalGraphic(m_randomizeBtn, RAND_BUTTON_X, RAND_BUTTON_Y, "Generate random sfx", "randomize"); + createButtonLocalGraphic(m_mutateBtn, MUTA_BUTTON_X, MUTA_BUTTON_Y, "Mutate sfx", "mutate"); + connect( m_randomizeBtn, SIGNAL ( clicked() ), this, SLOT ( randomize() ) ); + connect( m_mutateBtn, SIGNAL ( clicked() ), this, SLOT ( mutate() ) ); + + +} + + + + +void sfxrInstrumentView::modelChanged() +{ + sfxrInstrument * s = castModel(); + + m_attKnob->setModel( &s->m_attModel ); + m_holdKnob->setModel( &s->m_holdModel ); + m_susKnob->setModel( &s->m_susModel ); + m_decKnob->setModel( &s->m_decModel ); + + m_startFreqKnob->setModel( &s->m_startFreqModel ); + m_minFreqKnob->setModel( &s->m_minFreqModel ); + m_slideKnob->setModel( &s->m_slideModel ); + m_dSlideKnob->setModel( &s->m_dSlideModel ); + m_vibDepthKnob->setModel( &s->m_vibDepthModel ); + m_vibSpeedKnob->setModel( &s->m_vibSpeedModel ); + + m_changeAmtKnob->setModel( &s->m_changeAmtModel ); + m_changeSpeedKnob->setModel( &s->m_changeSpeedModel ); + + m_sqrDutyKnob->setModel( &s->m_sqrDutyModel ); + m_sqrSweepKnob->setModel( &s->m_sqrSweepModel ); + + m_repeatSpeedKnob->setModel( &s->m_repeatSpeedModel ); + + m_phaserOffsetKnob->setModel( &s->m_phaserOffsetModel ); + m_phaserSweepKnob->setModel( &s->m_phaserSweepModel ); + + m_lpFilCutKnob->setModel( &s->m_lpFilCutModel ); + m_lpFilCutSweepKnob->setModel( &s->m_lpFilCutSweepModel ); + m_lpFilResoKnob->setModel( &s->m_lpFilResoModel ); + m_hpFilCutKnob->setModel( &s->m_hpFilCutModel ); + m_hpFilCutSweepKnob->setModel( &s->m_hpFilCutSweepModel ); + + m_waveBtnGroup->setModel( &s->m_waveFormModel ); +} + + + + +void sfxrInstrumentView::genPickup() +{ + sfxrInstrument * s = castModel(); + s->resetModels(); + s->m_startFreqModel.setValue( 0.4f+frnd(0.5f) ); + s->m_attModel.setValue( 0.0f ); + s->m_holdModel.setValue( frnd(0.1f) ); + s->m_decModel.setValue( 0.1f+frnd(0.4f) ); + s->m_susModel.setValue( 0.3f+frnd(0.3f) ); + + if(rnd(1)) + { + s->m_changeSpeedModel.setValue( 0.5f+frnd(0.2f) ); + s->m_changeAmtModel.setValue( 0.2f+frnd(0.4f) ); + } +} + + + + +void sfxrInstrumentView::genLaser() +{ + sfxrInstrument * s = castModel(); + s->resetModels(); + + s->m_waveFormModel.setValue( rnd(2) ); + if(s->m_waveFormModel.value()==2 && rnd(1)) + s->m_waveFormModel.setValue( rnd(1) ); + + s->m_startFreqModel.setValue( 0.5f+frnd(0.5f) ); + s->m_minFreqModel.setValue( s->m_startFreqModel.value()-0.2f-frnd(0.6f) ); + + if(s->m_minFreqModel.value()<0.2f) + { + s->m_minFreqModel.setValue(0.2f); + } + + s->m_slideModel.setValue( -0.15f-frnd(0.2f) ); + + if(rnd(2)==0) + { + s->m_startFreqModel.setValue( 0.3f+frnd(0.6f) ); + s->m_minFreqModel.setValue( frnd(0.1f) ); + s->m_slideModel.setValue( -0.35f-frnd(0.3f) ); + } + + if(rnd(1)) + { + s->m_sqrDutyModel.setValue( frnd(0.5f) ); + s->m_sqrSweepModel.setValue( 0.2f ); + } + else + { + s->m_sqrDutyModel.setValue( 0.4f+frnd(0.5f) ); + s->m_sqrSweepModel.setValue( -frnd(0.7f) ); + } + + s->m_attModel.setValue( 0.0f ); + s->m_holdModel.setValue( 0.1f+frnd(0.2f) ); + s->m_decModel.setValue( frnd(0.4f) ); + + if(rnd(1)) + { + s->m_susModel.setValue( frnd(0.3f) ); + } + + if(rnd(2)==0) + { + s->m_phaserOffsetModel.setValue( frnd(0.2f) ); + s->m_phaserSweepModel.setValue( -frnd(0.2f) ); + } + + if(rnd(1)) + s->m_hpFilCutModel.setValue( frnd(0.3f) ); +} + + + + +void sfxrInstrumentView::genExplosion() +{ + sfxrInstrument * s = castModel(); + s->resetModels(); + + s->m_waveFormModel.setValue( 3 ); + + if(rnd(1)) + { + s->m_startFreqModel.setValue( 0.1f+frnd(0.4f) ); + s->m_slideModel.setValue( -0.1f+frnd(0.4f) ); + } + else + { + s->m_startFreqModel.setValue( 0.2f+frnd(0.7f) ); + s->m_slideModel.setValue( -0.2f-frnd(0.2f) ); + } + s->m_startFreqModel.setValue( s->m_startFreqModel.value()*s->m_startFreqModel.value() ); + + if(rnd(4)==0) + { + s->m_slideModel.setValue( 0.0f ); + } + + if(rnd(2)==0) + { + s->m_repeatSpeedModel.setValue( 0.3f+frnd(0.5f) ); + } + + s->m_attModel.setValue( 0.0f ); + s->m_holdModel.setValue( 0.1f+frnd(0.3f) ); + s->m_decModel.setValue( 0.5f ); + if(rnd(1)==0) + { + s->m_phaserOffsetModel.setValue( -0.3f+frnd(0.9f) ); + s->m_phaserSweepModel.setValue( -frnd(0.3f) ); + } + s->m_susModel.setValue( 0.2f+frnd(0.6f) ); + + if(rnd(1)) + { + s->m_vibDepthModel.setValue( frnd(0.7f) ); + s->m_vibSpeedModel.setValue( frnd(0.6f) ); + } + if(rnd(2)==0) + { + s->m_changeSpeedModel.setValue( 0.6f+frnd(0.3f) ); + s->m_changeAmtModel.setValue( 0.8f-frnd(1.6f) ); + } + +} + + + + +void sfxrInstrumentView::genPowerup() +{ + sfxrInstrument * s = castModel(); + s->resetModels(); + + if(rnd(1)) + s->m_waveFormModel.setValue( 1 ); + else + s->m_sqrDutyModel.setValue( frnd(0.6f) ); + if(rnd(1)) + { + s->m_startFreqModel.setValue( 0.2f+frnd(0.3f) ); + s->m_slideModel.setValue( 0.1f+frnd(0.4f) ); + s->m_repeatSpeedModel.setValue( 0.4f+frnd(0.4f) ); + } + else + { + s->m_startFreqModel.setValue( 0.2f+frnd(0.3f) ); + s->m_slideModel.setValue( 0.05f+frnd(0.2f) ); + if(rnd(1)) + { + s->m_vibDepthModel.setValue( frnd(0.7f) ); + s->m_vibSpeedModel.setValue( frnd(0.6f) ); + } + } + + s->m_attModel.setValue( 0.0f ); + s->m_holdModel.setValue( frnd(0.4f) ); + s->m_decModel.setValue( 0.1f+frnd(0.4f) ); +} + + + + +void sfxrInstrumentView::genHit() +{ + sfxrInstrument * s = castModel(); + s->resetModels(); + + s->m_waveFormModel.setValue( rnd(2) ); + if(s->m_waveFormModel.value()==2) + { + s->m_waveFormModel.setValue( 3 ); + } + if(s->m_waveFormModel.value()==0) + { + s->m_sqrDutyModel.setValue( frnd(0.6f) ); + } + + s->m_startFreqModel.setValue( 0.2f+frnd(0.6f) ); + s->m_slideModel.setValue( -0.3f-frnd(0.4f) ); + + s->m_attModel.setValue( 0.0f ); + s->m_holdModel.setValue( frnd(0.1f) ); + s->m_decModel.setValue( 0.1f+frnd(0.2f) ); + if(rnd(1)) + { + s->m_hpFilCutModel.setValue( frnd(0.3f) ); + } +} + + + + +void sfxrInstrumentView::genJump() +{ + sfxrInstrument * s = castModel(); + s->resetModels(); + + s->m_waveFormModel.setValue( 0 ); + s->m_sqrDutyModel.setValue( frnd(0.6f) ); + + s->m_startFreqModel.setValue( 0.3f+frnd(0.3f) ); + s->m_slideModel.setValue( 0.1f+frnd(0.2f) ); + + s->m_attModel.setValue( 0.0f ); + s->m_holdModel.setValue( 0.1f+frnd(0.3f) ); + s->m_decModel.setValue( 0.1f+frnd(0.2f) ); + + if(rnd(1)) + { + s->m_hpFilCutModel.setValue( frnd(0.3f) ); + } + if(rnd(1)) + { + + s->m_lpFilCutModel.setValue( 1.0f-frnd(0.6f) ); + } + +} + + + + +void sfxrInstrumentView::genBlip() +{ + sfxrInstrument * s = castModel(); + s->resetModels(); + + s->m_waveFormModel.setValue( rnd(1) ); + if( s->m_waveFormModel.value()==0 ) + { + s->m_sqrDutyModel.setValue( frnd(0.6f) ); + } + + s->m_startFreqModel.setValue( 0.2f+frnd(0.4f) ); + + s->m_attModel.setValue( 0.0f ); + s->m_holdModel.setValue( 0.1f+frnd(0.1f) ); + s->m_decModel.setValue( frnd(0.2f) ); + s->m_hpFilCutModel.setValue( 0.1f ); +} + + + + +void sfxrInstrumentView::randomize() +{ + sfxrInstrument * s = castModel(); + + s->m_startFreqModel.setValue( pow(frnd(2.0f)-1.0f, 2.0f) ); + if(rnd(1)) + { + s->m_startFreqModel.setValue( pow(frnd(2.0f)-1.0f, 3.0f)+0.5f ); + } + s->m_minFreqModel.setValue( 0.0f ); + s->m_slideModel.setValue( pow(frnd(2.0f)-1.0f, 5.0f) ); + if( s->m_startFreqModel.value()>0.7f && s->m_slideModel.value()>0.2f ) + { + s->m_slideModel.setValue( -s->m_slideModel.value() ); + } + if( s->m_startFreqModel.value()<0.2f && s->m_slideModel.value()<-0.05f ) + { + s->m_slideModel.setValue( -s->m_slideModel.value() ); + } + s->m_dSlideModel.setValue( pow(frnd(2.0f)-1.0f, 3.0f) ); + + s->m_sqrDutyModel.setValue( frnd(2.0f)-1.0f ); + s->m_sqrSweepModel.setValue( pow(frnd(2.0f)-1.0f, 3.0f) ); + + s->m_vibDepthModel.setValue( pow(frnd(2.0f)-1.0f, 3.0f) ); + s->m_vibSpeedModel.setValue( frnd(2.0f)-1.0f ); + //s->m_vibDelayModel.setValue( frnd(2.0f)-1.0f ); + + s->m_attModel.setValue( pow(frnd(2.0f)-1.0f, 3.0f) ); + s->m_holdModel.setValue( pow(frnd(2.0f)-1.0f, 2.0f) ); + s->m_decModel.setValue( frnd(2.0f)-1.0f ); + s->m_susModel.setValue( pow(frnd(0.8f), 2.0f) ); + if(s->m_attModel.value()+s->m_holdModel.value()+s->m_decModel.value()<0.2f) + { + s->m_holdModel.setValue( s->m_holdModel.value()+0.2f+frnd(0.3f) ); + s->m_decModel.setValue( s->m_decModel.value()+0.2f+frnd(0.3f) ); + } + + s->m_lpFilResoModel.setValue( frnd(2.0f)-1.0f ); + s->m_lpFilCutModel.setValue( 1.0f-pow(frnd(1.0f), 3.0f) ); + s->m_lpFilCutSweepModel.setValue( pow(frnd(2.0f)-1.0f, 3.0f) ); + if(s->m_lpFilCutModel.value()<0.1f && s->m_lpFilCutSweepModel.value()<-0.05f) + { + s->m_lpFilCutSweepModel.setValue( -s->m_lpFilCutSweepModel.value() ); + } + s->m_hpFilCutModel.setValue( pow(frnd(1.0f), 5.0f) ); + s->m_hpFilCutSweepModel.setValue( pow(frnd(2.0f)-1.0f, 5.0f) ); + + s->m_phaserOffsetModel.setValue( pow(frnd(2.0f)-1.0f, 3.0f) ); + s->m_phaserSweepModel.setValue( pow(frnd(2.0f)-1.0f, 3.0f) ); + + s->m_repeatSpeedModel.setValue( frnd(2.0f)-1.0f ); + + s->m_changeSpeedModel.setValue( frnd(2.0f)-1.0f ); + s->m_changeAmtModel.setValue( frnd(2.0f)-1.0f ); + +} + + + + +void sfxrInstrumentView::mutate() +{ + sfxrInstrument * s = castModel(); + + if(rnd(1)) s->m_startFreqModel.setValue( s->m_startFreqModel.value()+frnd(0.1f)-0.05f ); + // if(rnd(1)) s->m_minFreqModel.setValue( s->m_minFreqModel.value()+frnd(0.1f)-0.05f ); + if(rnd(1)) s->m_slideModel.setValue( s->m_slideModel.value()+frnd(0.1f)-0.05f ); + if(rnd(1)) s->m_dSlideModel.setValue( s->m_dSlideModel.value()+frnd(0.1f)-0.05f ); + + if(rnd(1)) s->m_sqrDutyModel.setValue( s->m_sqrDutyModel.value()+frnd(0.1f)-0.05f ); + if(rnd(1)) s->m_sqrSweepModel.setValue( s->m_sqrSweepModel.value()+frnd(0.1f)-0.05f ); + + if(rnd(1)) s->m_vibDepthModel.setValue( s->m_vibDepthModel.value()+frnd(0.1f)-0.05f ); + if(rnd(1)) s->m_vibSpeedModel.setValue( s->m_vibSpeedModel.value()+frnd(0.1f)-0.05f ); + // if(rnd(1)) s->m_vibDelayModel.setValue( s->m_vibDelayModel.value()+frnd(0.1f)-0.05f ); + + if(rnd(1)) s->m_attModel.setValue( s->m_attModel.value()+frnd(0.1f)-0.05f ); + if(rnd(1)) s->m_holdModel.setValue( s->m_holdModel.value()+frnd(0.1f)-0.05f ); + if(rnd(1)) s->m_decModel.setValue( s->m_decModel.value()+frnd(0.1f)-0.05f ); + if(rnd(1)) s->m_susModel.setValue( s->m_susModel.value()+frnd(0.1f)-0.05f ); + + if(rnd(1)) s->m_lpFilResoModel.setValue( s->m_lpFilResoModel.value()+frnd(0.1f)-0.05f ); + if(rnd(1)) s->m_lpFilCutModel.setValue( s->m_lpFilCutModel.value()+frnd(0.1f)-0.05f ); + if(rnd(1)) s->m_lpFilCutSweepModel.setValue( s->m_lpFilCutSweepModel.value()+frnd(0.1f)-0.05f ); + if(rnd(1)) s->m_hpFilCutModel.setValue( s->m_hpFilCutModel.value()+frnd(0.1f)-0.05f ); + if(rnd(1)) s->m_hpFilCutSweepModel.setValue( s->m_hpFilCutSweepModel.value()+frnd(0.1f)-0.05f ); + + if(rnd(1)) s->m_phaserOffsetModel.setValue( s->m_phaserOffsetModel.value()+frnd(0.1f)-0.05f ); + if(rnd(1)) s->m_phaserSweepModel.setValue( s->m_phaserSweepModel.value()+frnd(0.1f)-0.05f ); + + if(rnd(1)) s->m_repeatSpeedModel.setValue( s->m_repeatSpeedModel.value()+frnd(0.1f)-0.05f ); + + if(rnd(1)) s->m_changeSpeedModel.setValue( s->m_changeSpeedModel.value()+frnd(0.1f)-0.05f ); + if(rnd(1)) s->m_changeAmtModel.setValue( s->m_changeAmtModel.value()+frnd(0.1f)-0.05f ); + +} + + + + +extern "C" +{ + +// necessary for getting instance out of shared lib +Plugin * PLUGIN_EXPORT lmms_plugin_main( Model *, void * _data ) +{ + return( new sfxrInstrument( static_cast( _data ) ) ); +} + + +} + + + +#include "moc_sfxr.cxx" diff --git a/plugins/sfxr/sfxr.h b/plugins/sfxr/sfxr.h new file mode 100644 index 000000000..2d9934219 --- /dev/null +++ b/plugins/sfxr/sfxr.h @@ -0,0 +1,301 @@ +/* + * sfxr.h - declaration of classes of the LMMS sfxr plugin + * Originally written by Tomas Pettersson. For the original license, + * please read readme.txt in this directory + * + * Copyright (c) 2014 Wong Cho Ching + * + * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + + +#ifndef _SFXR_H +#define _SFXR_H + +#include "Instrument.h" +#include "InstrumentView.h" +#include "knob.h" +#include "graph.h" +#include "pixmap_button.h" +#include "led_checkbox.h" + + +enum SfxrWaves +{ + SQR_WAVE, SAW_WAVE, SINE_WAVE, NOISE_WAVE, WAVES_NUM +}; + +const int WAVEFORM_BASE_X = 20; +const int WAVEFORM_BASE_Y = 14; +const int WAVEFORM_BUTTON_WIDTH = 16; + +const int GENERATOR_BASE_X = 110; +const int GENERATOR_BASE_Y = 24; +const int GENERATOR_BUTTON_WIDTH = 16; + +const int RAND_BUTTON_X = 160; +const int RAND_BUTTON_Y = 4; + +const int MUTA_BUTTON_X = 205; +const int MUTA_BUTTON_Y = 4; + +const int KNOBS_BASE_X = 20; +const int KNOBS_BASE_Y = 50; +const int KNOB_BLOCK_SIZE_X = 40; +const int KNOB_BLOCK_SIZE_Y = 40; + + + + +class sfxrInstrument; + + + +class SfxrSynth +{ +public: + SfxrSynth( const sfxrInstrument * s ); + virtual ~SfxrSynth(); + + void resetSample( bool restart ); + void update( sampleFrame * buffer, const fpp_t frameNum ); + + bool isPlaying() const; + +private: + const sfxrInstrument * s; + bool playing_sample; + int phase; + double fperiod; + double fmaxperiod; + double fslide; + double fdslide; + int period; + float square_duty; + float square_slide; + int env_stage; + int env_time; + int env_length[3]; + float env_vol; + float fphase; + float fdphase; + int iphase; + float phaser_buffer[1024]; + int ipp; + float noise_buffer[32]; + float fltp; + float fltdp; + float fltw; + float fltw_d; + float fltdmp; + float fltphp; + float flthp; + float flthp_d; + float vib_phase; + float vib_speed; + float vib_amp; + int rep_time; + int rep_limit; + int arp_time; + int arp_limit; + double arp_mod; + +} ; + + + +/** + * @brief A class that simplify the constructor of FloatModel, with value [0,1] + */ +class SfxrZeroToOneFloatModel : public FloatModel +{ +public: + SfxrZeroToOneFloatModel(float val, Model * parent): + FloatModel( val, 0.0, 1.0, 0.001, parent) + { + } + /* purpose: prevent the initial value of the model from being changed */ + virtual void loadSettings( const QDomElement& element, const QString& name = QString( "value" ) ) + { + float oldInitValue = initValue(); + FloatModel::loadSettings(element, name); + float oldValue = value(); + setInitValue(oldInitValue); + setValue(oldValue); + } +}; + +/** + * @brief A class that simplify the constructor of FloatModel, with value [-1,1] + */ +class SfxrNegPosOneFloatModel : public FloatModel +{ +public: + SfxrNegPosOneFloatModel(float val, Model * parent): + FloatModel( val, -1.0, 1.0, 0.001, parent) + { + } + /* purpose: prevent the initial value of the model from being changed */ + virtual void loadSettings( const QDomElement& element, const QString& name = QString( "value" ) ) + { + float oldInitValue = initValue(); + FloatModel::loadSettings(element, name); + float oldValue = value(); + setInitValue(oldInitValue); + setValue(oldValue); + } +}; + +class sfxrInstrument : public Instrument +{ + Q_OBJECT +public: + sfxrInstrument(InstrumentTrack * _instrument_track ); + virtual ~sfxrInstrument(); + + virtual void playNote( notePlayHandle * _n, sampleFrame * _working_buffer ); + virtual void deleteNotePluginData( notePlayHandle * _n ); + + virtual void saveSettings( QDomDocument & _doc, + QDomElement & _parent ); + virtual void loadSettings( const QDomElement & _this ); + + virtual QString nodeName() const; + + virtual PluginView * instantiateView( QWidget * _parent ); + + void resetModels(); + + +private: + QMutex m_synthMutex; + SfxrZeroToOneFloatModel m_attModel; + SfxrZeroToOneFloatModel m_holdModel; + SfxrZeroToOneFloatModel m_susModel; + SfxrZeroToOneFloatModel m_decModel; + + SfxrZeroToOneFloatModel m_startFreqModel; + SfxrZeroToOneFloatModel m_minFreqModel; + SfxrNegPosOneFloatModel m_slideModel; + SfxrNegPosOneFloatModel m_dSlideModel; + SfxrZeroToOneFloatModel m_vibDepthModel; + SfxrZeroToOneFloatModel m_vibSpeedModel; + + SfxrNegPosOneFloatModel m_changeAmtModel; + SfxrZeroToOneFloatModel m_changeSpeedModel; + + SfxrZeroToOneFloatModel m_sqrDutyModel; + SfxrNegPosOneFloatModel m_sqrSweepModel; + + SfxrZeroToOneFloatModel m_repeatSpeedModel; + + SfxrNegPosOneFloatModel m_phaserOffsetModel; + SfxrNegPosOneFloatModel m_phaserSweepModel; + + SfxrZeroToOneFloatModel m_lpFilCutModel; + SfxrNegPosOneFloatModel m_lpFilCutSweepModel; + SfxrZeroToOneFloatModel m_lpFilResoModel; + SfxrZeroToOneFloatModel m_hpFilCutModel; + SfxrNegPosOneFloatModel m_hpFilCutSweepModel; + + IntModel m_waveFormModel; + + friend class sfxrInstrumentView; + friend class SfxrSynth; +}; + + + +class sfxrInstrumentView : public InstrumentView +{ + Q_OBJECT +public: + sfxrInstrumentView( Instrument * _instrument, + QWidget * _parent ); + + virtual ~sfxrInstrumentView() {}; + +protected slots: + void genPickup(); + void genLaser(); + void genExplosion(); + void genPowerup(); + void genHit(); + void genJump(); + void genBlip(); + void randomize(); + void mutate(); + +private: + virtual void modelChanged(); + + knob * m_attKnob; //Attack Time + knob * m_holdKnob; //Sustain Time + knob * m_susKnob; //Sustain Punch + knob * m_decKnob; //Decay Time + + knob * m_startFreqKnob; //Start Frequency + knob * m_minFreqKnob; //Min Frequency + knob * m_slideKnob; //Slide + knob * m_dSlideKnob; //Delta Slide + knob * m_vibDepthKnob; //Vibrato Depth + knob * m_vibSpeedKnob; //Vibrato Speed + + knob * m_changeAmtKnob; //Change Amount + knob * m_changeSpeedKnob; //Change Speed + + knob * m_sqrDutyKnob; //Squre Duty + knob * m_sqrSweepKnob; //Squre Sweep + + knob * m_repeatSpeedKnob; //Repeat Speed + + knob * m_phaserOffsetKnob; //Phaser Offset + knob * m_phaserSweepKnob; //Phaser Sweep + + knob * m_lpFilCutKnob; //LP Filter Cutoff + knob * m_lpFilCutSweepKnob; //LP Filter Cutoff Sweep + knob * m_lpFilResoKnob; //LP Filter Resonance + knob * m_hpFilCutKnob; //HP Filter Cutoff + knob * m_hpFilCutSweepKnob; //HP Filter Cutoff Sweep + + automatableButtonGroup * m_waveBtnGroup; + pixmapButton * m_sqrWaveBtn; //NOTE: This button has Squre Duty + //and Squre Speed configurable + pixmapButton * m_sawWaveBtn; + pixmapButton * m_sinWaveBtn; + pixmapButton * m_noiseWaveBtn; + + + pixmapButton * m_pickupBtn; + pixmapButton * m_laserBtn; + pixmapButton * m_explosionBtn; + pixmapButton * m_powerupBtn; + pixmapButton * m_hitBtn; + pixmapButton * m_jumpBtn; + pixmapButton * m_blipBtn; + + pixmapButton * m_randomizeBtn; + pixmapButton * m_mutateBtn; + + static QPixmap * s_artwork; +}; + + + +#endif diff --git a/plugins/triple_oscillator/artwork.png b/plugins/triple_oscillator/artwork.png index 7c61a87ec..b4940ae5e 100644 Binary files a/plugins/triple_oscillator/artwork.png and b/plugins/triple_oscillator/artwork.png differ diff --git a/plugins/zynaddsubfx/artwork.png b/plugins/zynaddsubfx/artwork.png index 7d158bdaa..2ef0b5705 100644 Binary files a/plugins/zynaddsubfx/artwork.png and b/plugins/zynaddsubfx/artwork.png differ diff --git a/src/core/preset_preview_play_handle.cpp b/src/core/preset_preview_play_handle.cpp index 09139ba21..22ff31a50 100644 --- a/src/core/preset_preview_play_handle.cpp +++ b/src/core/preset_preview_play_handle.cpp @@ -89,12 +89,24 @@ public: m_dataMutex.unlock(); } + bool isPreviewing() + { + bool ret = m_dataMutex.tryLock(); + if( ret == true ) + { + m_dataMutex.unlock(); + } + return ret; + } + private: InstrumentTrack * m_previewInstrumentTrack; notePlayHandle * m_previewNote; QMutex m_dataMutex; + friend class presetPreviewPlayHandle; + } ; @@ -242,3 +254,17 @@ ConstNotePlayHandleList presetPreviewPlayHandle::nphsOfInstrumentTrack( } + + +bool presetPreviewPlayHandle::isPreviewing() +{ + bool ret = s_previewTC->m_dataMutex.tryLock(); + if( ret == true ) + { + s_previewTC->m_dataMutex.unlock(); + } + return ret; +} + + + diff --git a/src/core/song.cpp b/src/core/song.cpp index a32f453d7..f49f1bb31 100644 --- a/src/core/song.cpp +++ b/src/core/song.cpp @@ -201,7 +201,7 @@ song::~song() } if( m_SncVSTplug != NULL ) { - delete m_SncVSTplug; + free( m_SncVSTplug ); m_SncVSTplug = NULL; } } diff --git a/src/gui/widgets/cpuload_widget.cpp b/src/gui/widgets/cpuload_widget.cpp index 508581a74..f634a6b1e 100644 --- a/src/gui/widgets/cpuload_widget.cpp +++ b/src/gui/widgets/cpuload_widget.cpp @@ -45,6 +45,7 @@ cpuloadWidget::cpuloadWidget( QWidget * _parent ) : setFixedSize( m_background.width(), m_background.height() ); m_temp = QPixmap( width(), height() ); + connect( &m_updateTimer, SIGNAL( timeout() ), this, SLOT( updateCpuLoad() ) ); @@ -66,7 +67,8 @@ void cpuloadWidget::paintEvent( QPaintEvent * ) if( m_changed == true ) { m_changed = false; - + + m_temp.fill( QColor(0,0,0,0) ); QPainter p( &m_temp ); p.drawPixmap( 0, 0, m_background ); diff --git a/src/gui/widgets/visualization_widget.cpp b/src/gui/widgets/visualization_widget.cpp index 7dee75d33..2f6eebe95 100644 --- a/src/gui/widgets/visualization_widget.cpp +++ b/src/gui/widgets/visualization_widget.cpp @@ -141,7 +141,7 @@ void visualizationWidget::paintEvent( QPaintEvent * ) // and set color according to that... if( max_level * master_output < 0.9 ) { - p.setPen( QColor( 128, 224, 128 ) ); + p.setPen( QColor( 71, 253, 133 ) ); } else if( max_level * master_output < 1.0 ) {