├── Builds ├── MacOSX │ ├── RecentFilesMenuTemplate.nib │ └── Info.plist ├── VisualStudio2005 │ ├── resources.rc │ └── Livecut.sln └── VisualStudio2012 │ ├── resources.rc │ └── Livecut.sln ├── JuceLibraryCode ├── modules │ ├── juce_core │ │ └── juce_core.h │ ├── juce_events │ │ └── juce_events.h │ ├── juce_graphics │ │ └── juce_graphics.h │ ├── juce_gui_basics │ │ └── juce_gui_basics.h │ ├── juce_gui_extra │ │ └── juce_gui_extra.h │ ├── juce_audio_basics │ │ └── juce_audio_basics.h │ ├── juce_data_structures │ │ └── juce_data_structures.h │ ├── juce_audio_processors │ │ └── juce_audio_processors.h │ └── juce_audio_plugin_client │ │ └── juce_audio_plugin_client.h ├── ReadMe.txt ├── JuceHeader.h └── AppConfig.h ├── LICENSE.md ├── README.md ├── Source ├── ParamButton.h ├── ParamSlider.h ├── ParamCombo.h ├── ParamLabel.h ├── ParamLabel.cpp ├── SQPAmp.cpp ├── ParamButton.cpp ├── SQPAmp.h ├── ParamSlider.cpp ├── FirstOrderLowpass.cpp ├── Control.h ├── LivecutEditor.h ├── Control.cpp ├── FirstOrderLowpass.h ├── ParamCombo.cpp ├── Comb.cpp ├── Functor.h ├── BitCrusher.cpp ├── BitCrusher.h ├── Comb.h ├── DelayLine.h ├── float_cast.h ├── LivecutProcessor.h ├── DelayLine.cpp ├── LivecutLookAndFeel.h ├── LivecutEditor.cpp ├── Params.cpp ├── BBCutter.h ├── LivecutProcessor.cpp ├── Params.h ├── LivecutLookAndFeel.cpp └── BBCutter.cpp ├── .gitignore └── Livecut.jucer /Builds/MacOSX/RecentFilesMenuTemplate.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdsp/Livecut/HEAD/Builds/MacOSX/RecentFilesMenuTemplate.nib -------------------------------------------------------------------------------- /JuceLibraryCode/modules/juce_core/juce_core.h: -------------------------------------------------------------------------------- 1 | // This is an auto-generated file to redirect any included 2 | // module headers to the correct external folder. 3 | 4 | #include "../../../../JUCE/modules/juce_core/juce_core.h" 5 | 6 | -------------------------------------------------------------------------------- /JuceLibraryCode/modules/juce_events/juce_events.h: -------------------------------------------------------------------------------- 1 | // This is an auto-generated file to redirect any included 2 | // module headers to the correct external folder. 3 | 4 | #include "../../../../JUCE/modules/juce_events/juce_events.h" 5 | 6 | -------------------------------------------------------------------------------- /JuceLibraryCode/modules/juce_graphics/juce_graphics.h: -------------------------------------------------------------------------------- 1 | // This is an auto-generated file to redirect any included 2 | // module headers to the correct external folder. 3 | 4 | #include "../../../../JUCE/modules/juce_graphics/juce_graphics.h" 5 | 6 | -------------------------------------------------------------------------------- /JuceLibraryCode/modules/juce_gui_basics/juce_gui_basics.h: -------------------------------------------------------------------------------- 1 | // This is an auto-generated file to redirect any included 2 | // module headers to the correct external folder. 3 | 4 | #include "../../../../JUCE/modules/juce_gui_basics/juce_gui_basics.h" 5 | 6 | -------------------------------------------------------------------------------- /JuceLibraryCode/modules/juce_gui_extra/juce_gui_extra.h: -------------------------------------------------------------------------------- 1 | // This is an auto-generated file to redirect any included 2 | // module headers to the correct external folder. 3 | 4 | #include "../../../../JUCE/modules/juce_gui_extra/juce_gui_extra.h" 5 | 6 | -------------------------------------------------------------------------------- /JuceLibraryCode/modules/juce_audio_basics/juce_audio_basics.h: -------------------------------------------------------------------------------- 1 | // This is an auto-generated file to redirect any included 2 | // module headers to the correct external folder. 3 | 4 | #include "../../../../JUCE/modules/juce_audio_basics/juce_audio_basics.h" 5 | 6 | -------------------------------------------------------------------------------- /JuceLibraryCode/modules/juce_data_structures/juce_data_structures.h: -------------------------------------------------------------------------------- 1 | // This is an auto-generated file to redirect any included 2 | // module headers to the correct external folder. 3 | 4 | #include "../../../../JUCE/modules/juce_data_structures/juce_data_structures.h" 5 | 6 | -------------------------------------------------------------------------------- /JuceLibraryCode/modules/juce_audio_processors/juce_audio_processors.h: -------------------------------------------------------------------------------- 1 | // This is an auto-generated file to redirect any included 2 | // module headers to the correct external folder. 3 | 4 | #include "../../../../JUCE/modules/juce_audio_processors/juce_audio_processors.h" 5 | 6 | -------------------------------------------------------------------------------- /JuceLibraryCode/modules/juce_audio_plugin_client/juce_audio_plugin_client.h: -------------------------------------------------------------------------------- 1 | // This is an auto-generated file to redirect any included 2 | // module headers to the correct external folder. 3 | 4 | #include "../../../../JUCE/modules/juce_audio_plugin_client/juce_audio_plugin_client.h" 5 | 6 | -------------------------------------------------------------------------------- /JuceLibraryCode/ReadMe.txt: -------------------------------------------------------------------------------- 1 | 2 | Important Note!! 3 | ================ 4 | 5 | The purpose of this folder is to contain files that are auto-generated by the Introjucer, 6 | and ALL files in this folder will be mercilessly DELETED and completely re-written whenever 7 | the Introjucer saves your project. 8 | 9 | Therefore, it's a bad idea to make any manual changes to the files in here, or to 10 | put any of your own files in here if you don't want to lose them. (Of course you may choose 11 | to add the folder's contents to your version-control system so that you can re-merge your own 12 | modifications after the Introjucer has saved its changes). 13 | -------------------------------------------------------------------------------- /Builds/VisualStudio2005/resources.rc: -------------------------------------------------------------------------------- 1 | #ifdef JUCE_USER_DEFINED_RC_FILE 2 | #include JUCE_USER_DEFINED_RC_FILE 3 | #else 4 | 5 | #undef WIN32_LEAN_AND_MEAN 6 | #define WIN32_LEAN_AND_MEAN 7 | #include 8 | 9 | VS_VERSION_INFO VERSIONINFO 10 | FILEVERSION 1,0,0,0 11 | BEGIN 12 | BLOCK "StringFileInfo" 13 | BEGIN 14 | BLOCK "040904E4" 15 | BEGIN 16 | VALUE "CompanyName", "Smarteletronix\0" 17 | VALUE "FileDescription", "Livecut\0" 18 | VALUE "FileVersion", "1.0.0\0" 19 | VALUE "ProductName", "Livecut\0" 20 | VALUE "ProductVersion", "1.0.0\0" 21 | END 22 | END 23 | 24 | BLOCK "VarFileInfo" 25 | BEGIN 26 | VALUE "Translation", 0x409, 65001 27 | END 28 | END 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /Builds/VisualStudio2012/resources.rc: -------------------------------------------------------------------------------- 1 | #ifdef JUCE_USER_DEFINED_RC_FILE 2 | #include JUCE_USER_DEFINED_RC_FILE 3 | #else 4 | 5 | #undef WIN32_LEAN_AND_MEAN 6 | #define WIN32_LEAN_AND_MEAN 7 | #include 8 | 9 | VS_VERSION_INFO VERSIONINFO 10 | FILEVERSION 1,0,0,0 11 | BEGIN 12 | BLOCK "StringFileInfo" 13 | BEGIN 14 | BLOCK "040904E4" 15 | BEGIN 16 | VALUE "CompanyName", "Smarteletronix\0" 17 | VALUE "FileDescription", "Livecut\0" 18 | VALUE "FileVersion", "1.0.0\0" 19 | VALUE "ProductName", "Livecut\0" 20 | VALUE "ProductVersion", "1.0.0\0" 21 | END 22 | END 23 | 24 | BLOCK "VarFileInfo" 25 | BEGIN 26 | VALUE "Translation", 0x409, 65001 27 | END 28 | END 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | This file is part of Livecut 2 | Copyright 2003 by Remy Muller. 3 | 4 | Livecut can be redistributed and/or modified under the terms of the 5 | GNU General Public License, as published by the Free Software Foundation; 6 | either version 2 of the License, or (at your option) any later version. 7 | 8 | Livecut is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with AnalogDelay; if not, visit www.gnu.org/licenses or write to the 15 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 16 | Boston, MA 02111-1307 USA -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Livecut 2 | ======= 3 | 4 | Livecut is based on [BBCut](http://www.cus.cam.ac.uk/~nc272/papers/pdfs/bbcutlib.pdf) the BreakBeat Cutting library written by [Nick Collins](http://www.cus.cam.ac.uk/~nc272/) for [SuperCollider](http://supercollider.sourceforge.net/) 5 | 6 | The BBCut Library began out of work on an algorithm to simulate the automatic cutting of breakbeats in the style of early jungle or drum and bass, Nick Collins. 7 | 8 | Livecut is only a small subset of what is possible with BBCut, but as it is available as a VST plugin, it is much easier to start experimenting with it. 9 | 10 | It is a live beat-slicer but instead of manipulating equal chunks of audio like most beatslicer do, it works on the notion of audio *cuts* whose length and number of repetition depends on the context and the cutting procedure. 11 | *Cuts* are organized in *blocks* which then form a *phrase*. see Image below. And each phrase can be ended by a *roll* or *fill*. 12 | -------------------------------------------------------------------------------- /Builds/VisualStudio2012/Livecut.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 11.00 2 | # Visual Studio 2012 3 | Project("{7A25972C-665D-5546-6626-ED9C4B9FCDB0}") = "Livecut", "Livecut.vcxproj", "{D99C8971-135C-4B8D-1AB4-FAA90C2ED369}" 4 | EndProject 5 | Global 6 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 7 | Debug|Win32 = Debug|Win32 8 | Release|Win32 = Release|Win32 9 | EndGlobalSection 10 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 11 | {D99C8971-135C-4B8D-1AB4-FAA90C2ED369}.Debug|Win32.ActiveCfg = Debug|Win32 12 | {D99C8971-135C-4B8D-1AB4-FAA90C2ED369}.Debug|Win32.Build.0 = Debug|Win32 13 | {D99C8971-135C-4B8D-1AB4-FAA90C2ED369}.Release|Win32.ActiveCfg = Release|Win32 14 | {D99C8971-135C-4B8D-1AB4-FAA90C2ED369}.Release|Win32.Build.0 = Release|Win32 15 | EndGlobalSection 16 | GlobalSection(SolutionProperties) = preSolution 17 | HideSolutionNode = FALSE 18 | EndGlobalSection 19 | EndGlobal 20 | -------------------------------------------------------------------------------- /Builds/VisualStudio2005/Livecut.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 9.00 2 | # Visual C++ Express 2005 3 | Project("{7A25972C-665D-5546-6626-ED9C4B9FCDB0}") = "Livecut", "Livecut.vcproj", "{D99C8971-135C-4B8D-1AB4-FAA90C2ED369}" 4 | EndProject 5 | Global 6 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 7 | Debug|Win32 = Debug|Win32 8 | Release|Win32 = Release|Win32 9 | EndGlobalSection 10 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 11 | {D99C8971-135C-4B8D-1AB4-FAA90C2ED369}.Debug|Win32.ActiveCfg = Debug|Win32 12 | {D99C8971-135C-4B8D-1AB4-FAA90C2ED369}.Debug|Win32.Build.0 = Debug|Win32 13 | {D99C8971-135C-4B8D-1AB4-FAA90C2ED369}.Release|Win32.ActiveCfg = Release|Win32 14 | {D99C8971-135C-4B8D-1AB4-FAA90C2ED369}.Release|Win32.Build.0 = Release|Win32 15 | EndGlobalSection 16 | GlobalSection(SolutionProperties) = preSolution 17 | HideSolutionNode = FALSE 18 | EndGlobalSection 19 | EndGlobal 20 | -------------------------------------------------------------------------------- /Source/ParamButton.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Livecut 3 | Copyright 2003 by Remy Muller. 4 | 5 | Livecut can be redistributed and/or modified under the terms of the 6 | GNU General Public License, as published by the Free Software Foundation; 7 | either version 2 of the License, or (at your option) any later version. 8 | 9 | Livecut is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Livecut; if not, visit www.gnu.org/licenses or write to the 16 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 17 | Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #ifndef PARAM_BUTTON_H 21 | #define PARAM_BUTTON_H 22 | 23 | #include "../JuceLibraryCode/JuceHeader.h" 24 | #include "Control.h" 25 | 26 | class ParamButton : public TextButton, public Control 27 | { 28 | public: 29 | ParamButton(AudioProcessor &effect, int paramId); 30 | ~ParamButton(); 31 | 32 | virtual void refresh(); 33 | virtual void clicked(); 34 | }; 35 | 36 | #endif -------------------------------------------------------------------------------- /Source/ParamSlider.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Livecut 3 | Copyright 2003 by Remy Muller. 4 | 5 | Livecut can be redistributed and/or modified under the terms of the 6 | GNU General Public License, as published by the Free Software Foundation; 7 | either version 2 of the License, or (at your option) any later version. 8 | 9 | Livecut is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Livecut; if not, visit www.gnu.org/licenses or write to the 16 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 17 | Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #ifndef PARAM_SLIDER_H 21 | #define PARAM_SLIDER_H 22 | 23 | #include "../JuceLibraryCode/JuceHeader.h" 24 | #include "Control.h" 25 | 26 | class ParamSlider : public Slider, public Control 27 | { 28 | public: 29 | ParamSlider(AudioProcessor &effect, int paramId); 30 | ~ParamSlider(); 31 | 32 | virtual void valueChanged(); 33 | 34 | virtual void refresh(); 35 | }; 36 | 37 | #endif -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Compiled Dynamic libraries 8 | *.so 9 | *.dylib 10 | *.dll 11 | 12 | # Compiled Static libraries 13 | *.lai 14 | *.la 15 | *.a 16 | *.lib 17 | 18 | # Executables 19 | *.exe 20 | *.out 21 | *.app 22 | 23 | # XCode 24 | *.xcworkspace 25 | *.xcscheme 26 | 27 | # mac 28 | *.DS_Store 29 | 30 | ## Ignore Visual Studio temporary files, build results, and 31 | ## files generated by popular Visual Studio add-ons. 32 | 33 | # User-specific files 34 | *.suo 35 | *.user 36 | *.sln.docstates 37 | 38 | # Build results 39 | [Dd]ebug/ 40 | [Dd]ebugPublic/ 41 | [Rr]elease/ 42 | [Rr]eleases/ 43 | x64/ 44 | 45 | *_i.c 46 | *_p.c 47 | *_i.h 48 | *.ilk 49 | *.meta 50 | *.obj 51 | *.pch 52 | *.pdb 53 | *.pgc 54 | *.pgd 55 | *.rsp 56 | *.sbr 57 | *.tlb 58 | *.tli 59 | *.tlh 60 | *.tmp 61 | *.tmp_proj 62 | *.log 63 | *.vspscc 64 | *.vssscc 65 | .builds 66 | *.pidb 67 | *.svclog 68 | *.scc 69 | 70 | # Visual C++ cache files 71 | ipch/ 72 | *.aps 73 | *.ncb 74 | *.opensdf 75 | *.sdf 76 | *.cachefile 77 | 78 | # Backup & report files from converting an old project file 79 | # to a newer Visual Studio version. Backup files are not needed, 80 | # because we have git ;-) 81 | _UpgradeReport_Files/ 82 | Backup*/ 83 | UpgradeLog*.XML 84 | UpgradeLog*.htm -------------------------------------------------------------------------------- /Source/ParamCombo.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Livecut 3 | Copyright 2003 by Remy Muller. 4 | 5 | AnalogDelay can be redistributed and/or modified under the terms of the 6 | GNU General Public License, as published by the Free Software Foundation; 7 | either version 2 of the License, or (at your option) any later version. 8 | 9 | AnalogDelay is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with AnalogDelay; if not, visit www.gnu.org/licenses or write to the 16 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 17 | Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #ifndef PARAM_COMBO_H 21 | #define PARAM_COMBO_H 22 | 23 | #include "../JuceLibraryCode/JuceHeader.h" 24 | #include "Control.h" 25 | 26 | class ParamCombo : public ComboBox, public Control, ComboBoxListener 27 | { 28 | public: 29 | ParamCombo(AudioProcessor &effect, int paramId); 30 | ~ParamCombo(); 31 | 32 | private: 33 | virtual void refresh(); 34 | virtual void comboBoxChanged (ComboBox* comboBoxThatHasChanged); 35 | 36 | }; 37 | 38 | #endif -------------------------------------------------------------------------------- /Source/ParamLabel.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Livecut 3 | Copyright 2003 by Remy Muller. 4 | 5 | Livecut can be redistributed and/or modified under the terms of the 6 | GNU General Public License, as published by the Free Software Foundation; 7 | either version 2 of the License, or (at your option) any later version. 8 | 9 | Livecut is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Livecut; if not, visit www.gnu.org/licenses or write to the 16 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 17 | Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #ifndef PARAM_LABEL_H 21 | #define PARAM_LABEL_H 22 | 23 | #include "../JuceLibraryCode/JuceHeader.h" 24 | #include "Control.h" 25 | 26 | class ParamLabel : public Label, public Control 27 | { 28 | public: 29 | enum Mode 30 | { 31 | showParameterValue=0, 32 | showParameterName, 33 | }; 34 | 35 | ParamLabel(AudioProcessor &effect, 36 | int paramId, 37 | Mode mode=showParameterValue); 38 | ~ParamLabel(); 39 | 40 | virtual void refresh(); 41 | 42 | protected: 43 | Mode mMode; 44 | }; 45 | 46 | #endif -------------------------------------------------------------------------------- /Source/ParamLabel.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Livecut 3 | Copyright 2003 by Remy Muller. 4 | 5 | Livecut can be redistributed and/or modified under the terms of the 6 | GNU General Public License, as published by the Free Software Foundation; 7 | either version 2 of the License, or (at your option) any later version. 8 | 9 | Livecut is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Livecut; if not, visit www.gnu.org/licenses or write to the 16 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 17 | Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #include "ParamLabel.h" 21 | 22 | ParamLabel::ParamLabel(AudioProcessor &effect, int paramId, Mode mode) 23 | : Label("ADLabel", "") 24 | , Control(effect, paramId) 25 | , mMode(mode) 26 | { 27 | setSize(40, 20); 28 | refresh(); 29 | } 30 | 31 | ParamLabel::~ParamLabel() 32 | { 33 | } 34 | 35 | void ParamLabel::refresh() 36 | { 37 | const String text = mMode==showParameterValue ? mEffect.getParameterText(mParamId) : mEffect.getParameterName(mParamId); 38 | 39 | if(text != getText()) 40 | { 41 | setText(text, dontSendNotification); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Source/SQPAmp.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Livecut 3 | Copyright 2003 by Remy Muller. 4 | 5 | Livecut can be redistributed and/or modified under the terms of the 6 | GNU General Public License, as published by the Free Software Foundation; 7 | either version 2 of the License, or (at your option) any later version. 8 | 9 | Livecut is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Livecut; if not, visit www.gnu.org/licenses or write to the 16 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 17 | Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #include "SQPAmp.h" 21 | 22 | SQPAmp::SQPAmp() 23 | : on(true) 24 | , amp(1.f) 25 | { 26 | } 27 | 28 | void SQPAmp::OnSemiQuaver(long semi) 29 | { 30 | // proba of amp=1 on semiquaver 31 | static double amptemplate[]= 32 | { 33 | 1.0, 0, 0.09, 0.06, 34 | 0.24, 0.03, 0.15, 0.06, 35 | 0.21, 0.03, 0.12, 0.09, 36 | 0.24, 0.21, 0.18, 0.21 37 | }; 38 | const float random = Math::randomfloat(0.0,1.0); 39 | const float proba = amptemplate[semi]; 40 | amp = (random0.5f)? true : false; 36 | 37 | if(v != getToggleState()) 38 | { 39 | setToggleState(v, false); 40 | } 41 | } 42 | 43 | void ParamButton::clicked() 44 | { 45 | setParameter(getToggleState()? 1.f : 0.f); 46 | } 47 | -------------------------------------------------------------------------------- /Source/SQPAmp.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Livecut 3 | Copyright 2003 by Remy Muller. 4 | 5 | Livecut can be redistributed and/or modified under the terms of the 6 | GNU General Public License, as published by the Free Software Foundation; 7 | either version 2 of the License, or (at your option) any later version. 8 | 9 | Livecut is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Livecut; if not, visit www.gnu.org/licenses or write to the 16 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 17 | Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #ifndef SQUARE_PUSHER_AMP_H 21 | #define SQUARE_PUSHER_AMP_H 22 | 23 | #include "BBCutter.h" 24 | 25 | class SQPAmp : public BBCutListener 26 | { 27 | public: 28 | SQPAmp(); 29 | 30 | void OnSemiQuaver(long semi); 31 | void SetOn(bool v); 32 | 33 | inline void tick(float &out1, 34 | float &out2, 35 | const float in1, 36 | const float in2) 37 | { 38 | if(on) 39 | { 40 | out1 = amp*in1; 41 | out2 = amp*in2; 42 | } 43 | else 44 | { 45 | out1 = in1; 46 | out2 = in2; 47 | } 48 | } 49 | 50 | private: 51 | bool on; 52 | float amp; 53 | }; 54 | 55 | #endif -------------------------------------------------------------------------------- /Source/ParamSlider.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Livecut 3 | Copyright 2003 by Remy Muller. 4 | 5 | Livecut can be redistributed and/or modified under the terms of the 6 | GNU General Public License, as published by the Free Software Foundation; 7 | either version 2 of the License, or (at your option) any later version. 8 | 9 | Livecut is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Livecut; if not, visit www.gnu.org/licenses or write to the 16 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 17 | Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #include "ParamSlider.h" 21 | 22 | ParamSlider::ParamSlider(AudioProcessor &effect, int paramId) 23 | : Slider("ParamSlider") 24 | , Control(effect, paramId) 25 | { 26 | setRange(0, 1); 27 | 28 | setTextBoxStyle(juce::Slider::NoTextBox, true, 0, 0); 29 | setSliderStyle(juce::Slider::LinearHorizontal); 30 | } 31 | 32 | ParamSlider::~ParamSlider() 33 | { 34 | } 35 | 36 | void ParamSlider::valueChanged() 37 | { 38 | setParameter((float)getValue()); 39 | } 40 | 41 | void ParamSlider::refresh() 42 | { 43 | const double x = mEffect.getParameter(mParamId); 44 | 45 | if(x != getValue()) 46 | { 47 | setValue(x, dontSendNotification); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Source/FirstOrderLowpass.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Livecut 3 | Copyright 2004 by Remy Muller. 4 | 5 | Livecut can be redistributed and/or modified under the terms of the 6 | GNU General Public License, as published by the Free Software Foundation; 7 | either version 2 of the License, or (at your option) any later version. 8 | 9 | Livecut is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Livecut; if not, visit www.gnu.org/licenses or write to the 16 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 17 | Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #include "FirstOrderLowpass.h" 21 | #include 22 | 23 | 24 | FirstOrderLowpass::FirstOrderLowpass() 25 | : lambda(0) 26 | , sr(0) 27 | , lastout(0) 28 | { 29 | } 30 | 31 | FirstOrderLowpass::~FirstOrderLowpass() 32 | { 33 | } 34 | 35 | void FirstOrderLowpass::SetTimeConstant(float t) 36 | { 37 | time = t; 38 | lambda = std::exp(std::log(1.0-0.66)/(0.001*time*sr)); 39 | } 40 | 41 | void FirstOrderLowpass::SetSampleRate(float samplerate) 42 | { 43 | sr = samplerate; 44 | SetTimeConstant(time); 45 | } 46 | 47 | void FirstOrderLowpass::clear() 48 | { 49 | lastout = 0.0f; 50 | } 51 | 52 | void FirstOrderLowpass::SetState(float v) 53 | { 54 | lastout=v; 55 | } 56 | -------------------------------------------------------------------------------- /Builds/MacOSX/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | CFBundleExecutable 7 | ${EXECUTABLE_NAME} 8 | CFBundleIconFile 9 | 10 | CFBundleIdentifier 11 | com.smartelectronix.mdsp.Livecut 12 | CFBundleName 13 | Livecut 14 | CFBundlePackageType 15 | TDMw 16 | CFBundleSignature 17 | PTul 18 | CFBundleShortVersionString 19 | 1.0.0 20 | CFBundleVersion 21 | 1.0.0 22 | NSHumanReadableCopyright 23 | Smarteletronix 24 | NSHighResolutionCapable 25 | 26 | AudioComponents 27 | 28 | 29 | name 30 | Mdsp @ Smartelectronix: Livecut 31 | description 32 | Livecut 33 | factoryFunction 34 | LivecutAUFactory 35 | manufacturer 36 | MDSP 37 | type 38 | aufx 39 | subtype 40 | lvct 41 | version 42 | 65536 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /JuceLibraryCode/JuceHeader.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | This is the header file that your files should include in order to get all the 7 | JUCE library headers. You should avoid including the JUCE headers directly in 8 | your own source files, because that wouldn't pick up the correct configuration 9 | options for your app. 10 | 11 | */ 12 | 13 | #ifndef __APPHEADERFILE_HZGYI6__ 14 | #define __APPHEADERFILE_HZGYI6__ 15 | 16 | #include "AppConfig.h" 17 | #include "modules/juce_audio_basics/juce_audio_basics.h" 18 | #include "modules/juce_audio_plugin_client/juce_audio_plugin_client.h" 19 | #include "modules/juce_audio_processors/juce_audio_processors.h" 20 | #include "modules/juce_core/juce_core.h" 21 | #include "modules/juce_data_structures/juce_data_structures.h" 22 | #include "modules/juce_events/juce_events.h" 23 | #include "modules/juce_graphics/juce_graphics.h" 24 | #include "modules/juce_gui_basics/juce_gui_basics.h" 25 | #include "modules/juce_gui_extra/juce_gui_extra.h" 26 | 27 | #if ! DONT_SET_USING_JUCE_NAMESPACE 28 | // If your code uses a lot of JUCE classes, then this will obviously save you 29 | // a lot of typing, but can be disabled by setting DONT_SET_USING_JUCE_NAMESPACE. 30 | using namespace juce; 31 | #endif 32 | 33 | namespace ProjectInfo 34 | { 35 | const char* const projectName = "Livecut"; 36 | const char* const versionString = "1.0.0"; 37 | const int versionNumber = 0x10000; 38 | } 39 | 40 | #endif // __APPHEADERFILE_HZGYI6__ 41 | -------------------------------------------------------------------------------- /Source/Control.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Livecut 3 | Copyright 2003 by Remy Muller. 4 | 5 | Livecut can be redistributed and/or modified under the terms of the 6 | GNU General Public License, as published by the Free Software Foundation; 7 | either version 2 of the License, or (at your option) any later version. 8 | 9 | Livecut is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Livecut; if not, visit www.gnu.org/licenses or write to the 16 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 17 | Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #ifndef LIVECUT_CONTROL_H 21 | #define LIVECUT_CONTROL_H 22 | 23 | #include "../JuceLibraryCode/JuceHeader.h" 24 | 25 | class Control : public AudioProcessorListener, AsyncUpdater 26 | { 27 | public: 28 | Control(AudioProcessor &effect, int paramId); 29 | virtual ~Control(); 30 | 31 | virtual void refresh() = 0; 32 | 33 | virtual void setParameter(const float val); 34 | virtual float getParameter(); 35 | 36 | private: 37 | virtual void audioProcessorParameterChanged (AudioProcessor* processor, 38 | int parameterIndex, 39 | float newValue); 40 | virtual void audioProcessorChanged (AudioProcessor* processor); 41 | virtual void handleAsyncUpdate(); 42 | 43 | protected: 44 | AudioProcessor &mEffect; 45 | int mParamId; 46 | }; 47 | 48 | #endif -------------------------------------------------------------------------------- /Source/LivecutEditor.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Livecut 3 | Copyright 2004 by Remy Muller. 4 | 5 | Livecut can be redistributed and/or modified under the terms of the 6 | GNU General Public License, as published by the Free Software Foundation; 7 | either version 2 of the License, or (at your option) any later version. 8 | 9 | Livecut is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Livecut; if not, visit www.gnu.org/licenses or write to the 16 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 17 | Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #ifndef LIVECUT_EDITOR_H 21 | #define LIVECUT_EDITOR_H 22 | 23 | #include "../JuceLibraryCode/JuceHeader.h" 24 | #include "LivecutProcessor.h" 25 | 26 | class LivecutAudioProcessorEditor : public AudioProcessorEditor 27 | { 28 | public: 29 | LivecutAudioProcessorEditor (LivecutAudioProcessor* ownerFilter); 30 | ~LivecutAudioProcessorEditor(); 31 | 32 | void addSlider(int paramId, 33 | int row, 34 | int col); 35 | 36 | void addKnob(int paramId, 37 | int row, 38 | int col); 39 | private: 40 | 41 | void addControl(int kind, 42 | int paramId, 43 | int row, 44 | int col, 45 | int rowSpan, 46 | int colSpan); 47 | 48 | private: 49 | void paint (Graphics& g); 50 | void paintOverChildren (Graphics& g); 51 | }; 52 | 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /Source/Control.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Livecut 3 | Copyright 2003 by Remy Muller. 4 | 5 | Livecut can be redistributed and/or modified under the terms of the 6 | GNU General Public License, as published by the Free Software Foundation; 7 | either version 2 of the License, or (at your option) any later version. 8 | 9 | Livecut is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Livecut; if not, visit www.gnu.org/licenses or write to the 16 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 17 | Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #include "Control.h" 21 | 22 | Control::Control(AudioProcessor &effect, int paramId) 23 | : mEffect(effect) 24 | , mParamId(paramId) 25 | { 26 | mEffect.addListener(this); 27 | triggerAsyncUpdate(); 28 | } 29 | 30 | Control::~Control() 31 | { 32 | mEffect.removeListener(this); 33 | } 34 | 35 | void Control::setParameter(const float val) 36 | { 37 | mEffect.setParameterNotifyingHost(mParamId, val); 38 | } 39 | 40 | float Control::getParameter() 41 | { 42 | return mEffect.getParameter(mParamId); 43 | } 44 | 45 | void Control::audioProcessorParameterChanged (AudioProcessor* processor, 46 | int parameterIndex, 47 | float newValue) 48 | { 49 | triggerAsyncUpdate(); 50 | } 51 | 52 | void Control::audioProcessorChanged (AudioProcessor* processor) 53 | { 54 | triggerAsyncUpdate(); 55 | } 56 | 57 | void Control::handleAsyncUpdate() 58 | { 59 | refresh(); 60 | } 61 | -------------------------------------------------------------------------------- /Source/FirstOrderLowpass.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Livecut 3 | Copyright 2004 by Remy Muller. 4 | 5 | Livecut can be redistributed and/or modified under the terms of the 6 | GNU General Public License, as published by the Free Software Foundation; 7 | either version 2 of the License, or (at your option) any later version. 8 | 9 | Livecut is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Livecut; if not, visit www.gnu.org/licenses or write to the 16 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 17 | Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #ifndef FIRST_ORDER_LOWPASS_H 21 | #define FIRST_ORDER_LOWPASS_H 22 | 23 | class FirstOrderLowpass 24 | { 25 | public: 26 | FirstOrderLowpass(); 27 | 28 | ~FirstOrderLowpass(); 29 | 30 | inline float tick(float x) 31 | { 32 | add_white_noise(x); 33 | lastout *= lambda; 34 | lastout += (1.f-lambda)*x; 35 | return lastout; 36 | } 37 | 38 | inline float LastOut() 39 | { 40 | return lastout; 41 | } 42 | 43 | void SetTimeConstant(float t); 44 | void SetSampleRate(float samplerate); 45 | void clear(); 46 | 47 | inline void add_white_noise (float &val) 48 | { 49 | static unsigned int rand_state = rand_state * 1234567UL + 890123UL; 50 | int mantissa = rand_state & 0x807F0000; // Keep only most significant bits 51 | int flt_rnd = mantissa | 0x1E000000; // Set exponent 52 | val += *reinterpret_cast (&flt_rnd); 53 | } 54 | 55 | void SetState(float v); 56 | 57 | protected: 58 | float lambda; 59 | float sr; 60 | float lastout; 61 | float time; 62 | }; 63 | 64 | #endif -------------------------------------------------------------------------------- /Source/ParamCombo.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Livecut 3 | Copyright 2003 by Remy Muller. 4 | 5 | AnalogDelay can be redistributed and/or modified under the terms of the 6 | GNU General Public License, as published by the Free Software Foundation; 7 | either version 2 of the License, or (at your option) any later version. 8 | 9 | AnalogDelay is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with AnalogDelay; if not, visit www.gnu.org/licenses or write to the 16 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 17 | Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #include "ParamCombo.h" 21 | 22 | ParamCombo::ParamCombo(AudioProcessor &effect, int paramId) 23 | : ComboBox(effect.getParameterName(paramId)) 24 | , Control(effect, paramId) 25 | { 26 | } 27 | 28 | ParamCombo::~ParamCombo() 29 | { 30 | } 31 | 32 | void ParamCombo::refresh() 33 | { 34 | /* 35 | const bool v = (mEffect.getParameter(mParamId)>0.5f)? true : false; 36 | 37 | if(v != getToggleState()) 38 | { 39 | setToggleState(v, false); 40 | } 41 | */ 42 | } 43 | 44 | void ParamCombo::comboBoxChanged (ComboBox* comboBoxThatHasChanged) 45 | { 46 | int selected = getSelectedItemIndex(); 47 | 48 | if(selected>=0) 49 | { 50 | /* 51 | const int minimum = parameterDescription.mRange.GetMin(); 52 | const int maximum = parameterDescription.mRange.GetMax(); 53 | 54 | const int realValue = selected+minimum; 55 | 56 | setParameter(realValue); 57 | */ 58 | } 59 | } 60 | 61 | /* 62 | void ParamCombo::clicked() 63 | { 64 | setParameter(getToggleState()? 1.f : 0.f); 65 | } 66 | */ 67 | -------------------------------------------------------------------------------- /Source/Comb.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Livecut 3 | Copyright 2003 by Remy Muller. 4 | 5 | Livecut can be redistributed and/or modified under the terms of the 6 | GNU General Public License, as published by the Free Software Foundation; 7 | either version 2 of the License, or (at your option) any later version. 8 | 9 | Livecut is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Livecut; if not, visit www.gnu.org/licenses or write to the 16 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 17 | Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #include "Comb.h" 21 | 22 | Comb::Comb() 23 | : mindelay(50) 24 | , maxdelay(50) 25 | , startdelay(50) 26 | , enddelay(50) 27 | , feedback(0.5) 28 | , type(FeedForward) //feedforward 29 | , sr(44100) 30 | , delay(2205) 31 | , dl1(2205,44100) 32 | , dl2(2205,44100) // 50 ms 33 | , on(true) 34 | { 35 | lp.SetSampleRate(44100); 36 | lp.SetTimeConstant(40.f); //40 ms 37 | lp.SetState(50.f); 38 | } 39 | 40 | void Comb::OnBlock(long bar, long sd) 41 | { 42 | startdelay = Math::randomfloat(mindelay,maxdelay); 43 | enddelay = Math::randomfloat(mindelay,maxdelay); 44 | } 45 | 46 | void Comb::OnCut(long cut, long numcuts) 47 | { 48 | delay = (startdelay + (float(cut)/float(numcuts))*enddelay)*sr/1000.f; 49 | if(type==FeedForward) // feedforward 50 | { 51 | dl1.set_delay(delay); 52 | dl2.set_delay(delay); 53 | } 54 | } 55 | 56 | void Comb::SetMinDelay(float v) 57 | { 58 | mindelay = v; 59 | } 60 | 61 | void Comb::SetMaxDelay(float v) 62 | { 63 | maxdelay = v; 64 | } 65 | 66 | void Comb::SetType(long v) 67 | { 68 | type = v; 69 | } 70 | 71 | void Comb::SetFeedBack(float v) 72 | { 73 | feedback = v; 74 | } 75 | 76 | void Comb::SetSampleRate(float v) 77 | { 78 | sr = v; 79 | lp.SetSampleRate(v); 80 | } 81 | 82 | void Comb::SetOn(bool v) 83 | { 84 | on = v; 85 | } 86 | -------------------------------------------------------------------------------- /Source/Functor.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Livecut 3 | Copyright 2004 by Remy Muller. 4 | 5 | Livecut can be redistributed and/or modified under the terms of the 6 | GNU General Public License, as published by the Free Software Foundation; 7 | either version 2 of the License, or (at your option) any later version. 8 | 9 | Livecut is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Livecut; if not, visit www.gnu.org/licenses or write to the 16 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 17 | Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #ifndef FUNCTOR_H 21 | #define FUNCTOR_H 22 | 23 | #include 24 | 25 | template 26 | struct nop : public std::unary_function 27 | { 28 | R operator()(const T val) const 29 | { 30 | return; 31 | } 32 | }; 33 | 34 | template 35 | struct Fun 36 | { 37 | virtual void call(T v) = 0; 38 | }; 39 | 40 | template 41 | struct MemFun : public Fun 42 | { 43 | Fn fun; 44 | MemFun(Fn fun):Fun(),fun(fun){} 45 | virtual void call(typename Fn::argument_type v) 46 | { 47 | fun(v); 48 | } 49 | }; 50 | 51 | template 52 | inline MemFun< Fn > *newfun(Fn f) 53 | { 54 | return new MemFun< Fn >(f); 55 | } 56 | 57 | // functor adapter (*p->*pfunc)(val,val2), non-const *pfunc 58 | template 59 | class mem_fun2_t : public std::binary_function 60 | { 61 | public: 62 | explicit mem_fun2_t(T *o,R (T::*pm)(A1,A2)) 63 | : method(pm),obj(o) 64 | { 65 | } 66 | R operator()(A1 left, A2 right) const 67 | { 68 | return ((obj->*method)(left,right)); 69 | } 70 | private: 71 | R (T::*method)(A1,A2); // the member function pointer 72 | T *obj; //this pointer 73 | }; 74 | 75 | template 76 | inline mem_fun2_t memfun2(T *o,R (T::*pm)(A1,A2)) 77 | { 78 | return (mem_fun2_t(o,pm)); 79 | } 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /Source/BitCrusher.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Livecut 3 | Copyright 2003 by Remy Muller. 4 | 5 | Livecut can be redistributed and/or modified under the terms of the 6 | GNU General Public License, as published by the Free Software Foundation; 7 | either version 2 of the License, or (at your option) any later version. 8 | 9 | Livecut is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Livecut; if not, visit www.gnu.org/licenses or write to the 16 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 17 | Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #include "BitCrusher.h" 21 | 22 | BitCrusher::BitCrusher() 23 | : minbits(32) 24 | , maxbits(32) 25 | , startbits(32) 26 | , endbits(32) 27 | , multiplier(pow(2.f,32.f)) 28 | , divider(pow(2.f,-32.f)) 29 | , minfreq(44100) 30 | , maxfreq(44100) 31 | , startfreq(44100) 32 | , endfreq(44100) 33 | , sr(44100) 34 | , lag(1.f) 35 | , count(0.f) 36 | , memory1(0.f) 37 | , memory2(0.f) 38 | , on(true) 39 | { 40 | } 41 | 42 | void BitCrusher::OnBlock(long bar, long sd) 43 | { 44 | startbits = Math::randomfloat(minbits,maxbits); 45 | endbits = Math::randomfloat(minbits,maxbits); 46 | 47 | startfreq = Math::randomfloat(minfreq,maxfreq); 48 | endfreq = Math::randomfloat(minfreq,maxfreq); 49 | } 50 | 51 | void BitCrusher::OnCut(long cut, long numcuts) 52 | { 53 | float bits = startbits + (float(cut)/float(numcuts))*endbits; 54 | multiplier = pow(2.f,bits); 55 | divider = 1.f/multiplier; 56 | 57 | float freq = startfreq + (float(cut)/float(numcuts))*endfreq; 58 | lag = sr/freq; 59 | } 60 | 61 | // 0 - 32 62 | void BitCrusher::SetMinBits(float v){minbits = v;} 63 | void BitCrusher::SetMaxBits(float v){maxbits = v;} 64 | 65 | void BitCrusher::SetMinFreqFromNormalized(float v){minfreq = v*sr;} 66 | void BitCrusher::SetMaxFreqFromNormalized(float v){maxfreq = v*sr;} 67 | void BitCrusher::SetMinFreq(float v){minfreq = v;} 68 | void BitCrusher::SetMaxFreq(float v){maxfreq = v;} 69 | void BitCrusher::SetSampleRate(float v){sr = v;} 70 | void BitCrusher::SetOn(bool v){on = v;} 71 | -------------------------------------------------------------------------------- /Source/BitCrusher.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Livecut 3 | Copyright 2004 by Remy Muller. 4 | 5 | Livecut can be redistributed and/or modified under the terms of the 6 | GNU General Public License, as published by the Free Software Foundation; 7 | either version 2 of the License, or (at your option) any later version. 8 | 9 | Livecut is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Livecut; if not, visit www.gnu.org/licenses or write to the 16 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 17 | Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #ifndef LIVECUT_BIT_CRUSHER_H 21 | #define LIVECUT_BIT_CRUSHER_H 22 | 23 | /* 24 | BBCut MultiFX: 25 | 26 | * Bitcrusher 27 | * Samplerate reduction (sr) 28 | merge the 2 in one 29 | 30 | * Comb filter (feeback, freq Hz) 31 | */ 32 | 33 | #include "BBCutter.h" 34 | 35 | class BitCrusher : public BBCutListener 36 | { 37 | public: 38 | BitCrusher(); 39 | virtual void OnBlock(long bar, long sd); 40 | virtual void OnCut(long cut, long numcuts); 41 | 42 | void SetMinBits(float v); 43 | void SetMaxBits(float v); 44 | 45 | void SetMinFreqFromNormalized(float v); 46 | void SetMaxFreqFromNormalized(float v); 47 | void SetMinFreq(float v); 48 | void SetMaxFreq(float v); 49 | void SetSampleRate(float v); 50 | void SetOn(bool v); 51 | 52 | inline void tick(float &out1,float &out2, const float in1, const float in2) 53 | { 54 | if(on) 55 | { 56 | if(count>lag) 57 | { 58 | // it also add jitter we should interpolate instead, 59 | // but eh it's a bitcrusher! 60 | memory1 = floor(in1*multiplier)*divider; 61 | memory2 = floor(in2*multiplier)*divider; 62 | while(count>lag) 63 | count -= lag; 64 | } 65 | count += 1.f; 66 | out1 = memory1; 67 | out2 = memory2; 68 | } // if(on) 69 | else 70 | { 71 | out1 = in1; 72 | out2 = in2; 73 | } 74 | } 75 | 76 | private: 77 | float minbits,maxbits,startbits,endbits; 78 | float multiplier,divider; 79 | float minfreq,maxfreq,startfreq,endfreq; 80 | float sr; 81 | float lag,count; 82 | float memory1,memory2; 83 | bool on; 84 | }; 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /Source/Comb.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Livecut 3 | Copyright 2004 by Remy Muller. 4 | 5 | Livecut can be redistributed and/or modified under the terms of the 6 | GNU General Public License, as published by the Free Software Foundation; 7 | either version 2 of the License, or (at your option) any later version. 8 | 9 | Livecut is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Livecut; if not, visit www.gnu.org/licenses or write to the 16 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 17 | Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #ifndef LIVECUT_COMB_H 21 | #define LIVECUT_COMB_H 22 | 23 | #include "BBCutter.h" 24 | #include "DelayLine.h" 25 | #include "FirstOrderLowpass.h" 26 | 27 | inline float clip(float x) 28 | { 29 | return std::max(std::min(x, 1.f), -1.f); 30 | } 31 | 32 | class Comb : public BBCutListener 33 | { 34 | public: 35 | enum Type 36 | { 37 | FeedForward=0, 38 | FeedBack 39 | }; 40 | 41 | Comb(); 42 | 43 | virtual void OnBlock(long bar, long sd); 44 | virtual void OnCut(long cut, long numcuts); 45 | 46 | void SetMinDelay(float v); 47 | void SetMaxDelay(float v); 48 | void SetType(long v); 49 | void SetFeedBack(float v); 50 | void SetSampleRate(float v); 51 | void SetOn(bool v); 52 | 53 | inline void tick(float &out1,float &out2, const float in1, const float in2) 54 | { 55 | if(on) 56 | { 57 | if(type==FeedForward) // feedforward 58 | { 59 | out1 = 0.5f*(in1+dl1.tick(in1)); 60 | out2 = 0.5f*(in2+dl2.tick(in2)); 61 | } 62 | else // feedback 63 | { 64 | // need delay interpolation 65 | dl1.set_delay(lp.LastOut()); 66 | dl2.set_delay(lp.LastOut()); 67 | lp.tick(delay); 68 | out1 = clip((0.99f-feedback)*in1 + feedback*dl1.lastOut()); 69 | dl1.tick(out1); 70 | out2 = clip((0.99f-feedback)*in2 + feedback*dl2.lastOut()); 71 | dl2.tick(out2); 72 | } 73 | } 74 | else 75 | { 76 | out1 = in1; 77 | out2 = in2; 78 | } 79 | } 80 | private: 81 | float mindelay,maxdelay,startdelay,enddelay;//ms 82 | DelayLine dl1,dl2; 83 | float sr; 84 | float feedback; 85 | float delay; 86 | FirstOrderLowpass lp; 87 | bool on; 88 | long type; 89 | }; 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /Source/DelayLine.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Livecut 3 | Copyright 2003 by Remy Muller. 4 | 5 | Livecut can be redistributed and/or modified under the terms of the 6 | GNU General Public License, as published by the Free Software Foundation; 7 | either version 2 of the License, or (at your option) any later version. 8 | 9 | Livecut is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Livecut; if not, visit www.gnu.org/licenses or write to the 16 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 17 | Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #if !defined(_mDelay_line__) 21 | #define _mDelay_line__ 22 | 23 | #include "float_cast.h" 24 | 25 | //------------------------------------------------------- 26 | inline float linear_interpolation(const float* data, unsigned long mask, float pos) 27 | { 28 | int ipos = lrintf(pos); 29 | float frac = float(pos-ipos); 30 | return (1.0f-frac)*data[ipos&mask] + frac*data[(ipos+1)&mask]; 31 | } 32 | 33 | //------------------------------------------------------- 34 | class DelayLine 35 | { 36 | public: 37 | DelayLine(float delay=22050, long size=44100); 38 | ~DelayLine(); 39 | 40 | void resize(int size); 41 | 42 | void set_delay(float delay); 43 | 44 | inline float tick(const float x) 45 | { 46 | mpBuffer[mWriteIndex] = x; 47 | const float pos = float(mWriteIndex+mSize)-mDelay; 48 | (++mWriteIndex) &= mMask; 49 | return (mLastOut = linear_interpolation(mpBuffer,mMask,pos)); 50 | } 51 | 52 | void replace(const float x[],int pos,int size); 53 | void write(const float x[],int pos,int size); 54 | 55 | inline void write(const float x) 56 | { 57 | mpBuffer[mWriteIndex] = x; 58 | mWriteIndex++; mWriteIndex &= mMask; 59 | } 60 | 61 | inline float read() 62 | { 63 | float tmp = mpBuffer[mWriteIndex]; 64 | mWriteIndex++;mWriteIndex &= mMask; 65 | return tmp; 66 | } 67 | 68 | inline float tap(const long samples) 69 | { 70 | return mpBuffer[(mWriteIndex+mSize-samples)&mMask]; 71 | } 72 | 73 | inline float tapL(const float samples) 74 | { 75 | const float pos = float(mWriteIndex+mSize)-samples; 76 | return linear_interpolation(mpBuffer,mMask,pos); 77 | } 78 | 79 | inline float readErase() 80 | { 81 | float tmp = mpBuffer[mWriteIndex]; 82 | mpBuffer[mWriteIndex] = 0.0f; //erase automatically after read 83 | mWriteIndex++; mWriteIndex &= mMask; 84 | return tmp; 85 | } 86 | 87 | void read(float dest[],int pos,int size); 88 | 89 | void clear(); 90 | 91 | float* get_ptr(int pos=0) {return &(mpBuffer[(mWriteIndex+pos)&mMask]);} 92 | 93 | inline float lastOut() {return mLastOut;} 94 | 95 | private: 96 | float* mpBuffer; 97 | float mLastOut; 98 | float mDelay; 99 | long mWriteIndex; 100 | long mMask; 101 | long mSize; 102 | }; 103 | 104 | #endif //_mDelay_line_ 105 | -------------------------------------------------------------------------------- /Source/float_cast.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2001 Erik de Castro Lopo 3 | ** 4 | ** Permission to use, copy, modify, distribute, and sell this file for any 5 | ** purpose is hereby granted without fee, provided that the above copyright 6 | ** and this permission notice appear in all copies. No representations are 7 | ** made about the suitability of this software for any purpose. It is 8 | ** provided "as is" without express or implied warranty. 9 | */ 10 | 11 | /* Version 1.1 */ 12 | 13 | 14 | /*============================================================================ 15 | ** On Intel Pentium processors (especially PIII and probably P4), converting 16 | ** from float to int is very slow. To meet the C specs, the code produced by 17 | ** most C compilers targeting Pentium needs to change the FPU rounding mode 18 | ** before the float to int conversion is performed. 19 | ** 20 | ** Changing the FPU rounding mode causes the FPU pipeline to be flushed. It 21 | ** is this flushing of the pipeline which is so slow. 22 | ** 23 | ** Fortunately the ISO C99 specifications define the functions lrint, lrintf, 24 | ** llrint and llrintf which fix this problem as a side effect. 25 | ** 26 | ** On Unix-like systems, the configure process should have detected the 27 | ** presence of these functions. If they weren't found we have to replace them 28 | ** here with a standard C cast. 29 | */ 30 | 31 | /* 32 | ** The C99 prototypes for lrint and lrintf are as follows: 33 | ** 34 | ** long int lrintf (float x) ; 35 | ** long int lrint (double x) ; 36 | */ 37 | 38 | #ifdef MACX 39 | #define HAVE_LRINT 1 40 | #define HAVE_LRINTF 1 41 | #endif 42 | 43 | /* The presence of the required functions are detected during the configure 44 | ** process and the values HAVE_LRINT and HAVE_LRINTF are set accordingly in 45 | ** the config.h file. 46 | */ 47 | 48 | #if (HAVE_LRINT && HAVE_LRINTF) 49 | 50 | /* These defines enable functionality introduced with the 1999 ISO C 51 | ** standard. They must be defined before the inclusion of math.h to 52 | ** engage them. If optimisation is enabled, these functions will be 53 | ** inlined. With optimisation switched off, you have to link in the 54 | ** maths library using -lm. 55 | */ 56 | 57 | #define _ISOC9X_SOURCE 1 58 | #define _ISOC99_SOURCE 1 59 | 60 | #define __USE_ISOC9X 1 61 | #define __USE_ISOC99 1 62 | 63 | #include 64 | 65 | #elif (defined (WIN32) || defined (_WIN32)) 66 | 67 | #include 68 | 69 | // Win32 doesn't seem to have these functions. 70 | // Therefore implement inline versions of these functions here. 71 | 72 | 73 | __inline long int 74 | lrint (double flt) 75 | { int intgr; 76 | 77 | _asm 78 | { fld flt 79 | fistp intgr 80 | } ; 81 | 82 | return intgr ; 83 | } 84 | 85 | __inline long int 86 | lrintf (float flt) 87 | { int intgr; 88 | 89 | _asm 90 | { fld flt 91 | fistp intgr 92 | } ; 93 | 94 | return intgr ; 95 | } 96 | 97 | #else 98 | 99 | #warning "Don't have the functions lrint() and lrintf ()." 100 | #warning "Replacing these functions with a standard C cast." 101 | 102 | #include 103 | 104 | #define lrint(dbl) ((int)(dbl)) 105 | #define lrintf(flt) ((int)(flt)) 106 | 107 | #endif 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /Source/LivecutProcessor.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Livecut 3 | Copyright 2004 by Remy Muller. 4 | 5 | Livecut can be redistributed and/or modified under the terms of the 6 | GNU General Public License, as published by the Free Software Foundation; 7 | either version 2 of the License, or (at your option) any later version. 8 | 9 | Livecut is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Livecut; if not, visit www.gnu.org/licenses or write to the 16 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 17 | Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #ifndef LIVECUT_PROCESSOR_H 21 | #define LIVECUT_PROCESSOR_H 22 | 23 | #include "../JuceLibraryCode/JuceHeader.h" 24 | #include "BBCutter.h" 25 | #include "BitCrusher.h" 26 | #include "Comb.h" 27 | #include "SQPAmp.h" 28 | #include "Params.h" 29 | 30 | class LivecutAudioProcessor : public AudioProcessor 31 | { 32 | public: 33 | LivecutAudioProcessor(); 34 | ~LivecutAudioProcessor(); 35 | 36 | void prepareToPlay (double sampleRate, int samplesPerBlock); 37 | void releaseResources(); 38 | 39 | void processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages); 40 | 41 | AudioProcessorEditor* createEditor(); 42 | bool hasEditor() const; 43 | 44 | const String getName() const; 45 | 46 | int getNumParameters(); 47 | 48 | float getParameter (int index); 49 | void setParameter (int index, float newValue); 50 | 51 | const String getParameterName (int index); 52 | const String getParameterText (int index); 53 | 54 | const String getInputChannelName (int channelIndex) const; 55 | const String getOutputChannelName (int channelIndex) const; 56 | bool isInputChannelStereoPair (int index) const; 57 | bool isOutputChannelStereoPair (int index) const; 58 | 59 | bool acceptsMidi() const; 60 | bool producesMidi() const; 61 | bool silenceInProducesSilenceOut() const; 62 | 63 | int getNumPrograms(); 64 | int getCurrentProgram(); 65 | void setCurrentProgram (int index); 66 | const String getProgramName (int index); 67 | void changeProgramName (int index, const String& newName); 68 | 69 | void getStateInformation (MemoryBlock& destData); 70 | void setStateInformation (const void* data, int sizeInBytes); 71 | 72 | virtual double getTailLengthSeconds() const { return 0; } 73 | 74 | private: 75 | void Process(float **inputs,float **outputs, const long size); 76 | void AddParameter(Param ¶m); 77 | 78 | private: 79 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LivecutAudioProcessor) 80 | ParamMap params; 81 | 82 | AutoParam maxphraselength, minphraselength, stutterchance, stutterarea, straightchance, regularchance, ritardchance, accel, maxrepeats, minrepeats; 83 | IntSetParam subdiv; 84 | AutoParam activity, minamp, maxamp, minpan, maxpan, mindetune, maxdetune, dutycycle, filldutycycle, seed, minbits, maxbits, crusherswitch; 85 | PowerParam minfreq, maxfreq, fade; 86 | AutoParam combmindelay, combmaxdelay, combfeedback, combswitch, sqpampswitch; 87 | EnumParam strategy, combtype; 88 | 89 | LivePlayer player; 90 | BitCrusher crusher; 91 | Comb comb; 92 | SQPAmp sqpamp; 93 | BBCutter bbcutter; 94 | }; 95 | 96 | #endif 97 | -------------------------------------------------------------------------------- /Source/DelayLine.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Livecut 3 | Copyright 2003 by Remy Muller. 4 | 5 | Livecut can be redistributed and/or modified under the terms of the 6 | GNU General Public License, as published by the Free Software Foundation; 7 | either version 2 of the License, or (at your option) any later version. 8 | 9 | Livecut is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Livecut; if not, visit www.gnu.org/licenses or write to the 16 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 17 | Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #include "DelayLine.h" 21 | #include 22 | 23 | DelayLine::DelayLine(float delay, long size) 24 | : mpBuffer(0) 25 | , mLastOut(0) 26 | , mDelay(delay) 27 | , mWriteIndex(0) 28 | , mMask(0) 29 | , mSize(0) 30 | { 31 | int n = int(floor (log(double(size))/log(2.0) + 0.5))+1; 32 | mMask = 1 ; mMask <<= n; mMask -= 1; 33 | mSize = mMask+1; 34 | mpBuffer = new float[mSize]; 35 | clear(); 36 | } 37 | 38 | DelayLine::~DelayLine() 39 | { 40 | if(0 != mpBuffer) 41 | delete[] mpBuffer; 42 | mpBuffer = 0; 43 | } 44 | 45 | void DelayLine::resize(int size) 46 | { 47 | int n = int(floor (log(double(size))/log(2.0) + 0.5))+1; 48 | // when N is a multiple of 2 we choose the next power of 2... 49 | // not good... cf OLA ou FFTFactory 50 | mMask = 1 ; mMask <<= n; mMask -= 1; 51 | mSize = mMask+1; 52 | if(0 != mpBuffer) 53 | delete[] mpBuffer; 54 | mpBuffer = 0; 55 | mpBuffer = new float[mSize]; 56 | mWriteIndex = 0; 57 | clear(); 58 | } 59 | 60 | 61 | void DelayLine::set_delay(float delay) 62 | { 63 | mDelay = delay; 64 | } 65 | 66 | void DelayLine::replace(const float x[],int pos,int size) 67 | { 68 | int p = (mWriteIndex+pos); p &= mMask; 69 | int n = mSize-p; 70 | if(n>size) 71 | n = size ; 72 | else 73 | n = n; 74 | 75 | float *dest = mpBuffer+p; 76 | int i=0; 77 | for(;isize) 93 | n = size ; 94 | else 95 | n = n; 96 | 97 | float *dest = mpBuffer+p; 98 | int i=0; 99 | for(;isetBounds(margin, toolbarHeight+margin, buttonWidth, buttonHeight); 55 | addAndMakeVisible(pParamButton); 56 | } 57 | { 58 | ParamButton *pParamButton = new ParamButton(*ownerFilter, 28); 59 | pParamButton->setBounds(margin+buttonWidth+margin, toolbarHeight+margin, buttonWidth, buttonHeight); 60 | addAndMakeVisible(pParamButton); 61 | } 62 | 63 | for(int i=2; i<20; ++i) 64 | { 65 | ParamSlider *pParamSlider = new ParamSlider(*ownerFilter, i); 66 | pParamSlider->setBounds(margin, toolbarHeight+(2+i)*margin+(1+i)*buttonHeight, buttonWidth, buttonHeight); 67 | addAndMakeVisible(pParamSlider); 68 | 69 | { 70 | ParamLabel *pParamLabel = new ParamLabel(*ownerFilter, i, ParamLabel::showParameterValue); 71 | pParamLabel->setBounds(margin+buttonWidth+margin, toolbarHeight+(2+i)*margin+(1+i)*buttonHeight, buttonWidth, buttonHeight); 72 | addAndMakeVisible(pParamLabel); 73 | } 74 | { 75 | ParamLabel *pParamLabel = new ParamLabel(*ownerFilter, i, ParamLabel::showParameterName); 76 | pParamLabel->setBounds(margin+(buttonWidth+margin)*2, toolbarHeight+(2+i)*margin+(1+i)*buttonHeight, buttonWidth, buttonHeight); 77 | addAndMakeVisible(pParamLabel); 78 | } 79 | } 80 | */ 81 | } 82 | 83 | LivecutAudioProcessorEditor::~LivecutAudioProcessorEditor() 84 | { 85 | deleteAllChildren(); 86 | } 87 | 88 | void LivecutAudioProcessorEditor::addSlider(int paramId, 89 | int row, 90 | int col) 91 | { 92 | addControl(kParamName, paramId, row, col, 1, 3); 93 | addControl(kParamSlider, paramId, row, col+3, 1, 5); 94 | } 95 | 96 | void LivecutAudioProcessorEditor::addKnob(int paramId, 97 | int row, 98 | int col) 99 | { 100 | AudioProcessor &processor = *getAudioProcessor(); 101 | 102 | int colSpan = 2; 103 | int rowSpan = 2; 104 | int x = 10+30*col; 105 | int y = 10+30*row; 106 | int width = 20 + 30*(colSpan-1); 107 | int height = 20 + 30*(rowSpan-1); 108 | 109 | ParamLabel *pParamLabel = new ParamLabel(processor, paramId, ParamLabel::showParameterName); 110 | pParamLabel->setColour(Label::textColourId, Colours::black); 111 | pParamLabel->setBounds(x, y, width, 20); 112 | pParamLabel->setJustificationType(Justification::centred); 113 | addAndMakeVisible(pParamLabel); 114 | 115 | ParamSlider *pSlider = new ParamSlider(processor, paramId); 116 | pSlider->setSliderStyle(Slider::RotaryVerticalDrag); 117 | pSlider->setBounds(x, y+20, width, height-20); 118 | addAndMakeVisible(pSlider); 119 | } 120 | 121 | void LivecutAudioProcessorEditor::addControl(int kind, 122 | int paramId, 123 | int row, 124 | int col, 125 | int rowSpan, 126 | int colSpan) 127 | { 128 | AudioProcessor &processor = *getAudioProcessor(); 129 | 130 | int x = 10+30*col; 131 | int y = 10+30*row; 132 | int width = 20 + 30*(colSpan-1); 133 | int height = 20 + 30*(rowSpan-1); 134 | 135 | juce::Component *pControl = NULL; 136 | switch (kind) 137 | { 138 | case kParamSlider: pControl = new ParamSlider(processor, paramId); break; 139 | case kParamKnob: 140 | { 141 | ParamSlider *pSlider = new ParamSlider(processor, paramId); 142 | pSlider->setSliderStyle(Slider::RotaryVerticalDrag); 143 | pControl = pSlider; 144 | break; 145 | } 146 | case kParamName: pControl = new ParamLabel(processor, paramId, ParamLabel::showParameterName); break; 147 | case kParamValue: pControl = new ParamLabel(processor, paramId, ParamLabel::showParameterValue); break; 148 | case kParamButton: pControl = new ParamButton(processor, paramId); break; 149 | default: 150 | break; 151 | } 152 | 153 | if(pControl) 154 | { 155 | addAndMakeVisible(pControl); 156 | pControl->setBounds(x, y, width, height); 157 | } 158 | } 159 | 160 | void LivecutAudioProcessorEditor::paintOverChildren (Graphics& g) 161 | { 162 | } 163 | 164 | static const char* sectionNames[] = 165 | { 166 | "Global", "Pitch", "Env", 167 | "CutProc11", "WarpCut", "SQPusher", 168 | "Amplifier", "Crusher", "Comb" 169 | }; 170 | 171 | void LivecutAudioProcessorEditor::paint (Graphics& g) 172 | { 173 | g.fillAll (Colours::lightgrey); 174 | 175 | // grid 176 | for(uint col=0; col<24; ++col) 177 | { 178 | int x = 10+col*(20+10); 179 | 180 | g.setColour(Colours::black); 181 | g.drawText(String(col), Rectangle(x, 0, 20, getHeight()), Justification::topLeft, false); 182 | 183 | g.setColour(Colours::red.withAlpha(0.1f)); 184 | g.fillRect(x, 0, 20, getHeight()); 185 | } 186 | 187 | for(uint row=0; row<16; ++row) 188 | { 189 | int y = 10+row*(20+10); 190 | 191 | g.setColour(Colours::black); 192 | g.drawText(String(row), Rectangle(0, y, getWidth(), 20), Justification::topLeft, false); 193 | 194 | g.setColour(Colours::red.withAlpha(0.1f)); 195 | g.fillRect(0, y, getWidth(), 20); 196 | } 197 | 198 | g.setColour(Colours::black); 199 | g.setFont(juce::Font(20.0f, juce::Font::bold)); 200 | 201 | g.drawRect(0, 0, getWidth(), 30); 202 | g.drawFittedText ("Livecut", 203 | 10, 10, getWidth()-20, 20, 204 | Justification::centredLeft, 1); 205 | 206 | g.setFont(juce::Font(15.0f, juce::Font::bold)); 207 | g.drawFittedText ("Mdsp @ Smartelectronix", 208 | 10, 10, getWidth()-20, 20, 209 | Justification::centredRight, 1); 210 | 211 | for(uint row=0; row<3; ++row) 212 | { 213 | int y = 40+150*row; 214 | int width = 240-10; 215 | int height = 150-10; 216 | for(uint col=0; col<3; ++col) 217 | { 218 | int x = 10 + 240*col; 219 | g.drawRect(x, y, width, height); 220 | 221 | String text(sectionNames[row*3+col]); 222 | g.drawFittedText (text, 223 | x, y, width, 20, 224 | Justification::centred, 1); 225 | } 226 | } 227 | } 228 | 229 | -------------------------------------------------------------------------------- /JuceLibraryCode/AppConfig.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | There's a section below where you can add your own custom code safely, and the 7 | Introjucer will preserve the contents of that block, but the best way to change 8 | any of these definitions is by using the Introjucer's project settings. 9 | 10 | Any commented-out settings will assume their default values. 11 | 12 | */ 13 | 14 | #ifndef __JUCE_APPCONFIG_HZGYI6__ 15 | #define __JUCE_APPCONFIG_HZGYI6__ 16 | 17 | //============================================================================== 18 | // [BEGIN_USER_CODE_SECTION] 19 | 20 | // (You can add your own code in this section, and the Introjucer will not overwrite it) 21 | 22 | // [END_USER_CODE_SECTION] 23 | 24 | //============================================================================== 25 | #define JUCE_MODULE_AVAILABLE_juce_audio_basics 1 26 | #define JUCE_MODULE_AVAILABLE_juce_audio_plugin_client 1 27 | #define JUCE_MODULE_AVAILABLE_juce_audio_processors 1 28 | #define JUCE_MODULE_AVAILABLE_juce_core 1 29 | #define JUCE_MODULE_AVAILABLE_juce_data_structures 1 30 | #define JUCE_MODULE_AVAILABLE_juce_events 1 31 | #define JUCE_MODULE_AVAILABLE_juce_graphics 1 32 | #define JUCE_MODULE_AVAILABLE_juce_gui_basics 1 33 | #define JUCE_MODULE_AVAILABLE_juce_gui_extra 1 34 | 35 | //============================================================================== 36 | // juce_audio_processors flags: 37 | 38 | #ifndef JUCE_PLUGINHOST_VST 39 | //#define JUCE_PLUGINHOST_VST 40 | #endif 41 | 42 | #ifndef JUCE_PLUGINHOST_VST3 43 | //#define JUCE_PLUGINHOST_VST3 44 | #endif 45 | 46 | #ifndef JUCE_PLUGINHOST_AU 47 | //#define JUCE_PLUGINHOST_AU 48 | #endif 49 | 50 | //============================================================================== 51 | // juce_core flags: 52 | 53 | #ifndef JUCE_FORCE_DEBUG 54 | //#define JUCE_FORCE_DEBUG 55 | #endif 56 | 57 | #ifndef JUCE_LOG_ASSERTIONS 58 | //#define JUCE_LOG_ASSERTIONS 59 | #endif 60 | 61 | #ifndef JUCE_CHECK_MEMORY_LEAKS 62 | //#define JUCE_CHECK_MEMORY_LEAKS 63 | #endif 64 | 65 | #ifndef JUCE_DONT_AUTOLINK_TO_WIN32_LIBRARIES 66 | //#define JUCE_DONT_AUTOLINK_TO_WIN32_LIBRARIES 67 | #endif 68 | 69 | #ifndef JUCE_INCLUDE_ZLIB_CODE 70 | //#define JUCE_INCLUDE_ZLIB_CODE 71 | #endif 72 | 73 | //============================================================================== 74 | // juce_graphics flags: 75 | 76 | #ifndef JUCE_USE_COREIMAGE_LOADER 77 | //#define JUCE_USE_COREIMAGE_LOADER 78 | #endif 79 | 80 | #ifndef JUCE_USE_DIRECTWRITE 81 | //#define JUCE_USE_DIRECTWRITE 82 | #endif 83 | 84 | //============================================================================== 85 | // juce_gui_basics flags: 86 | 87 | #ifndef JUCE_ENABLE_REPAINT_DEBUGGING 88 | //#define JUCE_ENABLE_REPAINT_DEBUGGING 89 | #endif 90 | 91 | #ifndef JUCE_USE_XSHM 92 | //#define JUCE_USE_XSHM 93 | #endif 94 | 95 | #ifndef JUCE_USE_XRENDER 96 | //#define JUCE_USE_XRENDER 97 | #endif 98 | 99 | #ifndef JUCE_USE_XCURSOR 100 | //#define JUCE_USE_XCURSOR 101 | #endif 102 | 103 | //============================================================================== 104 | // juce_gui_extra flags: 105 | 106 | #ifndef JUCE_WEB_BROWSER 107 | //#define JUCE_WEB_BROWSER 108 | #endif 109 | 110 | #ifndef JUCE_ENABLE_LIVE_CONSTANT_EDITOR 111 | //#define JUCE_ENABLE_LIVE_CONSTANT_EDITOR 112 | #endif 113 | 114 | 115 | //============================================================================== 116 | // Audio plugin settings.. 117 | 118 | #ifndef JucePlugin_Build_VST 119 | #define JucePlugin_Build_VST 1 120 | #endif 121 | #ifndef JucePlugin_Build_VST3 122 | #define JucePlugin_Build_VST3 0 123 | #endif 124 | #ifndef JucePlugin_Build_AU 125 | #define JucePlugin_Build_AU 1 126 | #endif 127 | #ifndef JucePlugin_Build_RTAS 128 | #define JucePlugin_Build_RTAS 0 129 | #endif 130 | #ifndef JucePlugin_Build_AAX 131 | #define JucePlugin_Build_AAX 0 132 | #endif 133 | #ifndef JucePlugin_Name 134 | #define JucePlugin_Name "Livecut" 135 | #endif 136 | #ifndef JucePlugin_Desc 137 | #define JucePlugin_Desc "Livecut" 138 | #endif 139 | #ifndef JucePlugin_Manufacturer 140 | #define JucePlugin_Manufacturer "Mdsp @ Smartelectronix" 141 | #endif 142 | #ifndef JucePlugin_ManufacturerWebsite 143 | #define JucePlugin_ManufacturerWebsite "http://mdsp.smartelectronix.com/" 144 | #endif 145 | #ifndef JucePlugin_ManufacturerEmail 146 | #define JucePlugin_ManufacturerEmail "" 147 | #endif 148 | #ifndef JucePlugin_ManufacturerCode 149 | #define JucePlugin_ManufacturerCode 'MDSP' 150 | #endif 151 | #ifndef JucePlugin_PluginCode 152 | #define JucePlugin_PluginCode 'lvct' 153 | #endif 154 | #ifndef JucePlugin_MaxNumInputChannels 155 | #define JucePlugin_MaxNumInputChannels 2 156 | #endif 157 | #ifndef JucePlugin_MaxNumOutputChannels 158 | #define JucePlugin_MaxNumOutputChannels 2 159 | #endif 160 | #ifndef JucePlugin_PreferredChannelConfigurations 161 | #define JucePlugin_PreferredChannelConfigurations {2, 2} 162 | #endif 163 | #ifndef JucePlugin_IsSynth 164 | #define JucePlugin_IsSynth 0 165 | #endif 166 | #ifndef JucePlugin_WantsMidiInput 167 | #define JucePlugin_WantsMidiInput 0 168 | #endif 169 | #ifndef JucePlugin_ProducesMidiOutput 170 | #define JucePlugin_ProducesMidiOutput 0 171 | #endif 172 | #ifndef JucePlugin_SilenceInProducesSilenceOut 173 | #define JucePlugin_SilenceInProducesSilenceOut 0 174 | #endif 175 | #ifndef JucePlugin_EditorRequiresKeyboardFocus 176 | #define JucePlugin_EditorRequiresKeyboardFocus 0 177 | #endif 178 | #ifndef JucePlugin_Version 179 | #define JucePlugin_Version 1.0.0 180 | #endif 181 | #ifndef JucePlugin_VersionCode 182 | #define JucePlugin_VersionCode 0x10000 183 | #endif 184 | #ifndef JucePlugin_VersionString 185 | #define JucePlugin_VersionString "1.0.0" 186 | #endif 187 | #ifndef JucePlugin_VSTUniqueID 188 | #define JucePlugin_VSTUniqueID JucePlugin_PluginCode 189 | #endif 190 | #ifndef JucePlugin_VSTCategory 191 | #define JucePlugin_VSTCategory kPlugCategEffect 192 | #endif 193 | #ifndef JucePlugin_AUMainType 194 | #define JucePlugin_AUMainType kAudioUnitType_Effect 195 | #endif 196 | #ifndef JucePlugin_AUSubType 197 | #define JucePlugin_AUSubType JucePlugin_PluginCode 198 | #endif 199 | #ifndef JucePlugin_AUExportPrefix 200 | #define JucePlugin_AUExportPrefix LivecutAU 201 | #endif 202 | #ifndef JucePlugin_AUExportPrefixQuoted 203 | #define JucePlugin_AUExportPrefixQuoted "LivecutAU" 204 | #endif 205 | #ifndef JucePlugin_AUManufacturerCode 206 | #define JucePlugin_AUManufacturerCode JucePlugin_ManufacturerCode 207 | #endif 208 | #ifndef JucePlugin_CFBundleIdentifier 209 | #define JucePlugin_CFBundleIdentifier com.smartelectronix.mdsp.Livecut 210 | #endif 211 | #ifndef JucePlugin_RTASCategory 212 | #define JucePlugin_RTASCategory ePlugInCategory_None 213 | #endif 214 | #ifndef JucePlugin_RTASManufacturerCode 215 | #define JucePlugin_RTASManufacturerCode JucePlugin_ManufacturerCode 216 | #endif 217 | #ifndef JucePlugin_RTASProductId 218 | #define JucePlugin_RTASProductId JucePlugin_PluginCode 219 | #endif 220 | #ifndef JucePlugin_RTASDisableBypass 221 | #define JucePlugin_RTASDisableBypass 0 222 | #endif 223 | #ifndef JucePlugin_RTASDisableMultiMono 224 | #define JucePlugin_RTASDisableMultiMono 0 225 | #endif 226 | #ifndef JucePlugin_AAXIdentifier 227 | #define JucePlugin_AAXIdentifier com.yourcompany.Livecut 228 | #endif 229 | #ifndef JucePlugin_AAXManufacturerCode 230 | #define JucePlugin_AAXManufacturerCode JucePlugin_ManufacturerCode 231 | #endif 232 | #ifndef JucePlugin_AAXProductId 233 | #define JucePlugin_AAXProductId JucePlugin_PluginCode 234 | #endif 235 | #ifndef JucePlugin_AAXCategory 236 | #define JucePlugin_AAXCategory AAX_ePlugInCategory_Dynamics 237 | #endif 238 | #ifndef JucePlugin_AAXDisableBypass 239 | #define JucePlugin_AAXDisableBypass 0 240 | #endif 241 | #ifndef JucePlugin_AAXDisableMultiMono 242 | #define JucePlugin_AAXDisableMultiMono 0 243 | #endif 244 | 245 | #endif // __JUCE_APPCONFIG_HZGYI6__ 246 | -------------------------------------------------------------------------------- /Source/Params.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Livecut 3 | Copyright 2004 by Remy Muller. 4 | 5 | Livecut can be redistributed and/or modified under the terms of the 6 | GNU General Public License, as published by the Free Software Foundation; 7 | either version 2 of the License, or (at your option) any later version. 8 | 9 | Livecut is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Livecut; if not, visit www.gnu.org/licenses or write to the 16 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 17 | Boston, MA 02111-1307 USA 18 | */ 19 | 20 | /***************************************************************************** 21 | 22 | Params.cpp 23 | Copyright (c) 2004 [mdsp @ smartelectronix] 24 | 25 | *Tab=3***********************************************************************/ 26 | 27 | #include "Params.h" 28 | 29 | #include 30 | using namespace std; 31 | 32 | void Param::init (ParamList &list, float min, float def, float max, std::string name, std::string unit, long tag_, char cc_, Fun *f) 33 | { 34 | m_tag = tag_; 35 | m_cc = cc_; 36 | m_name = name; 37 | m_unit = unit; 38 | this->min = min; 39 | this->max = max; 40 | m_def = def; 41 | value = def; 42 | list.insert(ParamList::value_type(m_tag,this)); 43 | fun.f=f; 44 | } 45 | void Param::init (ParamList &list, long min, long def, long max, std::string name, std::string unit, long tag_, char cc_, Fun *f) 46 | { 47 | m_tag = tag_; 48 | m_cc = cc_; 49 | m_name = name; 50 | m_unit = unit; 51 | this->min = min; 52 | this->max = max; 53 | m_def = def; 54 | value = def; 55 | list.insert(ParamList::value_type(m_tag,this)); 56 | fun.i=f; 57 | } 58 | void Param::init (ParamList &list, bool def, std::string name, std::string unit, long tag_, char cc_, Fun *f) 59 | { 60 | m_tag = tag_; 61 | m_cc = cc_; 62 | m_name = name; 63 | m_unit = unit; 64 | min = false; 65 | max = true; 66 | m_def = def; 67 | value = def; 68 | list.insert(ParamList::value_type(m_tag,this)); 69 | fun.b=f; 70 | } 71 | Param& Param::name(string text) 72 | { 73 | m_name = text; 74 | return *this; 75 | } 76 | Param& Param::unit(string text) 77 | { 78 | m_unit = text; 79 | return *this; 80 | } 81 | Param& Param::range(float min, float max) 82 | { 83 | this->min = min; 84 | this->max = max; 85 | if(float(value)float(max)) 88 | value = max; 89 | return *this; 90 | } 91 | Param& Param::range(long min, long max) 92 | { 93 | this->min = min; 94 | this->max = max; 95 | if(long(value)long(max)) 98 | value = max; 99 | return *this; 100 | } 101 | Param& Param::def(float val) 102 | { 103 | m_def = val; 104 | value = val; 105 | return *this; 106 | } 107 | Param& Param::def(long val) 108 | { 109 | m_def = val; 110 | value = val; 111 | return *this; 112 | } 113 | Param& Param::def(bool val) 114 | { 115 | min = false; 116 | max = true; 117 | m_def = val; 118 | value = val; 119 | m_style = eSwitch; 120 | return *this; 121 | } 122 | Param& Param::tag(long v) 123 | { 124 | m_tag = v; 125 | return *this; 126 | } 127 | Param& Param::cc(long v) 128 | { 129 | m_cc = v; 130 | return *this; 131 | } 132 | Param& Param::functor(Fun *f) 133 | { 134 | fun.f=f; 135 | return *this; 136 | } 137 | Param& Param::functor(Fun *f) 138 | { 139 | fun.i=f; 140 | return *this; 141 | } 142 | Param& Param::functor(Fun *f) 143 | { 144 | fun.b=f; 145 | return *this; 146 | } 147 | 148 | string Param::GetDisplay () 149 | { 150 | std::ostringstream out; 151 | //out.precision(6); 152 | //out << showpoint; 153 | //out.width(10); 154 | switch(value.type) 155 | { 156 | case TYPEFLOAT: 157 | out << float(value); 158 | break; 159 | case TYPELONG: 160 | out << long(value); 161 | break; 162 | case TYPEBOOL: 163 | if(bool(value) == true) 164 | out << "true"; 165 | else 166 | out << "false"; 167 | break; 168 | case TYPEUNKNOWN: 169 | out << "Unknown"; 170 | } 171 | return out.str(); 172 | } 173 | void Param::FromDisplay(string s) 174 | { 175 | istringstream in(s); 176 | switch(value.type) 177 | { 178 | case TYPEFLOAT: 179 | { 180 | float v=0.f; 181 | in >> v; 182 | if(!in.fail()) 183 | value.u.f = v; 184 | break; 185 | } 186 | case TYPELONG: 187 | { 188 | long v = 0; 189 | in >> v; 190 | if(!in.fail()) 191 | value.u.i = v; 192 | break; 193 | } 194 | case TYPEBOOL: 195 | if(s == string("true")) 196 | value.u.b = true; 197 | else 198 | value.u.b = false; 199 | break; 200 | case TYPEUNKNOWN: value.u.i = 0; break; 201 | } 202 | Clip(); 203 | this->TellListeners(); 204 | } 205 | float Param::GetNormalized(Atom v) 206 | { 207 | float norm = 0.0f; 208 | switch(v.type) 209 | { 210 | case TYPEFLOAT: 211 | norm = (float(v)-float(min))/(float(max)-float(min)); 212 | break; 213 | case TYPELONG: 214 | norm = float(long(v)-long(min))/float(long(max)-long(min)); 215 | break; 216 | case TYPEBOOL: 217 | if(bool(v) == true) 218 | norm = 1.0f; 219 | else 220 | norm = 0.0f; 221 | break; 222 | case TYPEUNKNOWN: 223 | norm = 0.f; 224 | break; 225 | } 226 | return norm; 227 | } 228 | void Param::SetFromNormalized(float norm) 229 | { 230 | switch(value.type) 231 | { 232 | case TYPEFLOAT: 233 | value = float(min)+norm*(float(max)-float(min)); 234 | break; 235 | case TYPELONG: 236 | value = long(float(long(min))+norm*float(long(max)-long(min))/*+0.5f*/); 237 | break; 238 | case TYPEBOOL: 239 | if(norm>0.5f) 240 | value = true; 241 | else 242 | value = false; 243 | break; 244 | case TYPEUNKNOWN: 245 | break; 246 | } 247 | Clip(); 248 | this->TellListeners(); 249 | } 250 | void Param::Clip() 251 | { 252 | switch(value.type) 253 | { 254 | case TYPEFLOAT: 255 | if(float(value)float(max)) value = float(max); 257 | break; 258 | case TYPELONG: 259 | if(long(value)long(max)) value = long(max); 261 | break; 262 | case TYPEBOOL: break; 263 | case TYPEUNKNOWN: 264 | break; 265 | } 266 | } 267 | void Param::TellListeners() 268 | { 269 | switch(value.type) 270 | { 271 | case TYPEFLOAT: 272 | if(fun.f) 273 | fun.f->call(float(value)); 274 | break; 275 | case TYPELONG: 276 | if(fun.i) 277 | fun.i->call(long(value)); 278 | break; 279 | case TYPEBOOL: 280 | if(fun.b) 281 | fun.b->call(bool(value)); 282 | break; 283 | case TYPEUNKNOWN: 284 | break; 285 | } 286 | dirty = false; 287 | } 288 | 289 | string Param::toString() 290 | { 291 | std::ostringstream out; 292 | out << Param::GetDisplay(); 293 | return out.str(); 294 | } 295 | void Param::fromString(string s) 296 | { 297 | istringstream in(s); 298 | //string localname; 299 | //in >> localname; 300 | //assert(localname==name); 301 | 302 | switch(value.type) 303 | { 304 | case TYPEFLOAT: 305 | { 306 | float v=0.f; 307 | in >> v; 308 | if(!in.fail()) 309 | value.u.f = v; 310 | break; 311 | } 312 | case TYPELONG: 313 | { 314 | long v=0.f; 315 | in >> v; 316 | if(!in.fail()) 317 | value.u.i = v; 318 | break; 319 | } 320 | case TYPEBOOL: 321 | { 322 | if(s == "true") 323 | value.u.b = true; 324 | else 325 | value.u.b = false; 326 | break; 327 | } 328 | case TYPEUNKNOWN: value.u.i = 0; break; 329 | } 330 | Clip(); 331 | this->TellListeners(); 332 | } 333 | float Param::GetNormalized() 334 | { 335 | return GetNormalized(value); 336 | } 337 | float Param::GetMinNormalized() 338 | { 339 | return GetNormalized(min); 340 | } 341 | float Param::GetDefaultNormalized() 342 | { 343 | return GetNormalized(m_def); 344 | } 345 | float Param::GetMaxNormalized() 346 | { 347 | return GetNormalized(max); 348 | } 349 | 350 | -------------------------------------------------------------------------------- /Livecut.jucer: -------------------------------------------------------------------------------- 1 | 2 | 3 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 27 | 28 | 30 | 32 | 33 | 34 | 35 | 36 | 38 | 40 | 42 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 72 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 92 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 112 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /Source/BBCutter.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Livecut 3 | Copyright 2004 by Remy Muller. 4 | 5 | Livecut can be redistributed and/or modified under the terms of the 6 | GNU General Public License, as published by the Free Software Foundation; 7 | either version 2 of the License, or (at your option) any later version. 8 | 9 | Livecut is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Livecut; if not, visit www.gnu.org/licenses or write to the 16 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 17 | Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #ifndef BBCUTTER_H 21 | #define BBCUTTER_H 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | //------------------------------------------------------------------------------- 31 | struct Math 32 | { 33 | static inline long randominteger(long min, long max) 34 | { 35 | return long(0.5000001+randomfloat(min,max)); 36 | } 37 | 38 | static inline double randomfloat(double min , double max) 39 | { 40 | return min + (max-min)*double(rand())/double(RAND_MAX); 41 | } 42 | 43 | static inline void randomseed(long seed) 44 | { 45 | srand(seed); 46 | } 47 | 48 | template 49 | static inline T wchoose(T *values,double *weights,long size) 50 | { 51 | std::vector cumsum(size); 52 | cumsum[0] = *weights; 53 | for(int i=1;i &cuts, 116 | long &unitsinblock, 117 | long unitsdone, 118 | long totalunits, 119 | long subdiv, 120 | double spu); 121 | 122 | protected: 123 | float minamp,maxamp,minpan,maxpan,mindetune,maxdetune,dutycycle,filldutycycle; 124 | long maxphraselength,minphraselength; 125 | }; 126 | 127 | //------------------------------------------------------------------------------- 128 | class CutProc11 : public CutProc 129 | { 130 | public: 131 | CutProc11(); 132 | 133 | void SetStutterChance(float v); 134 | void SetStutterArea(float v); 135 | void SetMinRepeats(long v); 136 | void SetMaxRepeats(long v); 137 | 138 | void ChooseCuts(std::vector &cuts, 139 | long &unitsinblock, 140 | long unitsdone, 141 | long totalunits, 142 | long subdiv, 143 | double spu); 144 | 145 | private: 146 | long ChooseRepeats(); 147 | long ChooseUnitsInCut(long subdiv); 148 | 149 | private: 150 | float stutterchance,stutterarea; 151 | long minrepeats, maxrepeats; 152 | }; 153 | 154 | //------------------------------------------------------------------------------- 155 | class WarpCutProc : public CutProc 156 | { 157 | public: 158 | WarpCutProc(); 159 | 160 | void SetStraightChance(float chance); 161 | void SetRegularChance(float chance); 162 | void SetRitardChance(float chance); 163 | void SetAccel(float v); 164 | 165 | void ChooseCuts(std::vector &cuts, 166 | long &unitsinblock, 167 | long unitsdone, 168 | long totalunits, 169 | long subdiv, 170 | double spu); 171 | 172 | long ChooseRepeats(float beatsinblock); 173 | long ChooseBlockSize(); 174 | 175 | private: 176 | float straightchance, regularchance, ritardchance, accel; 177 | }; 178 | 179 | //------------------------------------------------------------------------------- 180 | class SQPusherCutProc : public CutProc 181 | { 182 | public: 183 | SQPusherCutProc(); 184 | void SetActivity(float v); 185 | 186 | 187 | long ChoosePhraseLength(); 188 | void ChooseCuts(std::vector &cuts, 189 | long &unitsinblock, 190 | long unitsdone, 191 | long totalunits, 192 | long subdiv, 193 | double spu); 194 | 195 | private: 196 | void sqpusherinit(); 197 | 198 | private: 199 | typedef std::vector< std::vector< std::vector > > CutSequence; 200 | double activity; 201 | bool fill; 202 | long fillnumber,fillpos; 203 | CutSequence cs; 204 | }; 205 | 206 | //------------------------------------------------------------------------------- 207 | /* 208 | the BBCutter has to notify about phrase, blocks and units 209 | the player has to notify about cuts 210 | */ 211 | class BBCutListener 212 | { 213 | public: 214 | BBCutListener() { } 215 | virtual ~BBCutListener() { } 216 | virtual void OnPhrase(long bar, long sd) { } 217 | virtual void OnBlock(long bar, long sd) { } 218 | virtual void OnUnit(long bar, long sd) { } 219 | virtual void OnCut(long cut, long numcuts) { } 220 | }; 221 | 222 | class ListenerManager 223 | { 224 | std::vector listeners; 225 | public: 226 | ListenerManager(); 227 | 228 | void OnPhrase(long bar, long sd); 229 | void OnBlock(long bar, long sd); 230 | void OnUnit(long bar, long sd); 231 | void OnCut(long cut, long numcuts); 232 | 233 | void RegisterListener(BBCutListener *l); 234 | }; 235 | 236 | static float trapeze(long i,long fade, long size) 237 | { 238 | const long fadein = (i=(size-fade)); 240 | const float env = fadein * (i) 241 | + (1-fadein)*(1-fadeout)* (fade); 242 | + fadeout * (fade-i); 243 | return float(env)/float(fade); 244 | } 245 | 246 | static float expenv(float i,float fade,float size) 247 | { 248 | return (1-exp(-5*i/fade)) * (1-exp(5*(i-size)/fade)); 249 | } 250 | 251 | class LivePlayer 252 | { 253 | public: 254 | LivePlayer(); 255 | void SetListenerManager(ListenerManager *lm); 256 | void SetFade(float v); 257 | void OnBlock(std::vector newcuts); 258 | 259 | inline bool tick(float &outL, float &outR,const float inL,const float inR) 260 | { 261 | if(currentcut=cuts[currentcut].size) //end of cut 289 | { 290 | currentcut++; 291 | readindex = 0; 292 | if(currentcut>=cuts.size()) 293 | { 294 | outL = 0.f; 295 | outR = 0.f; 296 | return false; 297 | } 298 | const float amp = cuts[currentcut].amp; 299 | const float pan = cuts[currentcut].pan; 300 | ll = amp * ((pan<0)? 1.f : cos(pan*2*pi_4)); 301 | lr = amp * ((pan<0)? 0.f : sin(pan*2*pi_4)); 302 | rl = amp * ((pan>0)? 0.f : -sin(pan*2*pi_4)); 303 | rr = amp * ((pan>0)? 1.f : cos(pan*2*pi_4)); 304 | 305 | if(fabs(cuts[currentcut].cents) > 1e-10) 306 | { 307 | //resample 308 | const double ratio = pow(2.f,cuts[currentcut].cents/1200.f); 309 | const long sz = std::min( long(pitchedbufferL.size()), 310 | (long(double(inputbufferL.size())/ratio)-1)); 311 | for(int i=0;iOnCut(currentcut,cuts.size()); // allow interpolation... 326 | 327 | return true; 328 | } 329 | } 330 | else 331 | { 332 | outL = 0.f; 333 | outR = 0.f; 334 | } 335 | 336 | return false; 337 | } 338 | 339 | private: 340 | std::valarray inputbufferL; 341 | std::valarray inputbufferR; 342 | std::valarray pitchedbufferL; 343 | std::valarray pitchedbufferR; 344 | std::valarray *L; 345 | std::valarray *R; 346 | long currentcut; 347 | long inputindex,readindex; 348 | float ll,lr,rl,rr; 349 | long fade; 350 | std::vector cuts; 351 | ListenerManager *listenermanager; 352 | }; 353 | 354 | //------------------------------------------------------------------------------------------------ 355 | inline float ms2samples(float t,float sr) 356 | { 357 | return (t*0.001f)*sr; 358 | } 359 | 360 | class BBCutter 361 | { 362 | public: 363 | BBCutter(LivePlayer &player); 364 | ~BBCutter(); 365 | 366 | void RegisterListener(BBCutListener *l); 367 | void SetCutProc(long i); 368 | 369 | void SetBarsInSample(long bars) ; 370 | void SetTempo(double v) ; 371 | void SetSubdiv(long v) ; 372 | void SetStutterChance(float chance); 373 | void SetStutterArea(float area); 374 | void SetMaxRepeats(long repeats); 375 | void SetMinRepeats(long repeats); 376 | void SetStraightChance(float chance); 377 | void SetRegularChance(float chance); 378 | void SetRitardChance(float chance); 379 | void SetAccel(float v); 380 | void SetActivity(float v); 381 | void SetFade(float v); 382 | void SetMinPhraseLength(long v); 383 | void SetMaxPhraseLength(long v); 384 | void SetMinAmp(float v); 385 | void SetMaxAmp(float v); 386 | void SetMinPan(float v); 387 | void SetMaxPan(float v); 388 | void SetDutyCycle(float v); 389 | void SetFillDutyCycle(float v); 390 | void SetMinDetune(float v); 391 | void SetMaxDetune(float v); 392 | void SetNumerator(double v); 393 | void SetDenominator(double v); 394 | 395 | void SetSampleRate(double v); 396 | void SetTimeInfos(double bpm,double num,double den,double srate); 397 | void UpdateRates(); 398 | 399 | inline long GetUnitPosition() { return slicestart+unitsinsideblock;} 400 | inline double UnitsPerBar(double subdiv,double numerator,double denominator) { return subdiv*numerator/denominator;} 401 | inline double BeatsPerSecond(double tempo) { return tempo/60.0;} 402 | inline double SamplesPerBeat(double sr,double tempo) { return sr/BeatsPerSecond(tempo);} 403 | inline double SamplesPerBar() { return SamplesPerBeat(sr,tempo)*beatsPerBar;} 404 | inline double SamplesPerUnit() { return SamplesPerBar()/double(subdiv);} 405 | 406 | void Phrase(long bar, long sd); 407 | void Block(long bar,long sd); 408 | void Unit(long bar, long sd); 409 | void SetPosition(long bar, long sd); 410 | 411 | private: 412 | // params 413 | double tempo, sr; 414 | long subdiv; 415 | double numerator,denominator,beatsPerBar; 416 | 417 | // states 418 | long unitsdone, totalunits, barsnow, 419 | unitsinblock, unitsinsideblock, barsinsample,slicestart; 420 | 421 | CutProc11 cutproc11; 422 | WarpCutProc warpcutproc; 423 | SQPusherCutProc sqpusher; 424 | CutProc *strategy; 425 | std::vector procs; 426 | ListenerManager listenermanager; 427 | LivePlayer &player; 428 | }; 429 | 430 | #endif 431 | 432 | -------------------------------------------------------------------------------- /Source/LivecutProcessor.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Livecut 3 | Copyright 2004 by Remy Muller. 4 | 5 | Livecut can be redistributed and/or modified under the terms of the 6 | GNU General Public License, as published by the Free Software Foundation; 7 | either version 2 of the License, or (at your option) any later version. 8 | 9 | Livecut is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Livecut; if not, visit www.gnu.org/licenses or write to the 16 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 17 | Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #include "LivecutProcessor.h" 21 | #include "LivecutEditor.h" 22 | #include "Functor.h" 23 | 24 | using std::mem_fun; 25 | 26 | LivecutAudioProcessor::LivecutAudioProcessor() 27 | : bbcutter(player) 28 | { 29 | bbcutter.RegisterListener(&crusher); 30 | bbcutter.RegisterListener(&comb); 31 | 32 | AddParameter(strategy 33 | .AddEntry("CutProc11") 34 | .AddEntry("WarpCut") 35 | .AddEntry("SQPusher") 36 | .name("CutProc").tag(0).cc(64) 37 | .functor( newfun(bind1st(mem_fun(&BBCutter::SetCutProc),&bbcutter)) ) 38 | ); 39 | AddParameter(subdiv 40 | .AddEntry(6) 41 | .AddEntry(8) 42 | .AddEntry(12) 43 | .AddEntry(16) 44 | .AddEntry(18) 45 | .AddEntry(24) 46 | .AddEntry(32) 47 | .name("subdiv").def(1L) 48 | .functor( newfun(bind1st(mem_fun(&BBCutter::SetSubdiv),&bbcutter)) ) 49 | ); 50 | AddParameter(seed 51 | .name("seed") 52 | .range(1L,16L).def(1L) 53 | .functor( newfun(std::ptr_fun(&Math::randomseed)) ) 54 | ); 55 | AddParameter(fade 56 | .name("Fade") 57 | .unit("ms") 58 | .range(0.f,100.f).def(0.f) 59 | .functor( newfun(bind1st(mem_fun(&BBCutter::SetFade),&bbcutter)) ) 60 | ); 61 | fade.middle(5.f); 62 | AddParameter(minamp 63 | .name("minamp") 64 | .range(0.f,1.f).def(1.f) 65 | .functor( newfun(bind1st(mem_fun(&BBCutter::SetMinAmp),&bbcutter)) ) 66 | ); 67 | AddParameter(maxamp 68 | .name("maxamp") 69 | .range(0.f,1.f).def(1.f) 70 | .functor( newfun(bind1st(mem_fun(&BBCutter::SetMaxAmp),&bbcutter)) ) 71 | ); 72 | AddParameter(minpan 73 | .name("minpan").range(-1.f,1.f).def(-0.2f) 74 | .functor( newfun(bind1st(mem_fun(&BBCutter::SetMinPan),&bbcutter)) ) 75 | ); 76 | AddParameter(maxpan 77 | .name("maxpan") 78 | .range(-1.f,1.f).def(0.2f) 79 | .functor( newfun(bind1st(mem_fun(&BBCutter::SetMaxPan),&bbcutter)) ) 80 | ); 81 | AddParameter(mindetune 82 | .name("minpitch").unit(" cen") 83 | .range(-2400.f,2400.f).def(0.f) 84 | .functor( newfun(bind1st(mem_fun(&BBCutter::SetMinDetune),&bbcutter)) ) 85 | ); 86 | AddParameter(maxdetune 87 | .name("maxpitch").unit(" cen") 88 | .range(-2400.f,2400.f).def(0.f) 89 | .functor( newfun(bind1st(mem_fun(&BBCutter::SetMaxDetune),&bbcutter)) ) 90 | ); 91 | AddParameter(dutycycle 92 | .name("duty") 93 | .range(0.f,1.f).def(1.f) 94 | .functor( newfun(bind1st(mem_fun(&BBCutter::SetDutyCycle),&bbcutter)) ) 95 | ); 96 | AddParameter(filldutycycle 97 | .name("fillduty") 98 | .range(0.f,1.f).def(1.f) 99 | .functor( newfun(bind1st(mem_fun(&BBCutter::SetFillDutyCycle),&bbcutter)) ) 100 | ); 101 | AddParameter(maxphraselength 102 | .name("maxphrs").unit(" bar") 103 | .range(1L,8L).def(4L) 104 | .functor( newfun(bind1st(mem_fun(&BBCutter::SetMaxPhraseLength),&bbcutter)) ) 105 | ); 106 | AddParameter(minphraselength 107 | .name("minphrs").unit(" bar") 108 | .range(1L,8L).def(1L) 109 | .functor( newfun(bind1st(mem_fun(&BBCutter::SetMinPhraseLength),&bbcutter)) ) 110 | ); 111 | AddParameter(maxrepeats 112 | .name("maxrep").unit(" rep") 113 | .range(0L,4L).def(1L) 114 | .functor( newfun(bind1st(mem_fun(&BBCutter::SetMaxRepeats),&bbcutter)) ) 115 | ); 116 | AddParameter(minrepeats 117 | .name("minrep").unit(" rep") 118 | .range(0L,4L).def(0L) 119 | .functor( newfun(bind1st(mem_fun(&BBCutter::SetMinRepeats),&bbcutter)) ) 120 | ); 121 | AddParameter(stutterchance 122 | .name("stutter") 123 | .range(0.f,1.f).def(0.8f) 124 | .functor( newfun(bind1st(mem_fun(&BBCutter::SetStutterChance),&bbcutter)) ) 125 | ); 126 | AddParameter(stutterarea 127 | .name("area") 128 | .range(0.f,1.f).def(0.5f) 129 | .functor( newfun(bind1st(mem_fun(&BBCutter::SetStutterArea),&bbcutter)) ) 130 | ); 131 | AddParameter(straightchance 132 | .name("straight") 133 | .range(0.f,1.f).def(0.3f) 134 | .functor( newfun(bind1st(mem_fun(&BBCutter::SetStraightChance),&bbcutter)) ) 135 | ); 136 | AddParameter(regularchance 137 | .name("regular") 138 | .range(0.f,1.f).def(0.5f) 139 | .functor( newfun(bind1st(mem_fun(&BBCutter::SetRegularChance),&bbcutter)) ) 140 | ); 141 | AddParameter(ritardchance 142 | .name("ritard") 143 | .range(0.f,1.f).def(0.5f) 144 | .functor( newfun(bind1st(mem_fun(&BBCutter::SetRitardChance),&bbcutter)) ) 145 | ); 146 | AddParameter(accel 147 | .name("speed") 148 | .range(0.5f,0.999f).def(0.9f) 149 | .functor( newfun(bind1st(mem_fun(&BBCutter::SetAccel),&bbcutter)) ) 150 | ); 151 | AddParameter(activity 152 | .name("activity") 153 | .range(0.f,1.f).def(0.5f) 154 | .functor( newfun(bind1st(mem_fun(&BBCutter::SetActivity),&bbcutter)) ) 155 | ); 156 | AddParameter(crusherswitch 157 | .name("crusher").def(false) 158 | .functor( newfun(bind1st(mem_fun(&BitCrusher::SetOn),&crusher)) ) 159 | ); 160 | AddParameter(minbits 161 | .name("minbits").unit("bit") 162 | .range(1.f,32.f).def(32.f) 163 | .functor( newfun(bind1st(mem_fun(&BitCrusher::SetMinBits),&crusher)) ) 164 | ); 165 | AddParameter(maxbits 166 | .name("maxbits").unit("bit") 167 | .range(1.f,32.f).def(32.f) 168 | .functor( newfun(bind1st(mem_fun(&BitCrusher::SetMaxBits),&crusher)) ) 169 | ); 170 | float sr = 44100; 171 | AddParameter(minfreq 172 | .name("minfreq").unit("Hz") 173 | .range(sr/100.f,sr).def(sr) 174 | .functor( newfun(bind1st(mem_fun(&BitCrusher::SetMinFreq),&crusher)) ) 175 | ); 176 | minfreq.middle(sr/10.f); 177 | AddParameter(maxfreq 178 | .name("maxfreq").unit("Hz") 179 | .range(sr/100.f,sr).def(sr) 180 | .functor( newfun(bind1st(mem_fun(&BitCrusher::SetMaxFreq),&crusher)) ) 181 | ); 182 | maxfreq.middle(sr/10.f); 183 | AddParameter(combswitch 184 | .name("comb").def(false) 185 | .functor( newfun(bind1st(mem_fun(&Comb::SetOn),&comb)) ) 186 | ); 187 | AddParameter(combtype 188 | .AddEntry("FeedFwd") 189 | .AddEntry("FeedBack") 190 | .name("type") 191 | .functor( newfun(bind1st(mem_fun(&Comb::SetType),&comb)) ) 192 | ); 193 | AddParameter(combfeedback 194 | .name("feedback") 195 | .range(0.f,0.9).def(0.5f) 196 | .functor( newfun(bind1st(mem_fun(&Comb::SetFeedBack),&comb)) ) 197 | ); 198 | AddParameter(combmindelay 199 | .name("mindelay").unit("ms") 200 | .range(1.f,50.f).def(10.f) 201 | .functor( newfun(bind1st(mem_fun(&Comb::SetMinDelay),&comb)) ) 202 | ); 203 | AddParameter(combmaxdelay 204 | .name("maxdelay").unit("ms") 205 | .range(1.f,50.f).def(10.f) 206 | .functor( newfun(bind1st(mem_fun(&Comb::SetMaxDelay),&comb)) ) 207 | ); 208 | 209 | for(ParamMap::iterator it = params.begin(); it != params.end(); ++it) 210 | it->second->TellListeners(); 211 | } 212 | 213 | LivecutAudioProcessor::~LivecutAudioProcessor() 214 | { 215 | } 216 | 217 | void LivecutAudioProcessor::AddParameter(Param ¶m) 218 | { 219 | params.add(param); 220 | } 221 | 222 | const String LivecutAudioProcessor::getName() const 223 | { 224 | return JucePlugin_Name; 225 | } 226 | 227 | int LivecutAudioProcessor::getNumParameters() 228 | { 229 | return params.size(); 230 | } 231 | 232 | float LivecutAudioProcessor::getParameter (int index) 233 | { 234 | if(params.count(index)) 235 | return params[index]->GetNormalized(); 236 | else 237 | return 0.f; 238 | } 239 | 240 | void LivecutAudioProcessor::setParameter (int index, float newValue) 241 | { 242 | if(!params.count(index)) 243 | return; 244 | 245 | Param *p = params[index]; 246 | p->SetFromNormalized(newValue); 247 | } 248 | 249 | const String LivecutAudioProcessor::getParameterName (int index) 250 | { 251 | if(params.count(index)) 252 | return String(params[index]->GetName().c_str()); 253 | 254 | return String::empty; 255 | } 256 | 257 | const String LivecutAudioProcessor::getParameterText (int index) 258 | { 259 | if(params.count(index)) 260 | return String(params[index]->GetDisplay().c_str()); 261 | 262 | return String::empty; 263 | } 264 | 265 | const String LivecutAudioProcessor::getInputChannelName (int channelIndex) const 266 | { 267 | return String (channelIndex + 1); 268 | } 269 | 270 | const String LivecutAudioProcessor::getOutputChannelName (int channelIndex) const 271 | { 272 | return String (channelIndex + 1); 273 | } 274 | 275 | bool LivecutAudioProcessor::isInputChannelStereoPair (int index) const 276 | { 277 | return true; 278 | } 279 | 280 | bool LivecutAudioProcessor::isOutputChannelStereoPair (int index) const 281 | { 282 | return true; 283 | } 284 | 285 | bool LivecutAudioProcessor::acceptsMidi() const 286 | { 287 | #if JucePlugin_WantsMidiInput 288 | return true; 289 | #else 290 | return false; 291 | #endif 292 | } 293 | 294 | bool LivecutAudioProcessor::producesMidi() const 295 | { 296 | #if JucePlugin_ProducesMidiOutput 297 | return true; 298 | #else 299 | return false; 300 | #endif 301 | } 302 | 303 | bool LivecutAudioProcessor::silenceInProducesSilenceOut() const 304 | { 305 | return false; 306 | } 307 | 308 | int LivecutAudioProcessor::getNumPrograms() 309 | { 310 | return 0; 311 | } 312 | 313 | int LivecutAudioProcessor::getCurrentProgram() 314 | { 315 | return 0; 316 | } 317 | 318 | void LivecutAudioProcessor::setCurrentProgram (int index) 319 | { 320 | } 321 | 322 | const String LivecutAudioProcessor::getProgramName (int index) 323 | { 324 | return String::empty; 325 | } 326 | 327 | void LivecutAudioProcessor::changeProgramName (int index, const String& newName) 328 | { 329 | } 330 | 331 | void LivecutAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock) 332 | { 333 | // Use this method as the place to do any pre-playback 334 | // initialisation that you need.. 335 | 336 | crusher.SetSampleRate(sampleRate); 337 | comb.SetSampleRate(sampleRate); 338 | minfreq.range(100.f, sampleRate); 339 | maxfreq.range(100.f, sampleRate); 340 | } 341 | 342 | void LivecutAudioProcessor::releaseResources() 343 | { 344 | // When playback stops, you can use this as an opportunity to free up any 345 | // spare memory, etc. 346 | } 347 | 348 | void LivecutAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages) 349 | { 350 | // This is the place where you'd normally do the guts of your plugin's 351 | // audio processing... 352 | Process(buffer.getArrayOfChannels(), 353 | buffer.getArrayOfChannels(), 354 | buffer.getNumSamples()); 355 | 356 | // In case we have more outputs than inputs, we'll clear any output 357 | // channels that didn't contain input data, (because these aren't 358 | // guaranteed to be empty - they may contain garbage). 359 | for (int i = getNumInputChannels(); i < getNumOutputChannels(); ++i) 360 | { 361 | buffer.clear (i, 0, buffer.getNumSamples()); 362 | } 363 | } 364 | 365 | void LivecutAudioProcessor::Process(float **inputs,float **outputs, const long size) 366 | { 367 | float *outL = outputs[0]; 368 | float *outR = outputs[1]; 369 | float *inL = inputs[0]; 370 | float *inR = inputs[1]; 371 | long div = subdiv.GetIntValue(); 372 | 373 | AudioPlayHead* playHead = getPlayHead(); 374 | if(!playHead) return; 375 | 376 | AudioPlayHead::CurrentPositionInfo info; 377 | playHead->getCurrentPosition(info); 378 | 379 | double samplePos = info.timeInSamples; // current location 380 | double sampleRate = getSampleRate(); 381 | double ppqPos = info.ppqPosition; // 1 ppq 382 | double tempo = info.bpm; // in bpm 383 | double numerator = double(info.timeSigNumerator); // time signature 384 | double denominator = double(info.timeSigDenominator); 385 | double ppqduration = ((double)size/sampleRate) * (tempo/60.0); //duration of the block 386 | double divPerSample = (double(div)/double(numerator))*ppqduration*(denominator/4.0)/double(size); 387 | double position = (double(div)/double(numerator)) * ppqPos * (denominator/4.0); 388 | double ref = 0.0; 389 | long oldpositionInMeasure = long(floor(fmod(position-ref, div))); 390 | long oldmeasure = long(floor((position-ref)/div)); 391 | 392 | //double semiquaverPerSample = (double(16)/double(numerator))*ppqduration*(denominator/4.0)/double(sampleframes); 393 | //double semiquaverposition = (double(16)/double(numerator))*ppqPos * (denominator/4.0); 394 | //long oldsemiquaverpositionInMeasure = long(floor(fmod(semiquaverposition-ref,16))); 395 | 396 | bbcutter.SetTimeInfos(tempo, numerator, denominator, sampleRate); 397 | 398 | bool transportChanged = false; // predict from last bar 399 | if(transportChanged && info.isPlaying) 400 | { 401 | bbcutter.SetPosition(oldmeasure, oldpositionInMeasure); 402 | } 403 | 404 | for(int i=0; iaddKnob(minphraselength.GetTag(), 2, 0); 455 | pEditor->addKnob(maxphraselength.GetTag(), 2, 2); 456 | pEditor->addKnob(subdiv.GetTag(), 2, 4); 457 | pEditor->addKnob(seed.GetTag(), 2, 6); 458 | 459 | pEditor->addKnob(stutterchance.GetTag(), 7, 0); 460 | pEditor->addKnob(stutterarea.GetTag(), 7, 2); 461 | pEditor->addKnob(minrepeats.GetTag(), 7, 4); 462 | pEditor->addKnob(maxrepeats.GetTag(), 7, 6); 463 | 464 | pEditor->addKnob(straightchance.GetTag(), 7, 8); 465 | pEditor->addKnob(regularchance.GetTag(), 7, 10); 466 | pEditor->addKnob(ritardchance.GetTag(), 7, 12); 467 | pEditor->addKnob(accel.GetTag(), 7, 14); 468 | 469 | pEditor->addKnob(activity.GetTag(), 7, 16); 470 | 471 | pEditor->addKnob(minamp.GetTag(), 12, 0); 472 | pEditor->addKnob(maxamp.GetTag(), 12, 2); 473 | pEditor->addKnob(minpan.GetTag(), 12, 4); 474 | pEditor->addKnob(maxpan.GetTag(), 12, 6); 475 | 476 | pEditor->addKnob(mindetune.GetTag(), 2, 8); 477 | pEditor->addKnob(maxdetune.GetTag(), 2, 10); 478 | 479 | pEditor->addKnob(dutycycle.GetTag(), 2, 16); 480 | pEditor->addKnob(filldutycycle.GetTag(), 2, 18); 481 | pEditor->addKnob(fade.GetTag(), 2, 20); 482 | 483 | pEditor->addKnob(minbits.GetTag(), 12, 8); 484 | pEditor->addKnob(maxbits.GetTag(), 12, 10); 485 | pEditor->addKnob(minfreq.GetTag(), 12, 12); 486 | pEditor->addKnob(maxfreq.GetTag(), 12, 14); 487 | pEditor->addKnob(crusherswitch.GetTag(), 16, 2); 488 | 489 | 490 | return pEditor; 491 | } 492 | 493 | 494 | void LivecutAudioProcessor::getStateInformation (MemoryBlock& destData) 495 | { 496 | // You should use this method to store your parameters in the memory block. 497 | // You could do that either as raw data, or use the XML or ValueTree classes 498 | // as intermediaries to make it easy to save and load complex data. 499 | } 500 | 501 | void LivecutAudioProcessor::setStateInformation (const void* data, int sizeInBytes) 502 | { 503 | // You should use this method to restore your parameters from this memory block, 504 | // whose contents will have been created by the getStateInformation() call. 505 | } 506 | 507 | 508 | // This creates new instances of the plugin.. 509 | AudioProcessor* JUCE_CALLTYPE createPluginFilter() 510 | { 511 | return new LivecutAudioProcessor(); 512 | } 513 | -------------------------------------------------------------------------------- /Source/Params.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Livecut 3 | Copyright 2004 by Remy Muller. 4 | 5 | Livecut can be redistributed and/or modified under the terms of the 6 | GNU General Public License, as published by the Free Software Foundation; 7 | either version 2 of the License, or (at your option) any later version. 8 | 9 | Livecut is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Livecut; if not, visit www.gnu.org/licenses or write to the 16 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 17 | Boston, MA 02111-1307 USA 18 | */ 19 | 20 | /** 21 | DICLAIMER: 22 | this is a badly designed parameter system. 23 | It is only left here for legacy purpose 24 | */ 25 | 26 | #if ! defined (Params_HEADER_INCLUDED) 27 | #define Params_HEADER_INCLUDED 28 | 29 | #include "Functor.h" 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | using std::string; 38 | using std::unary_function; 39 | 40 | enum ControllerType 41 | { 42 | eHSlider, 43 | eVSlider, 44 | eKnob, 45 | eSwitch, 46 | eKick, 47 | eEnum, 48 | 49 | eNumControls 50 | }; 51 | 52 | enum Type 53 | { 54 | TYPELONG, 55 | TYPEFLOAT, 56 | TYPEBOOL, 57 | TYPEUNKNOWN 58 | }; 59 | 60 | struct Atom 61 | { 62 | union 63 | { 64 | float f; 65 | long i; 66 | bool b; 67 | } u; 68 | 69 | Type type; 70 | 71 | 72 | Atom(double v) {u.f=float(v); type = TYPEFLOAT;} 73 | Atom(float v) {u.f=v; type = TYPEFLOAT;} 74 | Atom(int v) {u.i=v; type = TYPELONG;} 75 | Atom(bool v) {u.b=v; type = TYPEBOOL;} 76 | Atom() {u.i = 0; type = TYPEUNKNOWN;} 77 | inline float AsFloat() 78 | { 79 | switch(type) 80 | { 81 | case TYPEFLOAT: return float(u.f); 82 | case TYPELONG: return float(u.i); 83 | case TYPEBOOL: return float(u.b); 84 | case TYPEUNKNOWN: 85 | default: 86 | return float(0.f); 87 | } 88 | } 89 | inline void FromFloat(float v) 90 | { 91 | switch(type) 92 | { 93 | case TYPEFLOAT: u.f = float(v); break; 94 | case TYPELONG: u.i = long(v); break; 95 | case TYPEBOOL: u.b = (v>0.5f)?true:false; break; 96 | case TYPEUNKNOWN: break; 97 | default:break; 98 | } 99 | } 100 | inline float GetFloat(){return u.f;} 101 | inline long GetLong() {return u.i;} 102 | inline bool GetBool() {return u.b;} 103 | inline Type GetType(){return type;} 104 | inline operator float() {return u.f;} 105 | inline operator bool() {return u.b;} 106 | inline operator long() {return u.i;} 107 | inline operator int() {return u.i;} 108 | inline operator Type() {return type;} 109 | inline Atom& operator=(double v){u.f = float(v); type = TYPEFLOAT; return *this;} 110 | inline Atom& operator=(float v) {u.f = v; type = TYPEFLOAT; return *this;} 111 | inline Atom& operator=(long v) {u.i = v; type = TYPELONG; return *this;} 112 | inline Atom& operator=(int v) {u.i = long(v); type = TYPELONG; return *this;} 113 | inline Atom& operator=(bool v) {u.b = v; type = TYPEBOOL; return *this;} 114 | /* 115 | friend inline double operator=(double &v, Atom& a); 116 | friend inline float operator=(float &v, Atom& a); 117 | friend inline long operator=(long &v, Atom& a); 118 | friend inline int operator=(int &v, Atom& a); 119 | friend inline bool operator=(bool &v, Atom& a); 120 | */ 121 | }; 122 | 123 | /* 124 | inline double operator=(double &v, Atom& a){v = double(a);} 125 | inline float operator=(float &v, Atom& a){v = float(a);} 126 | inline long operator=(long &v, Atom& a){v = long(a);} 127 | inline int operator=(int &v, Atom& a){v = int(a);} 128 | inline bool operator=(bool &v, Atom& a){v = bool(a);} 129 | */ 130 | template 131 | inline void SetAtom(Atom& a, T v) {a = v;} 132 | 133 | class IParam 134 | { 135 | public: 136 | virtual ~IParam() {} 137 | 138 | virtual string GetDisplay()=0; 139 | virtual string GetName()=0; 140 | virtual string GetUnit()=0; 141 | virtual Atom GetValue()=0; 142 | virtual void SetValue(Atom &a)=0; 143 | virtual float GetFloatValue()=0; 144 | virtual long GetIntValue()=0; 145 | virtual bool GetBoolValue()=0; 146 | virtual float GetNormalized()=0; 147 | virtual long GetTag()=0; 148 | virtual char GetCC()=0; 149 | virtual void SetFromNormalized(float norm)=0; 150 | virtual void SetDirty(bool dirty_)=0; 151 | virtual bool IsDirty()=0; 152 | virtual string toString()=0; 153 | virtual void fromString(string s)=0; 154 | }; 155 | 156 | 157 | class Param; 158 | 159 | typedef std::map ParamList; 160 | typedef std::map ParamNameMap; 161 | typedef std::map CcMap; 162 | 163 | class Param : public IParam 164 | { 165 | virtual float GetNormalized(Atom v); 166 | public: 167 | Param() 168 | : m_name("") 169 | , m_unit("") 170 | , m_description("") 171 | , m_tag(0) 172 | , m_cc(-1) 173 | , m_style(0) 174 | , dirty(false) 175 | { 176 | fun.f = NULL; 177 | } 178 | 179 | Param (ParamList &list,float min,float def,float max,string name,string unit,long tag_, char cc_,Fun *f=0) 180 | { 181 | fun.f=f; 182 | init(list,min,def,max,name,unit,tag_,cc_); 183 | } 184 | 185 | Param (ParamList &list,long min,long def,long max,string name,string unit,long tag_, char cc_,Fun *f=0) 186 | { 187 | fun.i=f; 188 | init(list,min,def,max,name,unit,tag_,cc_); 189 | } 190 | 191 | Param (ParamList &list,bool def, string name,string unit,long tag_, char cc_,Fun *f=0) 192 | { 193 | fun.b=f; 194 | init(list,def,name,unit,tag_,cc_); 195 | } 196 | 197 | virtual ~Param () 198 | { 199 | if(fun.b != NULL) 200 | { 201 | switch (value.GetType()) 202 | { 203 | case TYPEBOOL: 204 | delete fun.b; 205 | break; 206 | case TYPELONG: 207 | delete fun.i; 208 | break; 209 | case TYPEFLOAT: 210 | delete fun.f; 211 | break; 212 | default: 213 | break; 214 | } 215 | } 216 | } 217 | 218 | virtual void init (ParamList &list,float min,float def,float max,string name,string unit,long tag_, char cc_,Fun *f=0); 219 | 220 | virtual void init (ParamList &list,long min,long def,long max,string name,string unit,long tag_, char cc_,Fun *f=0); 221 | 222 | virtual void init (ParamList &list,bool def, string name,string unit,long tag_, char cc_,Fun *f=0); 223 | 224 | virtual Param& name(string text); 225 | virtual Param& unit(string text); 226 | virtual Param& range(float min, float max); 227 | virtual Param& range(long min, long max); 228 | virtual Param& description(string text) {m_description=text; return *this;} 229 | virtual Param& style(long v){m_style = v; return *this;} 230 | virtual Param& def(float val); 231 | virtual Param& def(long val); 232 | virtual Param& def(bool val); 233 | virtual Param& tag(long v); 234 | virtual Param& cc(long v); 235 | virtual Param& functor(Fun *f); 236 | virtual Param& functor(Fun *f); 237 | virtual Param& functor(Fun *f); 238 | 239 | virtual string description() {return m_description;} 240 | virtual long style(){return m_style;} 241 | 242 | virtual string GetDisplay(); 243 | virtual void FromDisplay(string s); 244 | virtual string GetName() {return m_name;} 245 | virtual string GetUnit() {return m_unit;} 246 | virtual void SetValue(Atom &a) {value = a; Clip(); TellListeners();} 247 | virtual void SetValueFromFloat(float v) {value.FromFloat(v); Clip(); TellListeners();} 248 | virtual Atom GetValue() {return value;} 249 | virtual Atom GetMin() {return min;} 250 | virtual Atom GetDefault() {return m_def;} 251 | virtual Atom GetMax() {return max;} 252 | virtual float GetNormalized(); 253 | virtual float GetMinNormalized(); 254 | virtual float GetDefaultNormalized(); 255 | virtual float GetMaxNormalized(); 256 | virtual long GetTag() {return m_tag;} 257 | virtual char GetCC() {return m_cc;} 258 | virtual Type GetType(){return value.GetType();} 259 | virtual void SetFromNormalized(float norm); 260 | virtual void SetDirty(bool dirty_) {dirty = dirty_;} 261 | virtual bool IsDirty(){return dirty;} 262 | virtual string toString(); 263 | virtual void fromString(string s); 264 | virtual float GetFloatValue() {return float(value);} 265 | virtual long GetIntValue() {return long(value);} 266 | virtual bool GetBoolValue() {return bool(value);} 267 | virtual void SetFunctor(Fun *f){fun.f = f;} 268 | virtual void SetFunctor(Fun *f){fun.i = f;} 269 | virtual void SetFunctor(Fun *f){fun.b = f;} 270 | virtual void Clip(); 271 | virtual void TellListeners(); 272 | 273 | protected: 274 | Atom value; 275 | Atom min; 276 | Atom m_def; 277 | Atom max; 278 | string m_name; 279 | string m_unit; 280 | string m_description; 281 | long m_style; 282 | long m_tag; 283 | char m_cc; 284 | bool dirty; 285 | union { 286 | Fun *f; 287 | Fun *i; 288 | Fun *b; 289 | } fun; 290 | }; // class Param 291 | 292 | class ParamMap : public std::map 293 | { 294 | public: 295 | ParamMap& add(Param ¶m) 296 | { 297 | if( count(param.GetTag()) ) 298 | { 299 | long newtag = rbegin()->second->GetTag() + 1; 300 | param.tag(newtag); 301 | } 302 | if(param.GetCC()<0) 303 | { 304 | long newcc = 0; 305 | if(!empty()) 306 | newcc = rbegin()->second->GetCC() + 1; 307 | param.cc(newcc); 308 | } 309 | (*this)[param.GetTag()] = ¶m; 310 | 311 | return *this; 312 | } 313 | }; 314 | 315 | 316 | class Freq : public Param 317 | { 318 | public: 319 | Freq (ParamList &list,float min,float def,float max,string name,long tag_, char cc_,Fun *f=0): Param(list,min,def,max,name,"Hz",tag_,cc_,f) {} 320 | virtual float GetNormalized() {return (log10(float(value))-log10(float(min)))/(log10(float(max))-log10(float(min)));} 321 | virtual void SetFromNormalized(float norm) {value = pow(10.0f,log10(float(min))+norm*(log10(float(max))-log10(float(min))));} 322 | }; // class Freq 323 | 324 | class OnOffParam : public Param 325 | { 326 | public: 327 | OnOffParam(ParamList &list,bool def,string name,long tag_,char cc_,Fun *f=0): Param(list,def,name,"",tag_,cc_,f) {} 328 | 329 | virtual string GetDisplay() 330 | { 331 | if(bool(value) == true) 332 | return string("On"); 333 | else 334 | return string("Off"); 335 | } 336 | }; 337 | 338 | class EnumParam : public Param 339 | { 340 | std::vector names; 341 | public: 342 | EnumParam() 343 | { 344 | min = 0L; 345 | max = 0L; 346 | value = 0L; 347 | m_def = 0L; 348 | m_style = eEnum; 349 | } 350 | EnumParam(ParamList &list,string name,long tag_,char cc_,Fun *f=0){init(list,name,tag_,cc_,f);} 351 | void init(ParamList &list,string name,long tag_,char cc_,Fun *f=0){Param::init(list,0L,0L,0L,name,"",tag_,cc_,f);} 352 | virtual string GetDisplay() {return names.at(long(value));} 353 | virtual void FromDisplay(string s) 354 | { 355 | fromString(s); 356 | } 357 | virtual void fromString(string s) 358 | { 359 | //find the index of the value in the array 360 | long index=0; 361 | while(index= names.size()) 370 | index = 0; 371 | 372 | value.u.i = index; 373 | Clip(); 374 | this->TellListeners(); 375 | } 376 | virtual string toString () 377 | { 378 | return GetDisplay(); 379 | } 380 | 381 | void AddNames(std::vector &v) 382 | { 383 | for(unsigned int i=0;i values; 398 | public: 399 | IntSetParam() 400 | { 401 | min = 0L; 402 | max = 0L; 403 | m_def = 0L; 404 | value = 0L; 405 | } 406 | IntSetParam(ParamList &list,std::vector vals,string name,string unit,long tag_,char cc_,Fun *f=0) 407 | { 408 | init(list,vals,0,name,unit,tag_,cc_,f); 409 | } 410 | void init(ParamList &list,std::vector vals,long def,string name,string unit,long tag_,char cc_,Fun *f=0) 411 | { 412 | Param::init(list,0L,def,long(vals.size()-1),name,unit,tag_,cc_,f);values = vals; 413 | } 414 | virtual void FromDisplay(string s) 415 | { 416 | fromString(s); 417 | } 418 | virtual void fromString(string s) 419 | { 420 | std::istringstream in(s); 421 | long v=0.f; 422 | in >> v; 423 | 424 | if(!in.fail()) 425 | { 426 | //find the index of the value in the array 427 | long index=0; 428 | while(index= values.size()) 435 | index = 0; 436 | value.u.i = index; 437 | Clip(); 438 | this->TellListeners(); 439 | } 440 | } 441 | IntSetParam& AddEntry(long v) 442 | { 443 | values.push_back(v); 444 | max = long(values.size()-1); 445 | return *this; 446 | } 447 | void AddValues(std::vector &v) 448 | { 449 | values = v; 450 | max = long(values.size()-1); 451 | } 452 | virtual void SetFromNormalized(float norm) 453 | { 454 | value = long(float(long(min))+norm*float(long(max)-long(min))/*+0.5f*/); 455 | Clip(); 456 | TellListeners(); 457 | } 458 | virtual void TellListeners() 459 | { 460 | long v = values[long(value)]; 461 | fun.i->call(v); 462 | } 463 | virtual void SetValue(Atom &a) 464 | { 465 | value = a; 466 | Clip(); 467 | TellListeners(); 468 | } 469 | virtual string GetDisplay () 470 | { 471 | std::ostringstream out; 472 | // out.precision(6); 473 | // out << std::showpoint; 474 | // out.width(10); 475 | out << values[long(value)]; 476 | return out.str(); 477 | } 478 | virtual string toString () 479 | { 480 | return GetDisplay(); 481 | } 482 | virtual long GetIntValue() {return values[long(value)];} 483 | }; 484 | 485 | class FloatSetParam : public Param 486 | { 487 | std::vector values; 488 | public: 489 | FloatSetParam() 490 | { 491 | min = 0L; 492 | max = 0L; 493 | m_def = 0L; 494 | value = 0L; 495 | } 496 | FloatSetParam(ParamList &list,std::vector vals,string name,string unit,long tag_,char cc_,Fun *f=0) 497 | { 498 | init(list,vals,0,name,unit,tag_,cc_,f); 499 | } 500 | void init(ParamList &list,std::vector vals,long def,string name,string unit,long tag_,char cc_,Fun *f=0) 501 | { 502 | Param::init(list,0L,def,long(vals.size()-1),name,unit,tag_,cc_,f); values = vals; 503 | } 504 | virtual void FromDisplay(string s) 505 | { 506 | fromString(s); 507 | } 508 | virtual void fromString(string s) 509 | { 510 | std::istringstream in(s); 511 | float v=0.f; 512 | in >> v; 513 | 514 | if(!in.fail()) 515 | { 516 | //find the index of the value in the array 517 | long index=0; 518 | while(index= values.size()) 525 | index = 0; 526 | value.u.i = index; 527 | Clip(); 528 | this->TellListeners(); 529 | } 530 | } 531 | FloatSetParam& AddEntry(float v) 532 | { 533 | values.push_back(v); 534 | max = long(values.size()-1); 535 | return *this; 536 | } 537 | void AddValues(std::vector &v) 538 | { 539 | values = v; 540 | max = long(values.size()-1); 541 | } 542 | virtual void TellListeners() 543 | { 544 | if(fun.f) 545 | fun.f->call(values[long(value)]); 546 | } 547 | virtual void SetValue(Atom &a) 548 | { 549 | value = a; 550 | Clip(); 551 | TellListeners(); 552 | } 553 | virtual string GetDisplay () 554 | { 555 | std::ostringstream out; 556 | out << values[long(value)]; 557 | return out.str(); 558 | } 559 | virtual string toString () 560 | { 561 | return GetDisplay(); 562 | } 563 | virtual float GetFloatValue() {return values[long(value)];} 564 | }; 565 | 566 | class AutoParam : public Param 567 | { 568 | public: 569 | /* 570 | void init (ParamList &list,float min,float def,float max,string name,string unit,long tag_, char cc_,Fun *f=0) 571 | {Param::init(list,min,def,max,name,unit,tag_,cc_,f)} 572 | void init (ParamList &list,long min,long def,long max,string name,string unit,long tag_, char cc_,Fun *f=0) 573 | {Param::init(list,min,def,max,name,unit,tag_,cc_); fi = f;} 574 | void init (ParamList &list,bool def, string name,string unit,long tag_, char cc_,Fun *f=0) 575 | {Param::init(list,def,name,unit,tag_,cc_); fb = f;} 576 | */ 577 | }; 578 | 579 | //---------------------------------------------------------------------------------------------------------------- 580 | // mapping 581 | //---------------------------------------------------------------------------------------------------------------- 582 | 583 | class LinearMapping 584 | { 585 | float y0,y1; 586 | public: 587 | LinearMapping(){} 588 | LinearMapping(float min,float max) 589 | :y0(min),y1(max) 590 | { 591 | assert(y1>0.f); 592 | } 593 | float FromNormalized(float x){return y0+(y1-y0)*x;} 594 | float ToNormalized(float y) {return (y-y0)/(y1-y0);} 595 | }; 596 | 597 | class ExponentialMapping 598 | { 599 | float y0,a,b; 600 | public: 601 | ExponentialMapping(){} 602 | ExponentialMapping(float min,float mid,float max) 603 | { 604 | init(min,mid,max); 605 | } 606 | void init(float min,float mid,float max) 607 | { 608 | assert(min 0.f); 613 | assert(b > 0.f); 614 | } 615 | float FromNormalized(float x) 616 | { 617 | return y0 + a * exp( b*x ); 618 | } 619 | float ToNormalized(float y) 620 | { 621 | return log( (y-y0) / a ) / b; 622 | } 623 | }; 624 | 625 | class PowerMapping 626 | { 627 | float y0,y1,a; 628 | public: 629 | PowerMapping(){} 630 | PowerMapping(float min_,float mid_,float max_) 631 | { 632 | init(min_,mid_,max_); 633 | } 634 | void init(float min_,float mid_,float max_) 635 | { 636 | assert(min_ *f=0) 659 | : Param(list,min,def,max,name,"Hz",tag_,cc_,f) 660 | ,mapping(min,mid,max) 661 | {} 662 | void init (ParamList &list,float min,float def,float mid,float max,string name,string unit,long tag_, char cc_,Fun *f=0) 663 | { 664 | Param::init(list,min,def,max,name,unit,tag_,cc_,f); 665 | mapping.init(min,mid,max); 666 | } 667 | virtual float GetNormalized() 668 | { 669 | return mapping.ToNormalized(float(value)); 670 | } 671 | virtual void SetFromNormalized(float norm) 672 | { 673 | value = mapping.FromNormalized(norm); 674 | Clip(); 675 | TellListeners(); 676 | } 677 | }; 678 | 679 | class PowerParam : public Param 680 | { 681 | PowerMapping mapping; 682 | public: 683 | PowerParam (){} 684 | PowerParam (ParamList &list,float min,float def,float mid,float max,string name,long tag_, char cc_,Fun *f=0) 685 | : Param(list,min,def,max,name,"Hz",tag_,cc_,f) 686 | ,mapping(min,mid,max) 687 | {} 688 | virtual void init (ParamList &list,float min,float def,float mid,float max,string name,string unit,long tag_, char cc_,Fun *f=0) 689 | { 690 | Param::init(list,min,def,max,name,unit,tag_,cc_,f); 691 | mapping.init(min,mid,max); 692 | } 693 | void middle(float mid) 694 | { 695 | mapping.init(float(min),mid,float(max)); 696 | } 697 | virtual float GetNormalized() 698 | { 699 | return mapping.ToNormalized(float(value)); 700 | } 701 | virtual void SetFromNormalized(float norm) 702 | { 703 | value = mapping.FromNormalized(norm); 704 | Clip(); 705 | TellListeners(); 706 | } 707 | }; 708 | 709 | 710 | #endif 711 | 712 | -------------------------------------------------------------------------------- /Source/LivecutLookAndFeel.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Livecut 3 | Copyright 2003 by Remy Muller. 4 | 5 | Livecut can be redistributed and/or modified under the terms of the 6 | GNU General Public License, as published by the Free Software Foundation; 7 | either version 2 of the License, or (at your option) any later version. 8 | 9 | Livecut is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Livecut; if not, visit www.gnu.org/licenses or write to the 16 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 17 | Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #include "LivecutLookAndFeel.h" 21 | 22 | static Colour createBaseColour (const Colour& buttonColour, 23 | const bool hasKeyboardFocus, 24 | const bool isMouseOverButton, 25 | const bool isButtonDown) 26 | { 27 | const float sat = hasKeyboardFocus ? 1.3f : 0.9f; 28 | const Colour baseColour (buttonColour.withMultipliedSaturation (sat)); 29 | 30 | if (isButtonDown) 31 | return baseColour.contrasting (0.2f); 32 | else if (isMouseOverButton) 33 | return baseColour.contrasting (0.1f); 34 | 35 | return baseColour; 36 | } 37 | 38 | static float getCornerSize(const int width, const int height) 39 | { 40 | return jlimit(1.f, 3.f, 3.f*jmin(width, height)/20.f); 41 | } 42 | 43 | static void createRoundedPath (Path& p, 44 | const float x, const float y, 45 | const float w, const float h, 46 | const float cs, 47 | const bool curveTopLeft, const bool curveTopRight, 48 | const bool curveBottomLeft, const bool curveBottomRight) 49 | { 50 | const float cs2 = 2.0f * cs; 51 | 52 | if (curveTopLeft) 53 | { 54 | p.startNewSubPath (x, y + cs); 55 | p.addArc (x, y, cs2, cs2, float_Pi * 1.5f, float_Pi * 2.0f); 56 | } 57 | else 58 | { 59 | p.startNewSubPath (x, y); 60 | } 61 | 62 | if (curveTopRight) 63 | { 64 | p.lineTo (x + w - cs, y); 65 | p.addArc (x + w - cs2, y, cs2, cs2, 0.0f, float_Pi * 0.5f); 66 | } 67 | else 68 | { 69 | p.lineTo (x + w, y); 70 | } 71 | 72 | if (curveBottomRight) 73 | { 74 | p.lineTo (x + w, y + h - cs); 75 | p.addArc (x + w - cs2, y + h - cs2, cs2, cs2, float_Pi * 0.5f, float_Pi); 76 | } 77 | else 78 | { 79 | p.lineTo (x + w, y + h); 80 | } 81 | 82 | if (curveBottomLeft) 83 | { 84 | p.lineTo (x + cs, y + h); 85 | p.addArc (x, y + h - cs2, cs2, cs2, float_Pi, float_Pi * 1.5f); 86 | } 87 | else 88 | { 89 | p.lineTo (x, y + h); 90 | } 91 | 92 | p.closeSubPath(); 93 | } 94 | 95 | 96 | //------------------------------------------------------------------------------ 97 | LivecutLookAndFeel::LivecutLookAndFeel() 98 | { 99 | static const int standardColours[] = 100 | { 101 | PopupMenu::highlightedBackgroundColourId, Colours::royalblue.getARGB(), 102 | PopupMenu::highlightedTextColourId, 0xffffffff, 103 | PopupMenu::backgroundColourId, 0xff1E1E1E, 104 | PopupMenu::textColourId, 0xffeeeeee, 105 | PopupMenu::headerTextColourId, 0xff57CDFF, 106 | 107 | ComboBox::backgroundColourId, Colours::darkgrey.getARGB(), 108 | ComboBox::outlineColourId, Colours::black.withAlpha(0.5f).getARGB(), 109 | ComboBox::textColourId, 0xffFFFFFF, 110 | ComboBox::arrowColourId, Colours::lightgrey.getARGB(), 111 | 112 | Label::textColourId, 0xffFFFFFF, 113 | 114 | Slider::rotarySliderFillColourId, Colours::darkgrey.getARGB(), 115 | Slider::rotarySliderOutlineColourId, 0xffB0D1F0, 116 | Slider::trackColourId, 0xff1E1E1E, 117 | Slider::thumbColourId, Colours::lightgrey.getARGB(), 118 | 119 | TextButton::buttonColourId, 0xff464646, 120 | TextButton::buttonOnColourId, Colours::royalblue.getARGB(), 121 | TextButton::textColourOnId, 0xffFFFFFF, 122 | TextButton::textColourOffId, 0xffFFFFFF, 123 | }; 124 | 125 | for (int i = 0; i < numElementsInArray (standardColours); i += 2) 126 | setColour (standardColours [i], Colour(standardColours [i + 1])); 127 | } 128 | 129 | LivecutLookAndFeel& LivecutLookAndFeel::getInstance() 130 | { 131 | static ScopedPointer lnf; 132 | 133 | if(!lnf.get()) 134 | { 135 | lnf = new LivecutLookAndFeel(); 136 | } 137 | 138 | return *lnf.get(); 139 | } 140 | 141 | void LivecutLookAndFeel::drawComboBox (Graphics &g, int width, int height, bool isButtonDown, 142 | int buttonX, int buttonY, int buttonW, int buttonH, ComboBox &box) 143 | { 144 | const float cornerSize = getCornerSize(width, height); 145 | 146 | const Colour colour(createBaseColour( box.findColour(ComboBox::backgroundColourId), box.hasKeyboardFocus (true), false, false) 147 | .withMultipliedAlpha (box.isEnabled() ? 1.0f : 0.5f)); 148 | 149 | float x = 0.5; 150 | float y = 0.5; 151 | float w = width-1; 152 | float h = height-1; 153 | 154 | Path outline; 155 | outline.addRoundedRectangle(x, y, w, h, cornerSize); 156 | 157 | // background 158 | if(isButtonDown) 159 | { 160 | g.setFillType(ColourGradient(colour.darker(), 0, y, 161 | colour, 0, y+h, 162 | false)); 163 | } 164 | else 165 | { 166 | g.setFillType(ColourGradient(colour, 0, y, 167 | colour.darker(), 0, y+h, 168 | false)); 169 | } 170 | g.fillPath(outline); 171 | 172 | // bevel 173 | if (!colour.isTransparent()) 174 | { 175 | ColourGradient bevel(Colours::white.withAlpha(0.1f), 0, y+1, 176 | Colours::transparentWhite, 0, y+1+cornerSize+1, false); 177 | g.setFillType(bevel); 178 | g.strokePath(outline, PathStrokeType(1), AffineTransform::translation(0, 1)); 179 | } 180 | 181 | // arrow 182 | if (box.isEnabled()) 183 | { 184 | if ((buttonW > 0.f) && (buttonH > 0.f)) 185 | { 186 | const float arrowW = 0.4f * float(buttonH)/float(buttonW); 187 | const float arrowH = 0.4f * float(buttonW)/float(buttonH); 188 | 189 | Path p; 190 | p.addTriangle ( floor(0.5f+buttonX + buttonW * 0.5f), floor(0.5f+buttonY + buttonH * (0.5f + arrowH/2)), 191 | floor(0.5f+buttonX + buttonW * (0.5f - arrowW/2)), floor(0.5f+buttonY + buttonH * (0.5f - arrowH/2)), 192 | floor(0.5f+buttonX + buttonW * (0.5f + arrowW/2)), floor(0.5f+buttonY + buttonH * (0.5f - arrowH/2))); 193 | 194 | g.setColour (box.findColour(ComboBox::arrowColourId)); 195 | g.fillPath (p); 196 | } 197 | } 198 | 199 | // outline 200 | g.setColour(box.findColour(ComboBox::outlineColourId)); 201 | g.strokePath(outline, PathStrokeType(1)); 202 | } 203 | 204 | void LivecutLookAndFeel::drawButtonBackground (Graphics &g, 205 | Button &button, 206 | const Colour &backgroundColour, 207 | bool isMouseOverButton, bool isButtonDown) 208 | { 209 | const int width = button.getWidth(); 210 | const int height = button.getHeight(); 211 | 212 | const Colour colour(createBaseColour(backgroundColour, button.hasKeyboardFocus (true), isMouseOverButton, isButtonDown) 213 | .withMultipliedAlpha (button.isEnabled() ? 1.0f : 0.5f)); 214 | 215 | 216 | const float cornerSize = getCornerSize(width, height); 217 | 218 | float x = 0.5; 219 | float y = 0.5; 220 | float w = width-1; 221 | float h = height-1; 222 | if(button.isConnectedOnRight()) 223 | w += 1; 224 | Path outline; 225 | createRoundedPath (outline, x, y, w, h, cornerSize, 226 | ! (button.isConnectedOnLeft() || button.isConnectedOnTop()), 227 | ! (button.isConnectedOnRight() || button.isConnectedOnTop()), 228 | ! (button.isConnectedOnLeft() || button.isConnectedOnBottom()), 229 | ! (button.isConnectedOnRight() || button.isConnectedOnBottom())); 230 | 231 | Rectangle r(x, y, width, height); 232 | 233 | if(!(isButtonDown || button.getToggleState())) 234 | { 235 | g.setFillType(ColourGradient(colour, 0, r.getY(), 236 | colour.darker(), 0, r.getBottom(), false)); 237 | g.fillPath(outline); 238 | 239 | ColourGradient bevel(Colours::white.withAlpha(0.1f), 0, y+1, 240 | Colours::transparentWhite, 0, y+1+cornerSize+1, false); 241 | g.setFillType(bevel); 242 | g.strokePath(outline, PathStrokeType(1), AffineTransform::translation(0, 1)); 243 | } 244 | else 245 | { 246 | g.setFillType(ColourGradient(colour.darker(), 0, 0, 247 | colour, 0, r.getHeight(), false)); 248 | g.fillPath(outline); 249 | } 250 | 251 | g.setColour(Colours::black.withAlpha(0.5f)); 252 | g.strokePath(outline, PathStrokeType(1)); 253 | } 254 | 255 | void LivecutLookAndFeel::drawLinearSlider (Graphics& g, 256 | int x, int y, 257 | int width, int height, 258 | float sliderPos, 259 | float minSliderPos, 260 | float maxSliderPos, 261 | const Slider::SliderStyle style, 262 | Slider& slider) 263 | { 264 | LookAndFeel_V3::drawLinearSlider(g,x,y,width,height,sliderPos,minSliderPos, maxSliderPos, style, slider); 265 | } 266 | 267 | void LivecutLookAndFeel::drawLinearSliderBackground (Graphics& g, 268 | int x, int y, 269 | int width, int height, 270 | float sliderPos, 271 | float /*minSliderPos*/, 272 | float /*maxSliderPos*/, 273 | const Slider::SliderStyle /*style*/, 274 | Slider& slider) 275 | { 276 | const float sliderRadius = (float) (getSliderThumbRadius (slider)); 277 | 278 | const Colour trackColour(slider.findColour(Slider::trackColourId)); 279 | const Colour gradCol1 (trackColour.overlaidWith (Colours::black.withAlpha(slider.isEnabled() ? 0.25f : 0.13f))); 280 | const Colour gradCol2 (trackColour.overlaidWith (Colour(0x14000000))); 281 | Path indent; 282 | 283 | const float zeroPos = slider.getPositionOfValue(0); 284 | const int from = jmin(zeroPos, sliderPos); 285 | const int to = jmax(zeroPos, sliderPos); 286 | 287 | if (slider.isHorizontal()) 288 | { 289 | const float iy = y + height * 0.5f - sliderRadius * 0.5f; 290 | const float ih = sliderRadius; 291 | { 292 | ColourGradient gb (gradCol1, 0.0f, iy, gradCol2, 0.0f, iy + ih, false); 293 | g.setFillType(gb); 294 | 295 | indent.addRoundedRectangle (x - sliderRadius * 0.5f, iy, 296 | width + sliderRadius, ih, 297 | 5.0f); 298 | g.fillPath (indent); 299 | } 300 | { 301 | const Colour c = Colours::royalblue.darker(); 302 | const Colour c1 (c.overlaidWith(Colours::black.withAlpha(slider.isEnabled() ? 0.25f : 0.13f))); 303 | const Colour c2 (c.overlaidWith(Colour(0x14000000))); 304 | ColourGradient gb (c1, 0.0f, iy, c2, 0.0f, iy + ih, false); 305 | g.setFillType(gb); 306 | 307 | Path indent2; 308 | float rx = from - sliderRadius * 0.5f; 309 | float rw = to-from; 310 | indent2.addRoundedRectangle (rx, iy, rw, ih, 5.0f); 311 | g.fillPath (indent2); 312 | } 313 | } 314 | else 315 | { 316 | const float ix = x + width * 0.5f - sliderRadius * 0.5f; 317 | const float iw = sliderRadius; 318 | { 319 | ColourGradient gb (gradCol1, ix, 0.0f, gradCol2, ix + iw, 0.0f, false); 320 | g.setFillType(gb); 321 | 322 | indent.addRoundedRectangle (ix, y - sliderRadius * 0.5f, 323 | iw, height + sliderRadius, 324 | 5.0f); 325 | g.fillPath (indent); 326 | } 327 | { 328 | const Colour c = Colours::royalblue.darker(); 329 | const Colour c1(c.overlaidWith(Colours::black.withAlpha(slider.isEnabled() ? 0.25f : 0.13f))); 330 | const Colour c2(c.overlaidWith(Colour(0x14000000))); 331 | ColourGradient gb (c1, ix, 0.0f, c2, ix + iw, 0.0f, false); 332 | g.setFillType(gb); 333 | 334 | Path indent2; 335 | float ry = from+sliderRadius*0.5f; 336 | float rh = to-from+sliderRadius*0.5f; 337 | indent2.addRoundedRectangle (ix, ry, iw, rh, 5.0f); 338 | g.fillPath (indent2); 339 | } 340 | } 341 | 342 | g.setColour (Colour (0x4c000000)); 343 | g.strokePath (indent, PathStrokeType (1.f)); 344 | 345 | if (slider.isHorizontal()) 346 | { 347 | Rectangle r = indent.getBounds(); 348 | g.setFillType(ColourGradient(Colours::black.withAlpha(0.1f), 0, r.getY(), 349 | Colours::transparentBlack, 0, r.getY()+5, false)); 350 | g.strokePath (indent, PathStrokeType (1.f)); 351 | 352 | g.setFillType(ColourGradient(Colours::transparentWhite, 0, r.getBottom()-5, 353 | Colours::white.withAlpha(0.15f), 0, r.getBottom(), false)); 354 | g.strokePath (indent, PathStrokeType (1.f)); 355 | } 356 | } 357 | 358 | void LivecutLookAndFeel::drawLinearSliderThumb(Graphics& g, 359 | int x, int y, 360 | int width, int height, 361 | float sliderPos, 362 | float minSliderPos, 363 | float maxSliderPos, 364 | const Slider::SliderStyle style, 365 | Slider& slider) 366 | { 367 | const float sliderRadius = (float)getSliderThumbRadius (slider); 368 | 369 | Colour knobColour (createBaseColour (slider.findColour (Slider::thumbColourId), 370 | slider.hasKeyboardFocus (false) && slider.isEnabled(), 371 | slider.isMouseOverOrDragging() && slider.isEnabled(), 372 | slider.isMouseButtonDown() && slider.isEnabled())); 373 | 374 | const float outlineThickness = slider.isEnabled() ? 1.f : 0.5f; 375 | 376 | if (style == Slider::LinearHorizontal || style == Slider::LinearVertical) 377 | { 378 | float kx, ky; 379 | 380 | if (style == Slider::LinearVertical) 381 | { 382 | kx = x + width * 0.5f; 383 | ky = sliderPos; 384 | } 385 | else 386 | { 387 | kx = sliderPos; 388 | ky = y + height * 0.5f; 389 | } 390 | 391 | Path ellipse; 392 | ellipse.addEllipse(kx-sliderRadius+0.5, ky-sliderRadius+0.5, 2*sliderRadius-1, 2*sliderRadius-1); 393 | 394 | //background 395 | g.setFillType(ColourGradient(knobColour, kx, ky, 396 | knobColour.darker(), kx, ky+2*sliderRadius, false)); 397 | g.fillPath(ellipse); 398 | 399 | // higlight 400 | g.setFillType(ColourGradient(Colours::white.withAlpha(0.1f), kx, ky+1, 401 | Colours::transparentWhite, kx, ky+sliderRadius, false)); 402 | g.strokePath(ellipse, PathStrokeType(1.f), AffineTransform::translation(0, 1)); 403 | 404 | // outline 405 | g.setColour(Colours::black.withAlpha(0.5f)); 406 | g.strokePath(ellipse, PathStrokeType(1.f)); 407 | } 408 | else 409 | { 410 | LookAndFeel_V3::drawLinearSliderThumb(g,x,y,width,height, sliderPos, minSliderPos, maxSliderPos, style, slider); 411 | } 412 | } 413 | 414 | int LivecutLookAndFeel::getSliderThumbRadius (Slider& slider) 415 | { 416 | return jmin (7, slider.getHeight()/2, slider.getWidth()/2); 417 | } 418 | 419 | void LivecutLookAndFeel::drawRotarySlider (Graphics& g, 420 | int x, int y, 421 | int width, int height, 422 | float sliderPos, 423 | float rotaryStartAngle, 424 | float rotaryEndAngle, 425 | Slider& slider) 426 | { 427 | const float radius = jmin (width / 2, height / 2); 428 | const float centreX = x + width * 0.5f; 429 | const float centreY = y + height * 0.5f; 430 | const float rx = centreX - radius; 431 | const float ry = centreY - radius; 432 | const float rw = radius * 2.0f; 433 | 434 | const float lineWidth = jmax(1.f, radius * 0.15f); 435 | 436 | const float minimum = slider.getMinimum(); 437 | const float maximum = slider.getMaximum(); 438 | 439 | const float referencePos = slider.valueToProportionOfLength(jlimit(minimum, maximum, 0.f)); 440 | 441 | const float from = jmin(referencePos, sliderPos); 442 | const float to = jmax(referencePos, sliderPos); 443 | 444 | const float angle = rotaryStartAngle + sliderPos * (rotaryEndAngle - rotaryStartAngle); 445 | const float fromAngle = rotaryStartAngle + from * (rotaryEndAngle - rotaryStartAngle); 446 | const float toAngle = rotaryStartAngle + to * (rotaryEndAngle - rotaryStartAngle); 447 | 448 | const bool isMouseOver = slider.isMouseOverOrDragging() && slider.isEnabled(); 449 | 450 | Colour colour = slider.isEnabled()? slider.findColour (Slider::rotarySliderFillColourId) : Colour (0x80808080); 451 | g.setColour (colour); 452 | 453 | Colour outlineColour = slider.isEnabled()? slider.findColour (Slider::rotarySliderOutlineColourId) : Colour (0x80808080); 454 | 455 | { 456 | //const float thickness = (radius>12.f)? 0.8f : 1.f; 457 | 458 | { 459 | const float thickness = (radius - lineWidth) / float(radius); 460 | Path filledArc; 461 | filledArc.addPieSegment(rx, ry, rw, rw, 462 | rotaryStartAngle, 463 | rotaryEndAngle, 464 | thickness); 465 | g.setColour(Colours::black.withAlpha(0.3f)); 466 | g.fillPath (filledArc); 467 | } 468 | { 469 | const float thickness = (radius - lineWidth) / float(radius); 470 | Path filledArc; 471 | filledArc.addPieSegment(rx, ry, rw, rw, 472 | fromAngle, 473 | toAngle, 474 | thickness); 475 | g.setColour(outlineColour); 476 | g.fillPath (filledArc); 477 | } 478 | 479 | //if (thickness > 0) 480 | { 481 | g.saveState(); 482 | 483 | const float innerRadius = radius - lineWidth - 2; 484 | Path shape; 485 | shape.addEllipse(-innerRadius+0.5f, -innerRadius+0.5f, 2*innerRadius-1, 2*innerRadius-1); 486 | 487 | { 488 | // inside 489 | ColourGradient gradient(colour, centreX, centreY-innerRadius, 490 | colour.darker(),centreX, centreY+innerRadius, 491 | false); 492 | ColourGradient brush(gradient); 493 | g.setGradientFill(brush); 494 | g.fillPath (shape, AffineTransform::translation (centreX, centreY)); 495 | } 496 | 497 | // higlight 498 | g.setFillType(ColourGradient(Colours::white.withAlpha(0.2f), centreX, centreY-innerRadius, 499 | Colours::transparentWhite, centreX, centreY, 500 | false)); 501 | g.strokePath(shape, PathStrokeType(2), AffineTransform::translation(centreX, centreY+1)); 502 | 503 | // shadow 504 | g.setFillType(ColourGradient(Colours::transparentBlack, centreX, centreY, 505 | Colours::black.withAlpha(0.2f), centreX, centreY+innerRadius, 506 | false)); 507 | g.strokePath(shape, PathStrokeType(2), AffineTransform::translation(centreX, centreY+1)); 508 | 509 | g.restoreState(); 510 | 511 | //handle 512 | g.setColour(colour.contrasting(0.5f)); 513 | Path handle; 514 | float handleWidth = jmax(2.f, innerRadius/4.f); 515 | handle.addRoundedRectangle(-handleWidth/2.f, -innerRadius, handleWidth , innerRadius, 2); 516 | g.fillPath (handle, AffineTransform::rotation(angle).scaled(0.8f, 0.8f).translated (centreX, centreY)); 517 | 518 | // outline 519 | g.setColour(Colours::black.withAlpha(0.5f)); 520 | g.strokePath(shape, PathStrokeType(1), AffineTransform::translation(centreX, centreY)); 521 | 522 | } 523 | } 524 | } 525 | 526 | -------------------------------------------------------------------------------- /Source/BBCutter.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Livecut 3 | Copyright 2003 by Remy Muller. 4 | 5 | Livecut can be redistributed and/or modified under the terms of the 6 | GNU General Public License, as published by the Free Software Foundation; 7 | either version 2 of the License, or (at your option) any later version. 8 | 9 | Livecut is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Livecut; if not, visit www.gnu.org/licenses or write to the 16 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 17 | Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #include "BBCutter.h" 21 | 22 | //------------------------------------------------------------------------------- 23 | CutInfo::CutInfo() 24 | : size(0) 25 | , length(0) 26 | , pan(0.f) 27 | , amp(1.f) 28 | , cents(0.f) 29 | { 30 | } 31 | 32 | CutProc::CutProc() 33 | : minamp(1.f) 34 | , maxamp(1.f) 35 | , minpan(0.5f) 36 | , maxpan(0.5f) 37 | , mindetune(0.f) 38 | , maxdetune(0.f) 39 | , dutycycle(1.f) 40 | , filldutycycle(1.f) 41 | , maxphraselength(4) 42 | , minphraselength(1) 43 | { 44 | } 45 | 46 | CutProc::~CutProc() {} 47 | 48 | void CutProc::SetMinAmp(float v) { minamp = v;} 49 | void CutProc::SetMaxAmp(float v) { maxamp = v;} 50 | void CutProc::SetMinPan(float v) { minpan = v;} 51 | void CutProc::SetMaxPan(float v) { maxpan = v;} 52 | void CutProc::SetMinDetune(float v) { mindetune = v;} 53 | void CutProc::SetMaxDetune(float v) { maxdetune = v;} 54 | void CutProc::SetDutyCycle(float v) { dutycycle = v;} 55 | void CutProc::SetFillDutyCycle(float v) { filldutycycle = v;} 56 | void CutProc::SetMinPhraseLength(long v) { minphraselength = v;} 57 | void CutProc::SetMaxPhraseLength(long v) { maxphraselength = v;} 58 | 59 | long CutProc::ChoosePhraseLength() 60 | { 61 | return Math::randominteger(minphraselength,maxphraselength); 62 | } 63 | 64 | void CutProc::ChooseCuts(std::vector &cuts, 65 | long &unitsinblock, 66 | long unitsdone, 67 | long totalunits, 68 | long subdiv, 69 | double spu) 70 | { 71 | } 72 | 73 | //------------------------------------------------------------------------------- 74 | long CutProc11::ChooseRepeats() 75 | { 76 | return Math::randominteger(minrepeats,maxrepeats); 77 | } 78 | 79 | long CutProc11::ChooseUnitsInCut(long subdiv) 80 | { // units = 2*x+1 , x is natural // 1 <= 2*x + 1 <= subdiv/2+1 81 | return 2*long(Math::randomfloat(0.f, float(subdiv)/4.f)+0.5f) + 1; 82 | } 83 | 84 | CutProc11::CutProc11() 85 | : stutterchance(1.f) 86 | , stutterarea(0.5f) 87 | , minrepeats(1) 88 | , maxrepeats(2) 89 | { 90 | } 91 | 92 | void CutProc11::SetStutterChance(float v) { stutterchance = v;} 93 | void CutProc11::SetStutterArea(float v) { stutterarea = v;} 94 | void CutProc11::SetMinRepeats(long v) { minrepeats = v+1;} //not repeats actually but occurences 95 | void CutProc11::SetMaxRepeats(long v) { maxrepeats = v+1;} 96 | 97 | void CutProc11::ChooseCuts(std::vector &cuts, 98 | long &unitsinblock, 99 | long unitsdone, 100 | long totalunits, 101 | long subdiv, 102 | double spu) 103 | { 104 | const long unitsleft = totalunits-unitsdone; 105 | long unitsincut = 1; 106 | long repeats = 1; 107 | 108 | if( float(unitsleft)/float(subdiv) < stutterarea && 109 | Math::randomfloat(0.0, 1.0) < stutterchance) //end of phrase stutter 110 | { 111 | long numbers[] = { 1, 2, 3, 4, 6, 8 }; 112 | double probs[] = { 0.4, 0.3, 0.1, 0.1, 0.05, 0.05 }; 113 | long multiplier = Math::wchoose(numbers,probs,6); 114 | repeats=unitsleft*multiplier; 115 | double unitsinthiscut= 1.0/multiplier; 116 | unitsinblock = repeats*unitsinthiscut; 117 | cuts.resize(repeats); 118 | const float startpan = Math::randomfloat(minpan,maxpan); 119 | const float endpan = Math::randomfloat(minpan,maxpan); 120 | const float startamp = Math::randomfloat(minamp,maxamp); 121 | const float endamp = Math::randomfloat(minamp,maxamp); 122 | const float startdetune = 0.f; 123 | const float enddetune = Math::randomfloat(mindetune,maxdetune); 124 | 125 | for(int i=0;iunitsleft) {unitsincut -= 2;} 142 | if(unitsincut<0) {unitsincut = 0;} 143 | 144 | while((repeats*unitsincut)>unitsleft) 145 | { 146 | if(repeats>1) 147 | { 148 | repeats--; 149 | } 150 | else if(unitsleft<=(subdiv/2+1)) 151 | { 152 | unitsincut=unitsleft; 153 | repeats=1; 154 | } 155 | else 156 | { 157 | unitsincut=1; //shouldn't happen 158 | repeats=1; 159 | } 160 | } 161 | unitsinblock = repeats*unitsincut; 162 | cuts.resize(repeats); 163 | for(int i=0;i &cuts, 206 | long &unitsinblock, 207 | long unitsdone, 208 | long totalunits, 209 | long subdiv, 210 | double spu) 211 | { 212 | const long unitsleft = totalunits-unitsdone; 213 | long repeats = 1; 214 | unitsinblock = ChooseBlockSize(); 215 | if(unitsinblock>unitsleft) 216 | unitsinblock = unitsleft; 217 | 218 | if(Math::randomfloat(0.0, 1.0)< straightchance) 219 | { 220 | double temp = double(unitsinblock)/double(repeats); 221 | cuts.resize(repeats); 222 | for(int i=0;i &cuts, 375 | long &unitsinblock, 376 | long unitsdone, 377 | long totalunits, 378 | long subdiv, 379 | double spu) 380 | { 381 | const long unitsleft = subdiv - (unitsdone%subdiv); //one bar at a time 382 | double done = double(unitsdone)/double(subdiv); 383 | long phrase = long(done); //{0,1,2,3} bars 384 | long barpos = long(done*4.0) % 4; //{0,1,2,3} beats 385 | long beatpos = long(done*16.0)%4; //position inside beat {0,1,2,3} semiquaver 386 | long quaver = long(done*8.0) % 8; //quaver inside bar 387 | //quaver = (long(done*8.0)*2) % 8; 388 | double barprop = double(barpos)/4.0; 389 | double sqweights[]= {0.0, 0.3, 0.0, 0.5, 0.7, 0.8, 0.9, 0.6}; 390 | double sqchance = sqweights[quaver]*activity; 391 | double spb = spu*double(subdiv)/4.0; //samplesperbeat 392 | 393 | if((totalunits-unitsdone) == subdiv) 394 | { 395 | fill = true; 396 | fillnumber = Math::randominteger(0,12); 397 | fillpos=0; 398 | } 399 | 400 | if(fill==true) 401 | { 402 | if(fillposunitsleft) 419 | unitsinblock=unitsleft; //will automatically interrupt cutsequence before its end 420 | fillpos++; 421 | return; 422 | } 423 | else 424 | { 425 | fill = false; 426 | fillpos=0; 427 | } 428 | } 429 | 430 | { 431 | long temp = 1 + 2*Math::randominteger(0,1); 432 | if(beatpos == 2) 433 | temp=1; 434 | 435 | unitsinblock = long(double(temp*8.0)/double(subdiv)); 436 | if(unitsinblock>unitsleft) 437 | unitsinblock=unitsleft; //will automatically interrupt cutsequence before its end 438 | 439 | if(Math::randomfloat(0.0,1.0) < sqchance) // 2*temp semiquaver 440 | { 441 | cuts.resize(temp*2); 442 | for(int i=0;iOnPhrase(bar,sd); 475 | } 476 | } 477 | 478 | void ListenerManager::OnBlock(long bar, long sd) 479 | { 480 | for(int i=0;iOnBlock(bar,sd); 483 | } 484 | } 485 | 486 | void ListenerManager::OnUnit(long bar, long sd) 487 | { 488 | for(int i=0;iOnUnit(bar,sd); 491 | } 492 | } 493 | 494 | void ListenerManager::OnCut(long cut, long numcuts) 495 | { 496 | for(int i=0;iOnCut(cut,numcuts); 499 | } 500 | } 501 | 502 | void ListenerManager::RegisterListener(BBCutListener *l) 503 | { 504 | if(l) 505 | listeners.push_back(l); 506 | } 507 | 508 | //------------------------------------------------------------------------ 509 | LivePlayer::LivePlayer() 510 | : currentcut(0) 511 | , inputindex(0) 512 | , readindex(0) 513 | , ll(0.f) 514 | , lr(0.f) 515 | , rl(0.f) 516 | , rr(0.f) 517 | , fade(0) 518 | , L(&inputbufferL) 519 | , R(&inputbufferR) 520 | , listenermanager(NULL) 521 | { 522 | } 523 | 524 | void LivePlayer::SetListenerManager(ListenerManager *lm) 525 | { 526 | listenermanager = lm; 527 | } 528 | 529 | void LivePlayer::SetFade(float v) 530 | { 531 | if(v<1.f) v = 1.f ; //0.1f; 532 | fade = v; 533 | } 534 | 535 | void LivePlayer::OnBlock(std::vector newcuts) 536 | { 537 | if(!newcuts.empty()) 538 | { 539 | cuts = newcuts; 540 | //rotation matrix 541 | // [ll lr] 542 | // [rl rr] 543 | const float pan = cuts[0].pan; 544 | const float amp = cuts[0].amp; 545 | ll = amp * ((pan<0)? 1.f : cos(pan*2*pi_4)); 546 | lr = amp * ((pan<0)? 0.f : sin(pan*2*pi_4)); 547 | rl = amp * ((pan>0)? 0.f : -sin(pan*2*pi_4)); 548 | rr = amp * ((pan>0)? 1.f : cos(pan*2*pi_4)); 549 | inputindex = readindex = 0; 550 | currentcut=0; 551 | 552 | // tell cut-synchrone effects 553 | if(listenermanager) 554 | listenermanager->OnCut(currentcut,cuts.size()); // allow interpolation... 555 | 556 | 557 | long maxcutlength=0; 558 | for(int i=0;imaxcutlength) 560 | maxcutlength = cuts[i].size; 561 | 562 | inputbufferL.resize(maxcutlength,0.f); 563 | inputbufferR.resize(maxcutlength,0.f); 564 | pitchedbufferL.resize(maxcutlength,0.f); 565 | pitchedbufferR.resize(maxcutlength,0.f); 566 | L = &inputbufferL; 567 | R = &inputbufferR; 568 | } 569 | } 570 | 571 | //------------------------------------------------------------------------------------------------ 572 | #include 573 | #include 574 | #include 575 | using std::for_each; 576 | using std::mem_fun; 577 | using std::bind2nd; 578 | 579 | BBCutter::BBCutter(LivePlayer &player) 580 | : player(player) 581 | , tempo(180) 582 | , sr(44100) 583 | , subdiv(8) 584 | , numerator(4) 585 | , denominator(4) 586 | , beatsPerBar(4.0*numerator/double(denominator)) 587 | //states 588 | , unitsdone(0) 589 | , totalunits(0) 590 | , barsnow(0) 591 | , unitsinblock(0) 592 | , unitsinsideblock(0) 593 | , barsinsample(1) 594 | , slicestart(0) 595 | , strategy(&cutproc11) 596 | { 597 | procs.reserve(kNumCutProcs); 598 | procs.push_back(&cutproc11); 599 | procs.push_back(&warpcutproc); 600 | procs.push_back(&sqpusher); 601 | 602 | player.SetListenerManager(&listenermanager); 603 | } 604 | 605 | BBCutter::~BBCutter() 606 | { 607 | } 608 | 609 | void BBCutter::RegisterListener(BBCutListener *l) 610 | { 611 | listenermanager.RegisterListener(l); 612 | } 613 | 614 | void BBCutter::SetCutProc(long i) 615 | { 616 | assert(i>=0 && i=0 && iChoosePhraseLength(); 689 | totalunits = barsnow*subdiv; 690 | unitsdone = 0; 691 | 692 | listenermanager.OnPhrase(bar,sd); 693 | } 694 | 695 | void BBCutter::Block(long bar,long sd) 696 | { 697 | unitsinsideblock=0; 698 | std::vector cuts; 699 | strategy->ChooseCuts(cuts,unitsinblock, 700 | unitsdone,totalunits,subdiv,SamplesPerUnit()); 701 | player.OnBlock(cuts); 702 | 703 | listenermanager.OnBlock(bar,sd); 704 | } 705 | 706 | void BBCutter::Unit(long bar, long sd) 707 | { 708 | if( totalunits<=0 || unitsdone>=totalunits || unitsdone<0 ) //out of phrase bounds and start of a bar 709 | { 710 | if(sd == 0) 711 | Phrase(bar,sd); 712 | else 713 | return; 714 | } 715 | 716 | if( unitsinsideblock>=unitsinblock || unitsinsideblock<0) //out of block bounds 717 | Block(bar,sd); 718 | 719 | unitsinsideblock++; 720 | unitsdone++; 721 | 722 | listenermanager.OnUnit(bar,sd); 723 | } 724 | 725 | void BBCutter::SetPosition(long bar, long sd) 726 | { 727 | const long delta = sd - (unitsdone % long(UnitsPerBar(subdiv,numerator,denominator))); 728 | unitsinsideblock += delta; 729 | unitsdone += delta; 730 | Unit(bar,sd); 731 | } 732 | 733 | --------------------------------------------------------------------------------