- initial import

git-svn-id: http://moon:8086/svn/software/trunk/projects/JaySynth@37 b431acfa-c32f-4a4a-93f1-934dc6c82436
This commit is contained in:
2014-10-25 07:27:55 +00:00
commit 843c6e300c
75 changed files with 40248 additions and 0 deletions
Binary file not shown.
Binary file not shown.
+19
View File
@@ -0,0 +1,19 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JaySynth", "JaySynth.vcxproj", "{2400C049-DC84-E012-E041-0D0690E731F9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{2400C049-DC84-E012-E041-0D0690E731F9}.Debug|Win32.ActiveCfg = Debug|Win32
{2400C049-DC84-E012-E041-0D0690E731F9}.Debug|Win32.Build.0 = Debug|Win32
{2400C049-DC84-E012-E041-0D0690E731F9}.Release|Win32.ActiveCfg = Release|Win32
{2400C049-DC84-E012-E041-0D0690E731F9}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8"?>
<VisualStudioUserFile
ProjectType="Visual C++"
Version="9,00"
ShowAllFiles="false"
>
<Configurations>
<Configuration
Name="Debug|Win32"
>
<DebugSettings
Command="D:\Drive_E\bin\VST-Host\vsthost.exe"
WorkingDirectory="D:\Drive_E\bin\VST-Host\"
CommandArguments=""
Attach="false"
DebuggerType="3"
Remote="1"
RemoteMachine="SATURN"
RemoteCommand=""
HttpUrl=""
PDBPath=""
SQLDebugging=""
Environment=""
EnvironmentMerge="true"
DebuggerFlavor="0"
MPIRunCommand=""
MPIRunArguments=""
MPIRunWorkingDirectory=""
ApplicationCommand=""
ApplicationArguments=""
ShimCommand=""
MPIAcceptMode=""
MPIAcceptFilter=""
/>
</Configuration>
<Configuration
Name="Release|Win32"
>
<DebugSettings
Command=""
WorkingDirectory=""
CommandArguments=""
Attach="false"
DebuggerType="3"
Remote="1"
RemoteMachine="SATURN"
RemoteCommand=""
HttpUrl=""
PDBPath=""
SQLDebugging=""
Environment=""
EnvironmentMerge="true"
DebuggerFlavor=""
MPIRunCommand=""
MPIRunArguments=""
MPIRunWorkingDirectory=""
ApplicationCommand=""
ApplicationArguments=""
ShimCommand=""
MPIAcceptMode=""
MPIAcceptFilter=""
/>
</Configuration>
</Configurations>
</VisualStudioUserFile>
@@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8"?>
<VisualStudioUserFile
ProjectType="Visual C++"
Version="9,00"
ShowAllFiles="false"
>
<Configurations>
<Configuration
Name="Debug|Win32"
>
<DebugSettings
Command="E:\bin\VST-Host\vsthost.exe"
WorkingDirectory=""
CommandArguments=""
Attach="false"
DebuggerType="3"
Remote="1"
RemoteMachine="JUPITER"
RemoteCommand=""
HttpUrl=""
PDBPath=""
SQLDebugging=""
Environment=""
EnvironmentMerge="true"
DebuggerFlavor="0"
MPIRunCommand=""
MPIRunArguments=""
MPIRunWorkingDirectory=""
ApplicationCommand=""
ApplicationArguments=""
ShimCommand=""
MPIAcceptMode=""
MPIAcceptFilter=""
/>
</Configuration>
<Configuration
Name="Release|Win32"
>
<DebugSettings
Command="C:\Program Files (x86)\Steinberg\Cubase 4\Cubase4.exe"
WorkingDirectory=""
CommandArguments=""
Attach="false"
DebuggerType="3"
Remote="1"
RemoteMachine="JUPITER"
RemoteCommand=""
HttpUrl=""
PDBPath=""
SQLDebugging=""
Environment=""
EnvironmentMerge="true"
DebuggerFlavor="0"
MPIRunCommand=""
MPIRunArguments=""
MPIRunWorkingDirectory=""
ApplicationCommand=""
ApplicationArguments=""
ShimCommand=""
MPIAcceptMode=""
MPIAcceptFilter=""
/>
</Configuration>
</Configurations>
</VisualStudioUserFile>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large Load Diff
Binary file not shown.
+32
View File
@@ -0,0 +1,32 @@
#undef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "../../JuceLibraryCode/AppConfig.h"
VS_VERSION_INFO VERSIONINFO
FILEVERSION JucePlugin_Version
PRODUCTVERSION JucePlugin_Version
#ifdef DEBUG
FILEFLAGS VS_FF_DEBUG
#else
FILEFLAGS VS_FF_PRERELEASE
#endif
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904E4"
BEGIN
VALUE "CompanyName", JucePlugin_Manufacturer
VALUE "LegalCopyright", "Copyright (C) 2012, 2013\0"
VALUE "FileDescription", JucePlugin_Desc
VALUE "FileVersion", JucePlugin_VersionString
VALUE "ProductName", JucePlugin_Name
VALUE "ProductVersion", JucePlugin_VersionString
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 65001
END
END
+259
View File
@@ -0,0 +1,259 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
There's a section below where you can add your own custom code safely, and the
Introjucer will preserve the contents of that block, but the best way to change
any of these definitions is by using the Introjucer's project settings.
Any commented-out settings will assume their default values.
*/
#ifndef __JUCE_APPCONFIG_SGFP29__
#define __JUCE_APPCONFIG_SGFP29__
//==============================================================================
// [BEGIN_USER_CODE_SECTION]
// (You can add your own code in this section, and the Introjucer will not overwrite it)
// [END_USER_CODE_SECTION]
//==============================================================================
#define JUCE_MODULE_AVAILABLE_juce_audio_basics 1
#define JUCE_MODULE_AVAILABLE_juce_audio_devices 1
#define JUCE_MODULE_AVAILABLE_juce_audio_formats 1
#define JUCE_MODULE_AVAILABLE_juce_audio_plugin_client 1
#define JUCE_MODULE_AVAILABLE_juce_audio_processors 1
#define JUCE_MODULE_AVAILABLE_juce_core 1
#define JUCE_MODULE_AVAILABLE_juce_data_structures 1
#define JUCE_MODULE_AVAILABLE_juce_events 1
#define JUCE_MODULE_AVAILABLE_juce_graphics 1
#define JUCE_MODULE_AVAILABLE_juce_gui_basics 1
#define JUCE_MODULE_AVAILABLE_juce_gui_extra 1
//==============================================================================
// juce_audio_devices flags:
#ifndef JUCE_ASIO
//#define JUCE_ASIO
#endif
#ifndef JUCE_WASAPI
//#define JUCE_WASAPI
#endif
#ifndef JUCE_DIRECTSOUND
//#define JUCE_DIRECTSOUND
#endif
#ifndef JUCE_ALSA
//#define JUCE_ALSA
#endif
#ifndef JUCE_JACK
//#define JUCE_JACK
#endif
#ifndef JUCE_USE_ANDROID_OPENSLES
//#define JUCE_USE_ANDROID_OPENSLES
#endif
#ifndef JUCE_USE_CDREADER
//#define JUCE_USE_CDREADER
#endif
#ifndef JUCE_USE_CDBURNER
//#define JUCE_USE_CDBURNER
#endif
//==============================================================================
// juce_audio_formats flags:
#ifndef JUCE_USE_FLAC
//#define JUCE_USE_FLAC
#endif
#ifndef JUCE_USE_OGGVORBIS
//#define JUCE_USE_OGGVORBIS
#endif
#ifndef JUCE_USE_MP3AUDIOFORMAT
//#define JUCE_USE_MP3AUDIOFORMAT
#endif
#ifndef JUCE_USE_WINDOWS_MEDIA_FORMAT
//#define JUCE_USE_WINDOWS_MEDIA_FORMAT
#endif
//==============================================================================
// juce_audio_processors flags:
#ifndef JUCE_PLUGINHOST_VST
#define JUCE_PLUGINHOST_VST 1
#endif
#ifndef JUCE_PLUGINHOST_AU
//#define JUCE_PLUGINHOST_AU
#endif
//==============================================================================
// juce_core flags:
#ifndef JUCE_FORCE_DEBUG
//#define JUCE_FORCE_DEBUG
#endif
#ifndef JUCE_LOG_ASSERTIONS
//#define JUCE_LOG_ASSERTIONS
#endif
#ifndef JUCE_CHECK_MEMORY_LEAKS
//#define JUCE_CHECK_MEMORY_LEAKS
#endif
#ifndef JUCE_DONT_AUTOLINK_TO_WIN32_LIBRARIES
//#define JUCE_DONT_AUTOLINK_TO_WIN32_LIBRARIES
#endif
//==============================================================================
// juce_graphics flags:
#ifndef JUCE_USE_COREIMAGE_LOADER
//#define JUCE_USE_COREIMAGE_LOADER
#endif
#ifndef JUCE_USE_DIRECTWRITE
#define JUCE_USE_DIRECTWRITE 0
#endif
//==============================================================================
// juce_gui_basics flags:
#ifndef JUCE_ENABLE_REPAINT_DEBUGGING
//#define JUCE_ENABLE_REPAINT_DEBUGGING
#endif
#ifndef JUCE_USE_XSHM
//#define JUCE_USE_XSHM
#endif
#ifndef JUCE_USE_XRENDER
//#define JUCE_USE_XRENDER
#endif
#ifndef JUCE_USE_XCURSOR
//#define JUCE_USE_XCURSOR
#endif
//==============================================================================
// juce_gui_extra flags:
#ifndef JUCE_WEB_BROWSER
//#define JUCE_WEB_BROWSER
#endif
//==============================================================================
// Audio plugin settings..
#ifndef JucePlugin_Build_VST
#define JucePlugin_Build_VST 1
#endif
#ifndef JucePlugin_Build_AU
#define JucePlugin_Build_AU 1
#endif
#ifndef JucePlugin_Build_RTAS
#define JucePlugin_Build_RTAS 0
#endif
#ifndef JucePlugin_Name
#define JucePlugin_Name "JaySynth"
#endif
#ifndef JucePlugin_Desc
#define JucePlugin_Desc "A Synthesizer VST-Plugin"
#endif
#ifndef JucePlugin_Manufacturer
#define JucePlugin_Manufacturer "Jay Digital Illusions"
#endif
#ifndef JucePlugin_ManufacturerCode
#define JucePlugin_ManufacturerCode '3110'
#endif
#ifndef JucePlugin_PluginCode
#define JucePlugin_PluginCode 'Jsy1'
#endif
#ifndef JucePlugin_MaxNumInputChannels
#define JucePlugin_MaxNumInputChannels 2
#endif
#ifndef JucePlugin_MaxNumOutputChannels
#define JucePlugin_MaxNumOutputChannels 2
#endif
#ifndef JucePlugin_PreferredChannelConfigurations
#define JucePlugin_PreferredChannelConfigurations {2, 2}
#endif
#ifndef JucePlugin_IsSynth
#define JucePlugin_IsSynth 1
#endif
#ifndef JucePlugin_WantsMidiInput
#define JucePlugin_WantsMidiInput 1
#endif
#ifndef JucePlugin_ProducesMidiOutput
#define JucePlugin_ProducesMidiOutput 0
#endif
#ifndef JucePlugin_SilenceInProducesSilenceOut
#define JucePlugin_SilenceInProducesSilenceOut 0
#endif
#ifndef JucePlugin_TailLengthSeconds
#define JucePlugin_TailLengthSeconds 0
#endif
#ifndef JucePlugin_EditorRequiresKeyboardFocus
#define JucePlugin_EditorRequiresKeyboardFocus 0
#endif
#ifndef JucePlugin_Version
#define JucePlugin_Version 0,5,6,0
#endif
#ifndef JucePlugin_VersionCode
#define JucePlugin_VersionCode 560
#endif
#ifndef JucePlugin_VersionString
#define JucePlugin_VersionString "0.5.6"
#endif
#ifndef JucePlugin_VSTUniqueID
#define JucePlugin_VSTUniqueID JucePlugin_PluginCode
#endif
#ifndef JucePlugin_VSTCategory
#define JucePlugin_VSTCategory kPlugCategSynth
#endif
#ifndef JucePlugin_AUMainType
#define JucePlugin_AUMainType kAudioUnitType_MusicDevice
#endif
#ifndef JucePlugin_AUSubType
#define JucePlugin_AUSubType JucePlugin_PluginCode
#endif
#ifndef JucePlugin_AUExportPrefix
#define JucePlugin_AUExportPrefix JaySynthAU
#endif
#ifndef JucePlugin_AUExportPrefixQuoted
#define JucePlugin_AUExportPrefixQuoted "JaySynthAU"
#endif
#ifndef JucePlugin_AUManufacturerCode
#define JucePlugin_AUManufacturerCode JucePlugin_ManufacturerCode
#endif
#ifndef JucePlugin_CFBundleIdentifier
#define JucePlugin_CFBundleIdentifier com.JDI.JaySynth
#endif
#ifndef JucePlugin_AUCocoaViewClassName
#define JucePlugin_AUCocoaViewClassName JaySynthAU_V1
#endif
#ifndef JucePlugin_RTASCategory
#define JucePlugin_RTASCategory ePlugInCategory_SWGenerators
#endif
#ifndef JucePlugin_RTASManufacturerCode
#define JucePlugin_RTASManufacturerCode JucePlugin_ManufacturerCode
#endif
#ifndef JucePlugin_RTASProductId
#define JucePlugin_RTASProductId JucePlugin_PluginCode
#endif
#endif // __JUCE_APPCONFIG_SGFP29__
+43
View File
@@ -0,0 +1,43 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
This is the header file that your files should include in order to get all the
JUCE library headers. You should avoid including the JUCE headers directly in
your own source files, because that wouldn't pick up the correct configuration
options for your app.
*/
#ifndef __APPHEADERFILE_SGFP29__
#define __APPHEADERFILE_SGFP29__
#include "AppConfig.h"
#include "modules/juce_audio_basics/juce_audio_basics.h"
#include "modules/juce_audio_devices/juce_audio_devices.h"
#include "modules/juce_audio_formats/juce_audio_formats.h"
#include "modules/juce_audio_plugin_client/juce_audio_plugin_client.h"
#include "modules/juce_audio_processors/juce_audio_processors.h"
#include "modules/juce_core/juce_core.h"
#include "modules/juce_data_structures/juce_data_structures.h"
#include "modules/juce_events/juce_events.h"
#include "modules/juce_graphics/juce_graphics.h"
#include "modules/juce_gui_basics/juce_gui_basics.h"
#include "modules/juce_gui_extra/juce_gui_extra.h"
#if ! DONT_SET_USING_JUCE_NAMESPACE
// If your code uses a lot of JUCE classes, then this will obviously save you
// a lot of typing, but can be disabled by setting DONT_SET_USING_JUCE_NAMESPACE.
using namespace juce;
#endif
namespace ProjectInfo
{
const char* const projectName = JucePlugin_Name;
const char* const versionString = JucePlugin_VersionString;
const int versionNumber = JucePlugin_VersionCode;
}
#endif // __APPHEADERFILE_SGFP29__
+12
View File
@@ -0,0 +1,12 @@
Important Note!!
================
The purpose of this folder is to contain files that are auto-generated by the Introjucer,
and ALL files in this folder will be mercilessly DELETED and completely re-written whenever
the Introjucer saves your project.
Therefore, it's a bad idea to make any manual changes to the files in here, or to
put any of your own files in here if you don't want to lose them. (Of course you may choose
to add the folder's contents to your version-control system so that you can re-merge your own
modifications after the Introjucer has saved its changes).
Binary file not shown.
+291
View File
@@ -0,0 +1,291 @@
/*
==============================================================================
This is an automatically generated file created by the Jucer!
Creation date: 10 Aug 2012 1:11:16pm
Be careful when adding custom code to these files, as only the code within
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
and re-saved.
Jucer version: 1.12
------------------------------------------------------------------------------
The Jucer is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-6 by Raw Material Software ltd.
==============================================================================
*/
//[Headers] You can add your own extra header files here...
//[/Headers]
#include "ButtonLED.h"
//[MiscUserDefs] You can add your own user definitions and misc code here...
//[/MiscUserDefs]
//==============================================================================
ButtonLED::ButtonLED (const String& name)
: Button (L"Button LED"),
cachedImage_led_23_red_png (0),
cachedImage_led_23_red1_png (0),
triggeredOnMouseDown(0),
clickingTogglesState(0),
clickingLeftMouseButtonTogglesState(1),
clickingMiddleMouseButtonTogglesState(0),
clickingRightMouseButtonTogglesState(0)
{
cachedImage_led_23_red_png = ImageCache::getFromMemory (led_23_red_png, led_23_red_pngSize);
cachedImage_led_23_red1_png = ImageCache::getFromMemory (led_23_red1_png, led_23_red1_pngSize);
//[UserPreSize]
//[/UserPreSize]
setSize (32, 32);
//[Constructor] You can add your own custom stuff here..
setName(name);
//[/Constructor]
}
ButtonLED::~ButtonLED()
{
//[Destructor_pre]. You can add your own custom destruction code here..
//[/Destructor_pre]
//[Destructor]. You can add your own custom destruction code here..
//[/Destructor]
}
//==============================================================================
void ButtonLED::resized()
{
//[UserResized] Add your own custom resize handling here..
//[/UserResized]
}
/*
void ButtonLED::paintButton (Graphics& g, bool isMouseOverButton, bool isButtonDown)
{
if (getToggleState())
{
g.setColour (Colours::black);
g.drawImageWithin (cachedImage_led_23_red1_png,
0, 0, 32, 32,
RectanglePlacement::centred,
false);
}
else
{
g.setColour (Colours::black);
g.drawImageWithin (cachedImage_led_23_red_png,
0, 0, 32, 32,
RectanglePlacement::centred,
false);
}
}
*/
void ButtonLED::clicked()
{
//[UserCode_clicked] -- Add your code here...
//[/UserCode_clicked]
}
void ButtonLED::buttonStateChanged()
{
//[UserCode_buttonStateChanged] -- Add your code here...
//[/UserCode_buttonStateChanged]
}
void ButtonLED::mouseWheelMove(const MouseEvent &/*event*/, const MouseWheelDetails &/*wheel*/)
{
}
//[MiscUserCode] You can add your own definitions of your custom methods or any other code here...
bool ButtonLED::getClickingLeftMouseButtonTogglesState (void)
{
return clickingLeftMouseButtonTogglesState;
}
bool ButtonLED::getClickingMiddleMouseButtonTogglesState (void)
{
return clickingMiddleMouseButtonTogglesState;
}
bool ButtonLED::getClickingRightMouseButtonTogglesState (void)
{
return clickingRightMouseButtonTogglesState;
}
void ButtonLED::setClickingLeftMouseButtonTogglesState (bool value)
{
this ->clickingLeftMouseButtonTogglesState = value;
}
void ButtonLED::setClickingMiddleMouseButtonTogglesState (bool value)
{
this ->clickingMiddleMouseButtonTogglesState = value;
}
void ButtonLED::setClickingRightMouseButtonTogglesState (bool value)
{
this ->clickingRightMouseButtonTogglesState = value;
}
void ButtonLED::setTriggeredOnMouseDown (bool triggeredOnMouseDown)
{
Button::setTriggeredOnMouseDown(triggeredOnMouseDown);
}
void ButtonLED::setClickingTogglesState(bool clickingTogglesState)
{
this->clickingTogglesState = clickingTogglesState;
}
bool ButtonLED::getClickingTogglesState(void)
{
return this->clickingTogglesState;
}
void ButtonLED::clicked(const ModifierKeys &modifiers)
{
bool state;
state = getToggleState();
if (modifiers.isLeftButtonDown())
if (!clickingLeftMouseButtonTogglesState)
return;
if (modifiers.isMiddleButtonDown())
if (!clickingMiddleMouseButtonTogglesState)
return;
if (modifiers.isRightButtonDown())
if (!clickingRightMouseButtonTogglesState)
return;
if (clickingTogglesState)
setToggleState(!state, false);
}
void ButtonLED::paintButton (Graphics& g, bool /*isMouseOverButton*/, bool /*isButtonDown*/)
{
if (getToggleState())
{
g.setColour (Colours::black);
g.drawImageWithin (cachedImage_led_23_red1_png,
0, 0, getWidth(), getHeight(),
RectanglePlacement::centred,
false);
}
else
{
g.setColour (Colours::black);
g.drawImageWithin (cachedImage_led_23_red_png,
0, 0, getWidth(), getHeight(),
RectanglePlacement::centred,
false);
}
}
//[/MiscUserCode]
//==============================================================================
#if 0
/* -- Jucer information section --
This is where the Jucer puts all of its metadata, so don't change anything in here!
BEGIN_JUCER_METADATA
<JUCER_COMPONENT documentType="Button" className="ButtonLED" componentName="Button LED"
parentClasses="public Button" constructorParams="const String&amp; name"
variableInitialisers="" snapPixels="8" snapActive="1" snapShown="1"
overlayOpacity="0.330000013" fixedSize="0" initialWidth="32"
initialHeight="32">
<METHODS>
<METHOD name="clicked()"/>
<METHOD name="buttonStateChanged()"/>
</METHODS>
<BACKGROUND backgroundColour="0" buttonState="normal" enabled="1">
<IMAGE pos="0 0 32 32" resource="led_23_red_png" opacity="1" mode="1"/>
</BACKGROUND>
<BACKGROUND backgroundColour="0" buttonState="over" enabled="0"/>
<BACKGROUND backgroundColour="0" buttonState="down" enabled="0"/>
<BACKGROUND backgroundColour="0" buttonState="normal on" enabled="1">
<IMAGE pos="0 0 32 32" resource="led_23_red1_png" opacity="1" mode="1"/>
</BACKGROUND>
<BACKGROUND backgroundColour="0" buttonState="over on" enabled="0"/>
<BACKGROUND backgroundColour="0" buttonState="down on" enabled="0"/>
<BACKGROUND backgroundColour="0" buttonState="common background" enabled="1"/>
</JUCER_COMPONENT>
END_JUCER_METADATA
*/
#endif
//==============================================================================
// Binary resources - be careful not to edit any of these sections!
// JUCER_RESOURCE: led_23_red_png, 820, "C:/Users/jens/Pictures/led_23_red.png"
static const unsigned char resource_ButtonLED_led_23_red_png[] = { 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,32,0,0,0,32,8,6,0,0,0,115,122,122,244,0,0,0,1,115,82,71,66,0,174,206,28,233,0,0,0,
4,103,65,77,65,0,0,177,143,11,252,97,5,0,0,0,9,112,72,89,115,0,0,14,195,0,0,14,195,1,199,111,168,100,0,0,2,201,73,68,65,84,88,71,237,84,77,79,26,81,20,125,51,128,56,200,48,10,242,49,45,6,148,50,72,45,
137,74,213,64,210,16,43,196,208,32,154,74,109,218,212,29,38,74,237,166,11,235,166,254,0,22,46,92,179,169,174,26,211,96,93,117,221,244,159,116,103,210,29,173,216,152,156,222,59,66,226,162,59,199,38,77,
120,201,201,187,51,239,222,123,206,189,239,67,136,222,232,117,160,215,129,94,7,254,215,14,36,18,9,111,50,153,124,96,24,70,238,159,214,80,169,84,222,44,46,46,54,106,181,218,175,157,157,29,108,111,111,131,
190,207,253,126,255,161,162,40,183,43,38,151,203,45,111,109,109,181,26,141,6,154,205,38,78,78,154,56,58,58,66,189,94,71,181,90,133,174,235,63,169,27,43,183,210,145,124,62,159,221,216,216,104,29,28,28,
224,248,248,35,90,173,31,56,59,251,142,201,201,73,238,0,214,215,215,81,40,20,160,170,42,139,120,111,181,8,185,88,44,30,238,238,238,98,111,111,15,167,167,159,112,121,217,194,254,126,29,195,195,195,112,
58,157,112,187,221,72,167,211,136,70,163,32,242,15,4,217,74,17,246,181,181,181,246,230,230,38,150,150,150,48,59,59,131,233,233,105,208,190,131,246,29,146,36,193,227,81,77,17,154,166,241,119,155,200,251,
173,18,32,5,131,65,163,84,42,161,92,46,155,196,99,99,99,8,4,2,112,185,92,144,108,14,24,70,2,153,204,44,188,222,33,174,190,139,123,100,75,86,136,112,208,190,38,178,217,44,166,166,166,16,139,197,64,130,
224,86,61,144,6,52,40,129,48,50,243,5,100,30,229,232,16,222,185,46,96,142,200,29,86,8,112,201,178,60,154,74,165,218,76,30,10,133,160,122,60,176,15,250,209,63,18,135,158,158,67,118,245,41,50,165,34,84,
22,208,215,199,34,46,8,35,4,197,10,1,78,74,18,165,170,63,155,228,170,10,89,113,195,17,140,32,52,147,65,120,225,49,178,47,159,35,62,159,131,208,117,8,218,22,242,255,194,49,4,142,189,241,232,227,100,118,
187,125,153,200,207,109,202,0,132,234,131,8,142,64,142,39,32,167,82,38,132,97,116,5,240,1,92,237,8,224,216,27,15,62,205,119,9,51,66,150,223,9,215,96,91,120,67,16,209,81,136,241,113,136,137,137,171,153,
175,159,207,119,97,250,176,239,85,140,37,91,96,167,68,94,194,4,161,64,4,175,133,170,125,19,225,240,111,17,137,64,140,146,16,182,53,237,43,173,213,76,159,43,95,142,225,216,27,15,126,80,184,146,48,225,33,
225,9,225,25,225,133,176,217,222,154,130,132,120,213,249,199,107,236,195,190,28,99,217,99,100,163,100,30,66,164,67,144,167,185,68,88,233,128,237,133,206,26,251,176,175,37,213,119,219,199,15,10,39,228,
196,92,221,125,66,154,192,119,157,193,118,146,192,251,222,37,183,228,17,234,10,224,153,19,114,39,184,181,67,4,157,192,119,157,193,54,255,227,53,246,177,156,252,111,66,248,142,51,33,131,237,91,39,190,46,
162,103,247,58,96,89,7,254,0,38,229,208,224,232,174,221,11,0,0,0,0,73,69,78,68,174,66,96,130,0,0};
const char* ButtonLED::led_23_red_png = (const char*) resource_ButtonLED_led_23_red_png;
const int ButtonLED::led_23_red_pngSize = 820;
// JUCER_RESOURCE: led_23_red1_png, 1556, "C:/Users/jens/Pictures/led_23_red1.png"
static const unsigned char resource_ButtonLED_led_23_red1_png[] = { 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,32,0,0,0,32,8,6,0,0,0,115,122,122,244,0,0,0,1,115,82,71,66,0,174,206,28,233,0,0,
0,4,103,65,77,65,0,0,177,143,11,252,97,5,0,0,0,9,112,72,89,115,0,0,14,195,0,0,14,195,1,199,111,168,100,0,0,5,169,73,68,65,84,88,71,197,87,11,80,148,85,20,62,139,15,18,36,205,23,246,82,18,199,28,84,124,
101,78,22,154,142,212,48,105,54,49,162,77,106,84,44,67,142,137,174,38,141,137,173,248,66,69,99,65,217,101,97,5,97,137,76,5,241,177,147,47,124,84,12,96,234,16,249,200,199,84,128,89,12,54,129,153,186,66,
167,243,237,254,59,187,12,168,187,232,232,206,124,243,223,189,247,124,223,61,247,156,123,207,127,127,162,182,252,204,172,34,51,123,9,218,43,64,91,213,22,41,247,57,206,9,189,101,50,31,129,159,160,139,2,
180,209,135,49,56,229,229,190,240,189,44,157,19,119,82,38,237,38,79,127,193,83,130,103,21,160,141,62,140,193,25,216,62,0,71,204,220,78,132,58,10,58,11,158,80,38,121,70,158,207,9,158,23,12,82,128,54,250,
48,6,71,96,11,14,184,237,238,181,198,150,227,246,28,99,114,132,20,43,234,46,120,82,208,87,48,64,48,88,48,66,240,162,2,180,209,135,49,216,192,22,28,112,161,1,45,15,246,136,61,236,32,98,21,8,43,4,3,4,88,
105,176,96,148,224,21,193,4,5,104,163,15,99,176,129,45,56,224,66,3,90,110,238,11,251,228,29,4,216,84,93,5,8,105,31,1,86,135,9,176,234,177,130,80,193,36,5,104,163,15,99,176,129,45,56,224,66,3,90,208,188,
135,19,45,67,223,67,72,200,107,127,1,66,140,85,134,8,94,19,188,41,152,170,0,109,244,97,12,54,176,5,7,92,104,184,153,10,187,3,174,171,239,45,255,145,211,129,130,225,130,49,130,137,130,201,202,196,51,229,
9,192,17,244,97,12,54,176,5,7,92,104,184,70,225,14,123,193,89,92,28,187,30,155,232,105,65,160,178,34,132,247,85,65,152,32,92,149,125,235,189,246,250,63,230,119,72,253,45,78,254,207,64,159,50,6,27,216,
34,10,224,66,3,90,142,83,113,135,162,213,60,252,143,11,161,167,0,231,28,249,28,166,172,108,98,39,99,109,100,96,252,206,67,225,171,205,214,168,141,5,60,107,195,87,60,70,163,179,250,168,211,143,169,82,170,
163,92,162,0,14,184,208,128,22,52,239,114,34,236,14,160,120,60,38,64,133,235,37,112,132,127,164,180,67,186,166,94,212,76,209,26,111,36,237,40,102,243,225,147,156,127,172,130,51,247,31,231,21,249,7,57,
114,195,86,238,253,238,202,155,180,230,140,6,182,2,112,28,105,128,22,52,161,141,57,90,73,67,243,138,135,156,33,119,40,46,65,130,81,157,13,191,79,157,188,56,245,70,66,174,133,179,246,151,242,181,127,235,
249,207,134,191,57,104,237,81,126,93,119,128,103,164,236,226,80,109,14,251,69,44,191,73,186,234,8,112,20,46,52,28,251,224,46,21,178,249,6,68,37,195,57,238,39,24,76,57,77,163,135,44,48,238,139,94,151,205,
115,245,5,188,253,196,69,110,108,186,206,73,37,85,220,99,77,57,251,45,59,202,221,227,10,121,228,146,124,14,152,99,98,138,249,250,27,112,108,92,187,6,180,160,233,56,142,173,70,192,245,4,192,24,245,29,155,
104,8,25,235,95,158,16,187,214,26,161,53,240,248,181,22,30,170,175,224,96,253,143,220,99,221,9,246,91,85,206,222,203,75,185,95,82,9,251,125,178,151,187,104,138,88,165,206,179,82,90,237,56,27,215,174,1,
45,143,28,64,5,179,59,176,229,118,176,111,66,201,180,49,177,201,28,178,40,93,66,126,132,251,126,113,130,123,38,157,100,223,245,167,217,75,247,11,79,179,92,102,109,73,13,7,233,79,49,105,15,49,45,42,100,
250,188,100,42,184,46,14,64,211,237,8,56,29,48,93,31,214,241,211,125,211,131,230,108,226,192,185,153,220,119,213,17,246,151,149,251,232,46,178,42,163,150,123,110,187,202,218,74,65,197,21,126,169,232,28,
83,198,247,76,73,22,166,184,61,31,146,112,219,234,128,51,5,134,186,225,180,96,247,219,1,243,54,91,123,47,200,99,255,101,7,217,87,119,129,189,179,235,56,192,210,192,227,203,235,57,225,82,29,107,207,95,
230,62,187,43,152,204,135,153,210,10,111,211,66,203,20,50,92,69,65,106,83,10,156,155,48,165,102,4,205,43,120,171,91,108,206,119,254,241,22,246,75,252,129,85,250,106,238,181,243,47,142,168,104,224,119,
42,235,120,197,133,43,28,94,122,129,41,79,86,111,148,213,47,205,42,3,135,192,245,96,19,58,174,88,56,42,206,99,152,82,51,140,98,119,76,105,23,101,252,204,119,245,113,171,215,198,159,153,114,107,88,181,
187,150,125,14,93,225,78,251,126,229,142,69,103,152,190,44,99,202,60,192,148,188,205,74,234,180,120,112,196,1,164,192,163,99,216,178,16,25,174,14,150,20,132,209,7,233,106,138,49,153,200,120,214,74,5,85,
76,7,4,123,46,49,21,96,242,114,38,83,49,83,202,206,219,20,157,106,18,219,104,210,236,10,35,67,29,142,33,138,153,91,133,200,245,18,226,44,197,166,235,3,41,254,219,113,20,179,101,6,205,212,197,81,148,222,
64,169,71,206,81,209,233,70,218,46,57,207,147,201,51,138,27,73,155,127,150,222,215,25,108,54,176,5,7,92,15,75,49,210,208,252,101,148,211,216,159,146,206,191,64,11,247,78,38,245,230,24,154,149,186,148,
34,211,214,83,84,230,38,250,56,103,43,205,222,146,39,109,189,173,15,99,176,129,45,56,224,186,253,50,194,197,236,78,175,227,140,134,65,180,242,84,136,8,135,83,76,206,108,82,155,226,41,58,43,145,62,50,39,
219,128,182,122,243,18,138,201,157,109,179,129,173,177,30,247,69,15,94,199,78,7,92,239,130,246,11,73,110,83,127,210,203,113,76,172,28,79,139,139,195,73,83,164,166,249,133,26,201,243,98,27,236,237,40,219,
24,108,96,11,142,199,23,18,187,19,173,95,201,114,155,6,80,230,181,225,164,171,10,161,213,149,147,40,161,124,58,45,43,139,180,1,237,196,159,222,176,141,153,254,193,228,109,188,146,57,238,199,119,187,148,
230,254,55,148,178,111,141,150,13,54,86,28,10,181,1,109,244,97,236,190,47,165,173,167,226,33,95,203,157,145,120,68,31,38,174,159,42,143,244,211,172,117,71,30,242,199,105,107,31,118,15,240,243,252,127,
1,108,76,65,198,225,150,95,0,0,0,0,73,69,78,68,174,66,96,130,0,0};
const char* ButtonLED::led_23_red1_png = (const char*) resource_ButtonLED_led_23_red1_png;
const int ButtonLED::led_23_red1_pngSize = 1556;
+100
View File
@@ -0,0 +1,100 @@
/*
==============================================================================
This is an automatically generated file created by the Jucer!
Creation date: 10 Aug 2012 1:11:16pm
Be careful when adding custom code to these files, as only the code within
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
and re-saved.
Jucer version: 1.12
------------------------------------------------------------------------------
The Jucer is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-6 by Raw Material Software ltd.
==============================================================================
*/
#ifndef __JUCER_HEADER_BUTTONLED_BUTTONLED_B8510B75__
#define __JUCER_HEADER_BUTTONLED_BUTTONLED_B8510B75__
//[Headers] -- You can add your own extra header files here --
#include "../JuceLibraryCode/JuceHeader.h"
//[/Headers]
//==============================================================================
/**
//[Comments]
An auto-generated component, created by the Jucer.
Describe your class and how it works here!
//[/Comments]
*/
class ButtonLED : public Button
{
public:
//==============================================================================
ButtonLED (const String& name);
~ButtonLED();
//==============================================================================
//[UserMethods] -- You can add your own custom methods in this section.
void paintButton (Graphics& g, bool isMouseOverButton, bool isButtonDown);
void clicked(const ModifierKeys &modifiers);
void mouseWheelMove(const MouseEvent &event, const MouseWheelDetails &wheel);
void setTriggeredOnMouseDown (bool triggeredOnMouseDown);
bool getClickingTogglesState (void);
void setClickingTogglesState (bool clickingTogglesState);
bool getClickingLeftMouseButtonTogglesState (void);
bool getClickingMiddleMouseButtonTogglesState (void);
bool getClickingRightMouseButtonTogglesState (void);
void setClickingLeftMouseButtonTogglesState (bool value);
void setClickingMiddleMouseButtonTogglesState (bool value);
void setClickingRightMouseButtonTogglesState (bool value);
//[/UserMethods]
void resized();
void clicked();
void buttonStateChanged();
// Binary resources:
static const char* led_23_red_png;
static const int led_23_red_pngSize;
static const char* led_23_red1_png;
static const int led_23_red1_pngSize;
//==============================================================================
juce_UseDebuggingNewOperator
private:
//[UserVariables] -- You can add your own custom variables in this section.
bool triggeredOnMouseDown;
bool clickingTogglesState;
bool clickingLeftMouseButtonTogglesState;
bool clickingMiddleMouseButtonTogglesState;
bool clickingRightMouseButtonTogglesState;
//[/UserVariables]
//==============================================================================
Image cachedImage_led_23_red_png;
Image cachedImage_led_23_red1_png;
//==============================================================================
// (prevent copy constructor and operator= being generated..)
ButtonLED (const ButtonLED&);
const ButtonLED& operator= (const ButtonLED&);
};
#endif // __JUCER_HEADER_BUTTONLED_BUTTONLED_B8510B75__
+1422
View File
File diff suppressed because it is too large Load Diff
+252
View File
@@ -0,0 +1,252 @@
/*
==============================================================================
This file was generated by user!
==============================================================================
*/
#ifndef _JAYSYNTH_H_
#define _JAYSYNTH_H_
#include "../JuceLibraryCode/JuceHeader.h"
#include "synth_defs.h"
#include "param_scale.h"
#include "JaySynthVoice.h"
#include "JaySynthMonophonicMGR.h"
#define GET_NUM_VOICES max_num_voices
class JaySynthListener
{
public:
virtual void synthChanged(int /*type*/, void* /*pData*/) {};
};
class JaySynthThread : public Thread
{
public:
JaySynthThread(WaitableEvent *pEventRdy, voice_t *pVoices, int num_voices, int offset, int step);
~JaySynthThread();
void go(int len);
AudioSampleBuffer& getBuffer(void);
void run(void);
private:
AudioSampleBuffer *m_buffer;
voice_t *m_pVoices;
int m_num_voices;
int m_voice_offset, m_voice_step;
int m_sample_len;
WaitableEvent *m_pEventRun;
WaitableEvent *m_pEventRdy;
};
class JaySynth : public Synthesiser
{
public:
JaySynth(int num_voices, String pathToWaves);
~JaySynth();
void setSampleRate (synth_float_t sampleRate);
void setBufsize (int bufsize);
void setParam(int paramID, int voice);
void ClearControls(void);
void setControl(int paramID, synth_float_t value);
void setParameter(int paramID, synth_float_t value);
void setPerVoiceControl(int voice, int channel, int paramID, synth_float_t param);
synth_float_t getParameter(int paramID);
synth_float_t getVolume(void);
int lastPitchWheelValue, lastmidiChannel;
void handlePitchWheel (int midiChannel, int wheelValue);
void handleController (int midiChannel, int controllerNumber, int controllerValue);
void updateParameters(void);
void updateParameter(int paramID);
void humanizeModeChanged(void);
void humanizeVarianceChanged_VCO(void);
void humanizeVarianceChanged_VCF(void);
void humanizeVarianceChanged_ENV(void);
void unisonoModeChanged(void);
void humanizeParam (int paramID, bool useRandom, UINT32 random_seed, synth_float_t spread_min, synth_float_t variance);
bool isUnison(void)
{
return m_isUnison;
}
int getUnisonNumberOfVoices(void)
{
return unison_num_voices;
}
// ========================================================================
void advanceNextPossibleVoice(void);
int getNextPossibleVoice(void);
void advanceOldestVoice(void);
int getOldestVoice(void);
void Voicestart (JaySynthVoice* const voice,
SynthesiserSound* const sound,
const int midiChannel,
const int midiNoteNumber,
const float velocity, bool doTrigger);
void Voicestop (JaySynthVoice* voice, const bool allowTailOff);
int getNumVoicesPlaying (SynthesiserSound* soundToPlay);
void clearKeysPressed(void);
void setKeyPressed(int key, float vel);
void noteOn (int midiChannel, int midiNoteNumber, float velocity);
void noteOff (int midiChannel, int midiNoteNumber, bool allowTailOff);
void allNotesOff (int midiChannel, bool allowTailOff);
JaySynthVoice* getFreeVoice (SynthesiserSound* soundToPlay,
const bool stealIfNoneAvailable);
void handleMidiEvent (const MidiMessage& m);
void handleSustainPedal (int midiChannel, bool isDown);
void handleSostenutoPedal (int midiChannel, bool isDown);
void handleSoftPedal (int midiChannel, bool isDown);
void renderNextBlock (AudioSampleBuffer& outputAudio,
const MidiBuffer& inputMidi,
int startSample,
int numSamples);
int getNumVoices() const
{
return max_num_voices;
}
JaySynthVoice* getVoice (const int index) const
{
const ScopedLock sl (lock);
return voices [index];
}
void clearVoices()
{
const ScopedLock sl (lock);
voices.clear();
}
void addVoice (JaySynthVoice* const newVoice)
{
const ScopedLock sl (lock);
voices.add (newVoice);
}
void removeVoice (const int index)
{
const ScopedLock sl (lock);
voices.remove (index);
}
// ========================================================================
void addListener(JaySynthListener *listener)
{
listeners.add (listener);
}
enum
{
SYNTH_PER_VOICE_CONTROL_VELKEY = 0,
SYNTH_PER_VOICE_CONTROL_SIZE
};
enum
{
SYNTH_CHANGED_PARAM = 0,
SYNTH_CHANGED_MIDICC,
SYNTH_CHANGED_NUM_VOICES_PLAYING,
SYNTH_CHANGED_NOTE_PRESSED,
SYNTH_CHANGED_NOTE_RELEASED,
SYNTH_CHANGED_SIZE
};
typedef struct _smidiCC_info_t
{
int channel;
int ID;
synth_float_t value;
} midiCC_info_t;
typedef struct _smidi_note_info_t
{
int note;
synth_float_t velocity;
} midi_note_info_t;
midiCC_info_t* getLastMidiCC_infos(void)
{
return last_midiCC_info;
}
midiCC_info_t* getLastMidiCC_info(int controllerID)
{
if (controllerID < NUM_MIDI_CONTROLLERS)
return &last_midiCC_info[controllerID];
return NULL;
}
midi_note_info_t* getLastMidiNote_infos()
{
return &last_midi_note_info;
}
void setMidiCC_editBuffer(JaySynthMidiCC *pMidiCC)
{
pMidCC_editBuffer = pMidiCC;
}
typedef struct _sper_voice_control_t
{
synth_float_t ctrl[SYNTH_PER_VOICE_CONTROL_SIZE][SYNTH_NUM_PARAMS];
} per_voice_control_t;
//==============================================================================
private:
int m_num_audiothreads;
float sampleRate;
BigInteger sustainPedalsDown;
int paramID_changed, next_possible_voice, oldest_voice;
JaySynthMidiCC *pMidCC_editBuffer;
midiCC_info_t last_midiCC_info[NUM_MIDI_CONTROLLERS];
midiCC_info_t midiCC_info;
synth_float_t params[SYNTH_NUM_PARAMS];
synth_float_t controls[SYNTH_NUM_PARAMS];
per_voice_control_t *pPer_voice_controls;
synth_float_t master_volume;
synth_float_t humanize_var_vco;
synth_float_t humanize_var_vcf;
synth_float_t humanize_var_env;
voice_common_t synth_common;
param_info_t pb_range[VOICE_NUM_OSC];
bool m_doVcoRestartOnTrigger;
bool doHumanize, isHumanize;
bool m_doMonophon, m_isMonophon;
bool m_doUnison, m_isUnison;
bool m_doMonophonRetrigger;
int m_num_keys_pressed;
int m_num_keys_pressed_last;
int m_highest_key;
int m_highest_key_last;
int m_latest_key;
int m_latest_key_last;
int unison_num_voices;
int max_num_voices, total_num_voices;
param_info_t **humanize_voice_param;
ListenerList <JaySynthListener> listeners;
OwnedArray <JaySynthVoice> voices;
synth_float_t m_unisonGain;
midi_note_info_t *pCurrNoteInfos;
midi_note_info_t last_midi_note_info;
voice_t *m_pVoices;
JaySynthThread **m_ppAudioThread;
WaitableEvent *m_pEventAudioThreadRdy;
JaySynthMonophonicMGR m_monoMGR;
};
#endif // _JAYSYNTH_H_
File diff suppressed because it is too large Load Diff
+330
View File
@@ -0,0 +1,330 @@
/*
==============================================================================
This is an automatically generated file created by the Jucer!
Creation date: 31 Mar 2014 12:38:24pm
Be careful when adding custom code to these files, as only the code within
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
and re-saved.
Jucer version: 1.12
------------------------------------------------------------------------------
The Jucer is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-6 by Raw Material Software ltd.
==============================================================================
*/
#ifndef __JUCER_HEADER_JAYSYNTHAUDIOPROCESSOREDITOR_JAYSYNTHAUDIOPROCESSOREDITOR_1F0BC626__
#define __JUCER_HEADER_JAYSYNTHAUDIOPROCESSOREDITOR_JAYSYNTHAUDIOPROCESSOREDITOR_1F0BC626__
//[Headers] -- You can add your own extra header files here --
#include "../JuceLibraryCode/JuceHeader.h"
#include "PluginProcessor.h"
#include "ButtonLED.h"
#include "MidiCC_PopUp.h"
#include "VelKey_PopUp.h"
//[/Headers]
#include "ButtonLED.h"
//==============================================================================
/**
//[Comments]
An auto-generated component, created by the Jucer.
Describe your class and how it works here!
//[/Comments]
*/
class JaySynthAudioProcessorEditor : public AudioProcessorEditor,
public Timer,
public ButtonListener,
public ActionListener,
public MidiCC_PopUp_Listener,
public VelKey_PopUp_Listener,
public SliderListener,
public LabelListener,
public ComboBoxListener
{
public:
//==============================================================================
JaySynthAudioProcessorEditor (JaySynthAudioProcessor* ownerFilter, bool has_wt);
~JaySynthAudioProcessorEditor();
//==============================================================================
//[UserMethods] -- You can add your own custom methods in this section.
void timerCallback();
void update_sliders();
void paramUpdate(int paramID, bool doHostUpdate);
void buttonClicked (Button* buttonThatWasClicked);
void mouseDoubleClick (const MouseEvent &m);
void mouseDown (const MouseEvent &m);
void changeListenerCallback (ChangeBroadcaster* source);
void actionListenerCallback (const String &message);
void MidiCC_PopUp_event(int event);
void VelKey_PopUp_event(int event);
void MidiCC_PopUp_show(Component *componentThatWasClicked);
void VelKey_PopUp_show(Component *componentThatWasClicked);
int ModSrc0_findByName(String name);
int ModSrc1_findByName(String name);
int ModSrcOP_findByName(String name);
int ModSrc1_CB_getIndex(int srcID, int opID);
//[/UserMethods]
void paint (Graphics& g);
void resized();
void sliderValueChanged (Slider* sliderThatWasMoved);
void labelTextChanged (Label* labelThatHasChanged);
void comboBoxChanged (ComboBox* comboBoxThatHasChanged);
// Binary resources:
static const char* led_23_red_png;
static const int led_23_red_pngSize;
static const char* led_23_red1_png;
static const int led_23_red1_pngSize;
//==============================================================================
juce_UseDebuggingNewOperator
private:
//[UserVariables] -- You can add your own custom variables in this section.
JaySynthAudioProcessor* getProcessor() const
{
return static_cast <JaySynthAudioProcessor*> (getAudioProcessor());
}
TooltipWindow *m_tooltipWindow;
MidiCC_PopUp *m_MidiCC_PopUp;
VelKey_PopUp *m_VelKey_PopUp;
String m_mod_src0_names[VOICE_NUM_MOD_SOURCES_0];
String m_mod_src1_names[VOICE_NUM_MOD_SOURCES_1];
String m_mod_src_op_names[VOICE_NUM_MOD_OPS];
String m_mod_src0_cb_names[VOICE_NUM_MOD_SOURCES_0];
String m_mod_src1_cb_names[(VOICE_NUM_MOD_SOURCES_1-1)*VOICE_NUM_MOD_OPS + 1];
//[/UserVariables]
//==============================================================================
Label* m_label_colon;
Slider* m_slider_master_volume;
Slider* m_slider_vcf_f;
Slider* m_slider_vcf_q;
Slider* m_slider_osc0_det;
Slider* m_slider_osc1_det;
Slider* m_slider_osc0_transpose;
Slider* m_slider_osc1_transpose;
Slider* m_slider_vca_env_attack;
Slider* m_slider_vca_env_decay;
Slider* m_slider_vca_env_release;
Slider* m_slider_vca_env_sustain;
Slider* m_slider_vcf_env_attack;
Slider* m_slider_vcf_env_decay;
Slider* m_slider_vcf_env_release;
Slider* m_slider_vcf_env_sustain;
Slider* m_slider_vcf_env_amount;
Label* m_label_vcf_env_attack;
Label* m_label_vcf_f;
Label* m_label_vca_env_attack;
Label* m_label_vca_env_decay;
Label* m_label_vca_env_sustain;
Label* m_label_vca_env_release;
Label* m_label_vcf_env_decay;
Label* m_label_vcf_env_sustain;
Label* m_label_vcf_env_release;
Label* m_label_vcf_q;
Label* m_label_vcf_env_amount;
Label* m_label_master_volume;
Label* m_label_osc0_transpose;
Label* m_label_osc1_transpose;
Label* m_label_osc0_det;
Label* m_label_osc1_det;
Slider* m_slider_vca_env_amount;
Label* m_label_vca_env_amount;
Slider* m_slider_osc0_dutycycle;
Slider* m_slider_osc1_dutycycle;
Label* m_label_osc0_dutycycle;
Label* m_label_osc1_dutycycle;
Slider* m_slider_lfo0_speed;
Slider* m_slider_osc1_fm_amt0;
Slider* m_slider_osc0_fm_amt0;
Label* m_label_lfo0_speed;
Label* m_label_osc0_fm_amt0;
Label* m_label_osc1_fm_amt0;
Slider* m_slider_vcf_f_amt0;
Label* m_label_vcf_f_amt0;
Slider* m_slider_lfo1_speed;
Label* m_label_lfo1_speed;
ComboBox* m_comboBox_osc0_shape;
ComboBox* m_comboBox_osc1_shape;
ComboBox* m_comboBox_lfo0_shape;
ComboBox* m_comboBox_lfo1_shape;
Slider* m_slider_lfo2_speed;
Slider* m_slider_lfo3_speed;
ComboBox* m_comboBox_lfo2_shape;
ComboBox* m_comboBox_lfo3_shape;
Label* m_label_lfo2_speed;
Label* m_label_lfo3_speed;
ComboBox* m_comboBox_vcf_f_src0;
ComboBox* m_comboBox_osc0_fm_src0;
ComboBox* m_comboBox_osc1_fm_src0;
Slider* m_slider_vca_am_amt0;
Label* m_label_vca_am_amt0;
ComboBox* m_comboBox_vca_am_src0;
Slider* m_slider_vca_pan_amt0;
Label* m_label_vca_pan_amt0;
ComboBox* m_comboBox_vca_pan_src0;
Label* m_label_synth_name;
Label* m_label_synth_version;
ComboBox* m_comboBox_vcf_type;
Slider* m_slider_lfo1_smooth;
Label* m_label_lfo1_smooth;
Slider* m_slider_lfo0_smooth;
Label* m_label_lfo0_smooth;
Slider* m_slider_lfo2_smooth;
Label* m_label_lfo2_smooth;
Slider* m_slider_lfo3_smooth;
Label* m_label_lfo3_smooth;
Slider* m_slider_osc0_pwm_amt0;
Label* m_label_osc0_pwm_amt0;
Slider* m_slider_osc1_pwm_amt0;
Label* m_label_osc1_pwm_amt0;
ComboBox* m_comboBox_osc0_pwm_src0;
ComboBox* m_comboBox_osc1_pwm_src0;
Slider* m_slider_osc0_level;
Label* m_label_osc0_level;
Slider* m_slider_osc1_level;
Label* m_label_osc1_level;
Slider* m_slider_noise_level;
Label* m_label_noise_level;
ComboBox* m_comboBox_noise_shape;
ButtonLED* m_btn_noise_enable_led;
ButtonLED* m_btn_osc0_enable;
ButtonLED* m_btn_osc1_enable;
Label* m_label_patch_name;
TextButton* m_button_patch_incr;
TextButton* m_button_patch_decr;
Label* m_label_patch_number;
Label* m_label_osc1_pb_min;
Label* m_label_osc1_pb_max;
Label* m_label_osc0_pb_max;
Label* m_label_osc0_pb_min;
Slider* m_slider_master_tune;
Label* m_label_master_tune;
ToggleButton* m_button_humanize_enable;
ComboBox* m_comboBox_vcf_order;
Slider* m_slider_portamento_time;
Label* m_label_portamento_time;
ToggleButton* m_button_unisono_enable;
Slider* m_slider_humanize_var_vco;
Slider* m_slider_voice_pan_spread;
Label* m_label_voice_pan_spread;
Slider* m_slider_humanize_var_vcf;
Slider* m_slider_humanize_var_env;
Label* m_label_unisono_num_voices;
ToggleButton* m_button_osc0_restart_enable;
ToggleButton* m_button_osc1_restart_enable;
ToggleButton* m_button_mono_enable;
ComboBox* m_comboBox_osc1_fm_src1;
ComboBox* m_comboBox_osc1_pwm_src1;
ComboBox* m_comboBox_osc0_fm_src1;
ComboBox* m_comboBox_osc0_pwm_src1;
ComboBox* m_comboBox_osc1_am_src0;
ComboBox* m_comboBox_osc1_am_src1;
Slider* m_slider_osc1_am_amt0;
Label* m_label_osc1_am_amt0;
ComboBox* m_comboBox_osc0_am_src0;
ComboBox* m_comboBox_osc0_am_src1;
Slider* m_slider_osc0_am_amt0;
Label* m_label_osc0_am_amt0;
Slider* m_slider_env2_attack;
Slider* m_slider_env2_decay;
Slider* m_slider_env2_release;
Slider* m_slider_env2_sustain;
Label* m_label_env2_attack;
Label* m_label_env2_decay;
Label* m_label_env2_sustain;
Label* m_label_env2_release;
Slider* m_slider_env3_attack;
Slider* m_slider_env3_decay;
Slider* m_slider_env3_release;
Slider* m_slider_env3_sustain;
Label* m_label_env3_attack;
Label* m_label_env3_decay;
Label* m_label_env3_sustain;
Label* m_label_env3_release;
ComboBox* m_comboBox_vcf_f_src1;
Slider* m_slider_vcf_q_amt0;
Label* m_label_vcf_q_amt0;
ComboBox* m_comboBox_vcf_q_src0;
ComboBox* m_comboBox_vcf_q_src1;
Label* m_label_humanize_var_vco;
Label* m_label_humanize_var_vcf;
Label* m_label_humanize_var_env;
ButtonLED* m_btn_limiter_led;
Label* m_label_limiter_led;
Slider* m_slider_lfo0_delay;
Label* m_label_lfo0_delay;
Slider* m_slider_lfo0_attack;
Label* m_label_lfo0_attack;
Slider* m_slider_lfo1_delay;
Label* m_label_lfo1_delay;
Slider* m_slider_lfo1_attack;
Label* m_label_lfo1_attack;
Slider* m_slider_lfo2_delay;
Label* m_label_lfo2_delay;
Slider* m_slider_lfo2_attack;
Label* m_label_lfo2_attack;
Slider* m_slider_lfo3_delay;
Label* m_label_lfo3_delay;
Slider* m_slider_lfo3_attack;
Label* m_label_lfo3_attack;
ToggleButton* m_button_lfo0_restart_enable;
ToggleButton* m_button_lfo0_individual_enable;
Slider* m_slider_lfo0_symmetry;
Label* m_label_lfo0_symmetry;
Slider* m_slider_lfo1_symmetry;
Label* m_label_lfo1_symmetry;
ToggleButton* m_button_lfo1_restart_enable;
ToggleButton* m_button_lfo1_individual_enable;
ToggleButton* m_button_lfo2_restart_enable;
ToggleButton* m_button_lfo2_individual_enable;
Slider* m_slider_lfo2_symmetry;
Label* m_label_lfo2_symmetry;
Slider* m_slider_lfo3_symmetry;
Label* m_label_lfo3_symmetry;
ToggleButton* m_button_lfo3_restart_enable;
ToggleButton* m_button_lfo3_individual_enable;
Slider* m_slider_osc0_fm_amt1;
Label* m_label_osc0_fm_amt1;
Slider* m_slider_osc0_pwm_amt1;
Label* m_label_osc0_pwm_amt1;
Slider* m_slider_osc0_am_amt1;
Label* m_label_osc0_am_amt1;
Slider* m_slider_osc1_fm_amt1;
Label* m_label_osc1_fm_amt1;
Slider* m_slider_osc1_pwm_amt1;
Label* m_label_osc1_pwm_amt1;
Slider* m_slider_osc1_am_amt1;
Label* m_label_osc1_am_amt1;
Slider* m_slider_vcf_f_amt1;
Label* m_label_vcf_f_amt1;
Slider* m_slider_vcf_q_amt1;
Label* m_label_vcf_q_amt1;
ToggleButton* m_button_mono_retrigger;
Label* m_label_max_num_voices;
Label* m_label_num_voices_playing;
//==============================================================================
// (prevent copy constructor and operator= being generated..)
JaySynthAudioProcessorEditor (const JaySynthAudioProcessorEditor&);
const JaySynthAudioProcessorEditor& operator= (const JaySynthAudioProcessorEditor&);
};
#endif // __JUCER_HEADER_JAYSYNTHAUDIOPROCESSOREDITOR_JAYSYNTHAUDIOPROCESSOREDITOR_1F0BC626__
+741
View File
@@ -0,0 +1,741 @@
/*
==============================================================================
This file was auto-generated!
It contains the basic startup code for a Juce application.
==============================================================================
*/
#include "../JuceLibraryCode/JuceHeader.h"
#include "synth_defs.h"
#include "JaySynthMidiCC.h"
//==============================================================================
JaySynthMidiCC::JaySynthMidiCC()
{
int i;
param_info_t *pConstraints;
for (i=0; i < SYNTH_NUM_PARAMS; i++)
{
pConstraints = getParamInfo(i);
// Constraints
paramInfoInit(&midiCC_containers[i].constraints, i, pConstraints->pName);
paramInfoSet(&midiCC_containers[i].constraints,
/*base*/pConstraints->base,
/*kexp*/pConstraints->kexp,
/*scenter*/pConstraints->scenter,
/*pmin*/pConstraints->pmin,
/*pcenter*/pConstraints->pcenter,
/*pmax*/pConstraints->pmax,
/*pinterval*/pConstraints->pinterval);
// Control
paramInfoInit(&midiCC_containers[i].control, i, pConstraints->pName);
paramInfoSet(&midiCC_containers[i].control,
/*base*/1,
/*kexp*/1,
/*scenter*/0.5,
/*pmin*/0,
/*pcenter*/-1E18,
/*pmax*/pConstraints->pmax,
/*pinterval*/pConstraints->pinterval);
// Parameters
paramInfoInit(&midiCC_containers[i].param, i, pConstraints->pName);
paramInfoSet(&midiCC_containers[i].param,
/*base*/pConstraints->base,
/*kexp*/pConstraints->kexp,
/*scenter*/pConstraints->scenter,
/*pmin*/pConstraints->pmin,
/*pcenter*/-1E18,
/*pmax*/pConstraints->pmax,
/*pinterval*/pConstraints->pinterval);
midiCC_containers[i].doChangeParameter = false;
midiCC_containers[i].controllerID = 0;
midiCC_containers[i].isAssigned = false;
midiCC_containers[i].doApplyOnPatchInit = false;
// Velocity
paramInfoInit(&midiCC_containers[i].curve_vel, i, pConstraints->pName);
paramInfoSet(&midiCC_containers[i].curve_vel,
/*base*/exp(1.0),
/*kexp*/0,
/*scenter*/0.0,
/*pmin*/0,
/*pcenter*/-1E18,
/*pmax*/1,
/*pinterval*/0);
// Key follow
paramInfoInit(&midiCC_containers[i].curve_key, i, pConstraints->pName);
paramInfoSet(&midiCC_containers[i].curve_key,
/*base*/exp(1.0),
/*kexp*/0,
/*scenter*/0.0,
/*pmin*/0,
/*pcenter*/-1E18,
/*pmax*/1,
/*pinterval*/0);
midiCC_containers[i].isVelAssigned = false;
midiCC_containers[i].isKeyAssigned = false;
midiCC_containers[i].velKeyCombineOP = VELKEY_OP_ADD;
isModified = false;
paramNamedValueSet.set(toParameterNameXML(String(pConstraints->pName)), var(i));
}
}
JaySynthMidiCC::~JaySynthMidiCC()
{
int i;
for (i=0; i < SYNTH_NUM_PARAMS; i++)
{
paramInfoFree(&midiCC_containers[i].constraints);
paramInfoFree(&midiCC_containers[i].control);
paramInfoFree(&midiCC_containers[i].param);
paramInfoFree(&midiCC_containers[i].curve_vel);
paramInfoFree(&midiCC_containers[i].curve_key);
}
for (i=0; i < NUM_MIDI_CONTROLLERS; i++)
removeDestinations(i);
}
JaySynthMidiCC& JaySynthMidiCC::operator= (JaySynthMidiCC& other)
{
if (this != &other)
{
this->copyMidiCC(&other);
}
return *this;
}
void JaySynthMidiCC::copyMidiCC(JaySynthMidiCC *pSrc)
{
int i;
midiCC_container_t *pMidiContainerSrc, *pMidiContainerDst;
for (i=0; i < NUM_MIDI_CONTROLLERS; i++)
removeDestinations(i);
pMidiContainerSrc = pSrc->midiCC_containers;
pMidiContainerDst = this->midiCC_containers;
for (i=0; i < SYNTH_NUM_PARAMS; i++)
{
paramInfoCopy(&pMidiContainerDst[i].constraints, &pMidiContainerSrc[i].constraints);
paramInfoCopy(&pMidiContainerDst[i].control, &pMidiContainerSrc[i].control);
paramInfoCopy(&pMidiContainerDst[i].param, &pMidiContainerSrc[i].param);
pMidiContainerDst[i].doChangeParameter = pMidiContainerSrc[i].doChangeParameter;
pMidiContainerDst[i].doApplyOnPatchInit = pMidiContainerSrc[i].doApplyOnPatchInit;
pMidiContainerDst[i].controllerID = pMidiContainerSrc[i].controllerID;
pMidiContainerDst[i].isAssigned = 0;
if (pMidiContainerSrc[i].isAssigned)
{
add(&pMidiContainerDst[i], pMidiContainerSrc[i].controllerID);
}
}
for (i=0; i < SYNTH_NUM_PARAMS; i++)
{
paramInfoCopy(&pMidiContainerDst[i].curve_vel, &pMidiContainerSrc[i].curve_vel);
paramInfoCopy(&pMidiContainerDst[i].curve_key, &pMidiContainerSrc[i].curve_key);
pMidiContainerDst[i].isVelAssigned = pMidiContainerSrc[i].isVelAssigned;
pMidiContainerDst[i].isKeyAssigned = pMidiContainerSrc[i].isKeyAssigned;
pMidiContainerDst[i].velKeyCombineOP = pMidiContainerSrc[i].velKeyCombineOP;
}
isModified = false;
}
bool JaySynthMidiCC::isMidiCCmodified(void)
{
return isModified;
}
JaySynthMidiCC* JaySynthMidiCC::getMidiCC(void)
{
return this;
}
const String JaySynthMidiCC::toParameterNameXML (String name)
{
name = name.removeCharacters (String("."));
name = name.replaceCharacter (' ','_');
return name;
}
int JaySynthMidiCC::findParamID_byName(String name)
{
return (int)paramNamedValueSet.getWithDefault (toParameterNameXML(name), var(-1));
}
void JaySynthMidiCC::exportXML(String name)
{
File file(name);
XmlElement xml ("JSYNTH_MIDICC_TABLE_FILE");
exportXML(&xml);
file.create();
xml.writeToFile (/*const File &destinationFile*/file, /*const String &dtdToUse*/"JSYNTH_MIDICC_TABLE_FILE" /*, const String &encodingType="UTF-8", int lineWrapLength=60*/);
}
void JaySynthMidiCC::exportXML(XmlElement *pXML_doc)
{
int paramID;
midiCC_container_t *pMidiContainer;
XmlElement *pXML, *pXML_root, *pXML_PARAM, *pXML_PARAM_INFO;
// Store controller and slider infos
pXML_root = pXML_doc->createNewChildElement (String("JSYNTH_MIDICONTROLLER_TABLE"));
pXML = pXML_root->createNewChildElement (String("TARGETS"));
for (paramID=0; paramID < SYNTH_NUM_PARAMS; paramID++)
{
pMidiContainer = &midiCC_containers[paramID];
pXML_PARAM = pXML->createNewChildElement (String("PARAM_") + String(paramID));
pXML_PARAM->setAttribute ("NAME", toParameterNameXML(pMidiContainer->constraints.pName));
pXML_PARAM->setAttribute ("IS_ASSIGNED", pMidiContainer->isAssigned);
pXML_PARAM->setAttribute ("IS_ABSOLUTE", pMidiContainer->doChangeParameter);
pXML_PARAM->setAttribute ("DO_APPLY_ON_PATCH_INIT", pMidiContainer->doApplyOnPatchInit);
pXML_PARAM->setAttribute ("CONTROLLER_ID", pMidiContainer->controllerID);
pXML_PARAM->setAttribute ("IS_VELOCITY_ASSIGNED", pMidiContainer->isVelAssigned);
pXML_PARAM->setAttribute ("IS_KEYFOLLOW_ASSIGNED", pMidiContainer->isKeyAssigned);
pXML_PARAM->setAttribute ("VELKEY_COMBINE_OP", pMidiContainer->velKeyCombineOP);
pXML_PARAM_INFO = pXML_PARAM->createNewChildElement (String("RELATIVE"));
// pXML_PARAM_INFO->setAttribute ("BASE", String(pMidiContainer->control.base, 10));
// pXML_PARAM_INFO->setAttribute ("KEXP", String(pMidiContainer->control.kexp, 10));
// pXML_PARAM_INFO->setAttribute ("SCENTER", String(pMidiContainer->control.scenter, 10));
pXML_PARAM_INFO->setAttribute ("PMIN", String(pMidiContainer->control.pmin, 10));
pXML_PARAM_INFO->setAttribute ("PMAX", String(pMidiContainer->control.pmax, 10));
// pXML_PARAM_INFO->setAttribute ("PINTERVAL", String(pMidiContainer->control.pinterval, 10));
pXML_PARAM_INFO = pXML_PARAM->createNewChildElement (String("ABSOLUTE"));
// pXML_PARAM_INFO->setAttribute ("BASE", String(pMidiContainer->param.base, 10));
// pXML_PARAM_INFO->setAttribute ("KEXP", String(pMidiContainer->param.kexp, 10));
// pXML_PARAM_INFO->setAttribute ("SCENTER", String(pMidiContainer->param.scenter, 10));
pXML_PARAM_INFO->setAttribute ("PMIN", String(pMidiContainer->param.pmin, 10));
pXML_PARAM_INFO->setAttribute ("PMAX", String(pMidiContainer->param.pmax, 10));
// pXML_PARAM_INFO->setAttribute ("PINTERVAL", String(pMidiContainer->param.pinterval, 10));
pXML_PARAM_INFO = pXML_PARAM->createNewChildElement (String("VELOCITY_CURVE"));
// pXML_PARAM_INFO->setAttribute ("BASE", String(pMidiContainer->curve_vel.base, 10));
pXML_PARAM_INFO->setAttribute ("KEXP", String(pMidiContainer->curve_vel.kexp, 10));
pXML_PARAM_INFO->setAttribute ("SCENTER", String(pMidiContainer->curve_vel.scenter, 10));
pXML_PARAM_INFO->setAttribute ("PMIN", String(pMidiContainer->curve_vel.pmin, 10));
pXML_PARAM_INFO->setAttribute ("PMAX", String(pMidiContainer->curve_vel.pmax, 10));
pXML_PARAM_INFO->setAttribute ("PINTERVAL", String(pMidiContainer->curve_vel.pinterval, 10));
pXML_PARAM_INFO = pXML_PARAM->createNewChildElement (String("KEYFOLLOW_CURVE"));
// pXML_PARAM_INFO->setAttribute ("BASE", String(pMidiContainer->curve_key.base, 10));
pXML_PARAM_INFO->setAttribute ("KEXP", String(pMidiContainer->curve_key.kexp, 10));
pXML_PARAM_INFO->setAttribute ("SCENTER", String(pMidiContainer->curve_key.scenter, 10));
pXML_PARAM_INFO->setAttribute ("PMIN", String(pMidiContainer->curve_key.pmin, 10));
pXML_PARAM_INFO->setAttribute ("PMAX", String(pMidiContainer->curve_key.pmax, 10));
pXML_PARAM_INFO->setAttribute ("PINTERVAL", String(pMidiContainer->curve_key.pinterval, 10));
}
/*
{
int i, controllerID, numDst;
XmlElement *pXML_dst, *pXML_MIDICC;
// todo: romove that in future versions
pXML = pXML_root->createNewChildElement (String("CONTROLLERS"));
// Store MIDI controller assignments
for (controllerID=0; controllerID < NUM_MIDI_CONTROLLERS; controllerID++)
{
pXML_MIDICC = pXML->createNewChildElement (String("MIDICC_") + String(controllerID));
pXML_MIDICC->setAttribute ("ID", controllerID);
pXML_dst = pXML_MIDICC->createNewChildElement (String("TARGETS"));
numDst = getNumDestinations(controllerID);
for (i=0; i < numDst; i++)
{
pMidiContainer = getDestination(controllerID, i);
pXML_dst->setAttribute (String("PARAM") + String(pMidiContainer->constraints.id), pMidiContainer->constraints.pName);
}
}
}
// todo: romove that in future versions
*/
}
int JaySynthMidiCC::importXML(String name)
{
File file(name);
XmlDocument xml(file);
ScopedPointer<XmlElement> pXML_root (xml.getDocumentElement());
return importXML(pXML_root);
}
int JaySynthMidiCC::importXML(XmlElement *pXML_doc)
{
int i, paramID;
midiCC_container_t *pMidiContainer;
XmlElement *pXML, *pXML_root, *pXML_PARAM, *pXML_PARAM_INFO;
for (i=0; i < NUM_MIDI_CONTROLLERS; i++)
removeDestinations(i);
pXML_root = pXML_doc->getChildByName ("JSYNTH_MIDICONTROLLER_TABLE");
// make sure that it's actually our type of XML object..
if (pXML_root)
{
pXML = pXML_root->getFirstChildElement();
while(pXML)
{
pXML_PARAM = pXML->getFirstChildElement();
while(pXML_PARAM)
{
paramID = findParamID_byName(pXML_PARAM->getStringAttribute("NAME"));
if (paramID < 0)
{
pXML_PARAM = pXML_PARAM->getNextElement();
continue;
}
pMidiContainer = &midiCC_containers[paramID];
pMidiContainer->doChangeParameter = pXML_PARAM->getIntAttribute("IS_ABSOLUTE", pXML_PARAM->getIntAttribute("DO_CHANGE_PARAMETER", 0)) != 0;
pMidiContainer->doApplyOnPatchInit = pXML_PARAM->getIntAttribute("DO_APPLY_ON_PATCH_INIT", 0) != 0;
pMidiContainer->isVelAssigned = pXML_PARAM->getIntAttribute("IS_VELOCITY_ASSIGNED", 0) != 0;
pMidiContainer->isKeyAssigned = pXML_PARAM->getIntAttribute("IS_KEYFOLLOW_ASSIGNED", 0) != 0;
pMidiContainer->velKeyCombineOP = pXML_PARAM->getIntAttribute("VELKEY_COMBINE_OP", VELKEY_OP_ADD);
pXML_PARAM_INFO = pXML_PARAM->getChildByName(String("RELATIVE"));
if (pXML_PARAM_INFO)
{
// pMidiContainer->control.base = pXML_PARAM_INFO->getDoubleAttribute("BASE", pMidiContainer->constraints.base);
// pMidiContainer->control.kexp = pXML_PARAM_INFO->getDoubleAttribute("KEXP", pMidiContainer->constraints.kexp);
// pMidiContainer->control.scenter = pXML_PARAM_INFO->getDoubleAttribute("SCENTER", pMidiContainer->constraints.scenter);
pMidiContainer->control.pmin = pXML_PARAM_INFO->getDoubleAttribute("PMIN", pMidiContainer->constraints.pmin);
pMidiContainer->control.pmax = pXML_PARAM_INFO->getDoubleAttribute("PMAX", pMidiContainer->constraints.pmax);
// pMidiContainer->control.pinterval = pXML_PARAM_INFO->getDoubleAttribute("PINTERVAL", pMidiContainer->constraints.pinterval);
}
pXML_PARAM_INFO = pXML_PARAM->getChildByName(String("ABSOLUTE"));
if (pXML_PARAM_INFO)
{
// pMidiContainer->param.base = pXML_PARAM_INFO->getDoubleAttribute("BASE", pMidiContainer->constraints.base);
// pMidiContainer->param.kexp = pXML_PARAM_INFO->getDoubleAttribute("KEXP", pMidiContainer->constraints.kexp);
// pMidiContainer->param.scenter = pXML_PARAM_INFO->getDoubleAttribute("SCENTER", pMidiContainer->constraints.scenter);
pMidiContainer->param.pmin = pXML_PARAM_INFO->getDoubleAttribute("PMIN", pMidiContainer->constraints.pmin);
pMidiContainer->param.pmax = pXML_PARAM_INFO->getDoubleAttribute("PMAX", pMidiContainer->constraints.pmax);
// pMidiContainer->param.pinterval = pXML_PARAM_INFO->getDoubleAttribute("PINTERVAL", pMidiContainer->constraints.pinterval);
}
pXML_PARAM_INFO = pXML_PARAM->getChildByName(String("VELOCITY_CURVE"));
if (pXML_PARAM_INFO)
{
// pMidiContainer->curve_vel.base = pXML_PARAM_INFO->getDoubleAttribute("BASE", exp(1.0));
pMidiContainer->curve_vel.kexp = pXML_PARAM_INFO->getDoubleAttribute("KEXP", 0);
pMidiContainer->curve_vel.scenter = pXML_PARAM_INFO->getDoubleAttribute("SCENTER", 0.5);
pMidiContainer->curve_vel.pmin = pXML_PARAM_INFO->getDoubleAttribute("PMIN", 0);
pMidiContainer->curve_vel.pmax = pXML_PARAM_INFO->getDoubleAttribute("PMAX", 1);
// pMidiContainer->curve_vel.pinterval = pXML_PARAM_INFO->getDoubleAttribute("PINTERVAL", 0);
}
pXML_PARAM_INFO = pXML_PARAM->getChildByName(String("KEYFOLLOW_CURVE"));
if (pXML_PARAM_INFO)
{
// pMidiContainer->curve_key.base = pXML_PARAM_INFO->getDoubleAttribute("BASE", exp(1.0));
pMidiContainer->curve_key.kexp = pXML_PARAM_INFO->getDoubleAttribute("KEXP", 0);
pMidiContainer->curve_key.scenter = pXML_PARAM_INFO->getDoubleAttribute("SCENTER", 0.5);
pMidiContainer->curve_key.pmin = pXML_PARAM_INFO->getDoubleAttribute("PMIN", 0);
pMidiContainer->curve_key.pmax = pXML_PARAM_INFO->getDoubleAttribute("PMAX", 1);
// pMidiContainer->curve_key.pinterval = pXML_PARAM_INFO->getDoubleAttribute("PINTERVAL", 0);
}
if (pXML_PARAM->getIntAttribute("IS_ASSIGNED", 0))
add(pMidiContainer, pXML_PARAM->getIntAttribute("CONTROLLER_ID", 0));
pXML_PARAM = pXML_PARAM->getNextElement();
}
// todo: romove that in future versions
{
int controllerID;
XmlElement *pXML_MIDICC, *pXML_DST;
pXML = pXML->getNextElement();
while(pXML)
{
pXML_MIDICC = pXML->getFirstChildElement();
while(pXML_MIDICC)
{
controllerID = pXML_MIDICC->getIntAttribute("ID");
pXML_DST = pXML_MIDICC->getFirstChildElement();
if (pXML_DST)
{
for (i=0; i < pXML_DST->getNumAttributes(); i++)
{
paramID = findParamID_byName(pXML_DST->getAttributeValue(i));
if (paramID < 0)
break;
pMidiContainer = &midiCC_containers[paramID];
add(pMidiContainer, controllerID);
}
}
pXML_MIDICC = pXML_MIDICC->getNextElement();
}
pXML = pXML->getNextElement();
}
}
// todo: romove that in future versions
}
}
isModified = false;
return 0;
}
void JaySynthMidiCC::add(midiCC_container_t *pObj, int controllerID)
{
if (controllerID >= NUM_MIDI_CONTROLLERS)
return;
remove(pObj, pObj->controllerID);
if (midiCC_dest[controllerID].contains(pObj))
return;
pObj->isAssigned = 1;
pObj->controllerID = controllerID;
midiCC_dest[controllerID].append(pObj);
isModified = true;
}
void JaySynthMidiCC::remove(midiCC_container_t *pObj, int controllerID)
{
if (controllerID >= NUM_MIDI_CONTROLLERS)
return;
pObj->isAssigned = 0;
if (midiCC_dest[controllerID].contains(pObj))
{
midiCC_dest[controllerID].remove(pObj);
}
isModified = true;
}
struct midiCC_container_t* JaySynthMidiCC::getAtParamID(int paramID)
{
if (paramID >= SYNTH_NUM_PARAMS)
return NULL;
return &midiCC_containers[paramID];
}
int JaySynthMidiCC::getNumDestinations(int controllerID)
{
if (controllerID >= NUM_MIDI_CONTROLLERS)
return 0;
return midiCC_dest[controllerID].size();
}
void JaySynthMidiCC::removeDestinations(int controllerID)
{
int i;
if (controllerID >= NUM_MIDI_CONTROLLERS)
return;
int numDst = getNumDestinations(controllerID);
midiCC_container_t *pDst;
for (i=0; i < numDst; i++)
{
pDst = getDestination(controllerID, 0);
remove(pDst, controllerID);
}
midiCC_dest[controllerID].deleteAll();
isModified = true;
}
midiCC_container_t* JaySynthMidiCC::getDestination(int controllerID, int index)
{
if (controllerID >= NUM_MIDI_CONTROLLERS)
return NULL;
midiCC_container_t *pDst;
if (index >= getNumDestinations(controllerID))
return NULL;
pDst = midiCC_dest[controllerID][index].get();
return pDst;
}
int JaySynthMidiCC::getParamID(midiCC_container_t *pObj)
{
return pObj->constraints.id;
}
int JaySynthMidiCC::getControllerID(midiCC_container_t *pObj)
{
return pObj->controllerID;
}
void JaySynthMidiCC::setControllerID(midiCC_container_t *pObj, int controllerID)
{
if (controllerID >= NUM_MIDI_CONTROLLERS)
return;
if(isAssigned(pObj))
{
remove(pObj, pObj->controllerID);
add(pObj, controllerID);
}
pObj->controllerID = controllerID;
isModified = true;
}
bool JaySynthMidiCC::isAssigned(midiCC_container_t *pObj)
{
return pObj->isAssigned;
}
void JaySynthMidiCC::setDoChangeParameter(midiCC_container_t *pObj, bool doChangeParameter)
{
pObj->doChangeParameter = doChangeParameter;
isModified = true;
}
bool JaySynthMidiCC::doChangeParameter(midiCC_container_t *pObj)
{
return pObj->doChangeParameter;
}
void JaySynthMidiCC::setDoApplyOnPatchInit(midiCC_container_t *pObj, bool doApplyOnPatchInit)
{
pObj->doApplyOnPatchInit = doApplyOnPatchInit;
isModified = true;
}
bool JaySynthMidiCC::doApplyOnPatchInit(midiCC_container_t *pObj)
{
return pObj->doApplyOnPatchInit;
}
synth_float_t JaySynthMidiCC::getConstraintsMin(midiCC_container_t *pObj)
{
return pObj->constraints.pmin;
}
synth_float_t JaySynthMidiCC::getConstraintsMax(midiCC_container_t *pObj)
{
return pObj->constraints.pmax;
}
param_info_t* JaySynthMidiCC::getConstraints(midiCC_container_t *pObj)
{
return &pObj->constraints;
}
synth_float_t JaySynthMidiCC::getControlMin(midiCC_container_t *pObj)
{
return pObj->control.pmin;
}
void JaySynthMidiCC::setControlMin(midiCC_container_t *pObj, synth_float_t value)
{
pObj->control.pmin = value;
isModified = true;
}
synth_float_t JaySynthMidiCC::getControlMax(midiCC_container_t *pObj)
{
return pObj->control.pmax;
}
void JaySynthMidiCC::setControlMax(midiCC_container_t *pObj, synth_float_t value)
{
pObj->control.pmax = value;
isModified = true;
}
param_info_t* JaySynthMidiCC::getControl(midiCC_container_t *pObj)
{
return &pObj->control;
}
synth_float_t JaySynthMidiCC::getParamMin(midiCC_container_t *pObj)
{
return pObj->param.pmin;
}
void JaySynthMidiCC::setParamMin(midiCC_container_t *pObj, synth_float_t value)
{
pObj->param.pmin = value;
isModified = true;
}
synth_float_t JaySynthMidiCC::getParamMax(midiCC_container_t *pObj)
{
return pObj->param.pmax;
}
void JaySynthMidiCC::setParamMax(midiCC_container_t *pObj, synth_float_t value)
{
pObj->param.pmax = value;
isModified = true;
}
param_info_t* JaySynthMidiCC::getParam(midiCC_container_t *pObj)
{
return &pObj->param;
}
param_info_t* JaySynthMidiCC::getVelCurve(midiCC_container_t *pObj)
{
return &pObj->curve_vel;
}
void JaySynthMidiCC::setVelCurveMin(midiCC_container_t *pObj, synth_float_t value)
{
pObj->curve_vel.pmin = value;
isModified = true;
}
void JaySynthMidiCC::setVelCurveMax(midiCC_container_t *pObj, synth_float_t value)
{
pObj->curve_vel.pmax = value;
isModified = true;
}
void JaySynthMidiCC::setVelCurveSkew(midiCC_container_t *pObj, synth_float_t value)
{
pObj->curve_vel.scenter = value;
isModified = true;
}
void JaySynthMidiCC::setVelCurveShape(midiCC_container_t *pObj, synth_float_t value)
{
pObj->curve_vel.kexp = value;
isModified = true;
}
param_info_t* JaySynthMidiCC::getKeyCurve(midiCC_container_t *pObj)
{
return &pObj->curve_key;
}
void JaySynthMidiCC::setKeyCurveMin(midiCC_container_t *pObj, synth_float_t value)
{
pObj->curve_key.pmin = value;
isModified = true;
}
void JaySynthMidiCC::setKeyCurveMax(midiCC_container_t *pObj, synth_float_t value)
{
pObj->curve_key.pmax = value;
isModified = true;
}
void JaySynthMidiCC::setKeyCurveSkew(midiCC_container_t *pObj, synth_float_t value)
{
pObj->curve_key.scenter = value;
isModified = true;
}
void JaySynthMidiCC::setKeyCurveShape(midiCC_container_t *pObj, synth_float_t value)
{
pObj->curve_key.kexp = value;
isModified = true;
}
bool JaySynthMidiCC::isAssignedVel(midiCC_container_t *pObj)
{
return pObj->isVelAssigned;
}
bool JaySynthMidiCC::isAssignedKey(midiCC_container_t *pObj)
{
return pObj->isKeyAssigned;
}
void JaySynthMidiCC::setAssignedVel(midiCC_container_t *pObj, bool active)
{
pObj->isVelAssigned = active;
isModified = true;
}
void JaySynthMidiCC::setAssignedKey(midiCC_container_t *pObj, bool active)
{
pObj->isKeyAssigned = active;
isModified = true;
}
int JaySynthMidiCC::getVelKeyCombineOP(midiCC_container_t *pObj)
{
return pObj->velKeyCombineOP;
}
void JaySynthMidiCC::setVelKeyCombineOP(midiCC_container_t *pObj, int combineOP)
{
if (combineOP >= VELKEY_NUM_OPS)
return;
pObj->velKeyCombineOP = combineOP;
isModified = true;
}
bool JaySynthMidiCC::isAssignedVelKeyControl(int paramID)
{
return isAssignedVel(&midiCC_containers[paramID]) || isAssignedKey(&midiCC_containers[paramID]);
}
synth_float_t JaySynthMidiCC::getVelKeyControl(int paramID, synth_float_t vel, synth_float_t key)
{
synth_float_t result, result_vel, result_key;
result_vel = 0;
result_key = 0;
result = 0;
if (isAssignedVel(&midiCC_containers[paramID]))
result_vel = toParam(&midiCC_containers[paramID].curve_vel, vel);
if (isAssignedKey(&midiCC_containers[paramID]))
result_key = toParam(&midiCC_containers[paramID].curve_key, key/127);
switch (midiCC_containers[paramID].velKeyCombineOP)
{
case VELKEY_OP_ADD:
result = min(1, max(-1, result_vel + result_key));
break;
case VELKEY_OP_SUB:
result = min(1, max(-1, result_vel - result_key));
break;
case VELKEY_OP_MUL:
if (!isAssignedVel(&midiCC_containers[paramID]))
{
result = result_key;
break;
}
if (!isAssignedKey(&midiCC_containers[paramID]))
{
result = result_vel;
break;
}
result = result_vel * result_key;
break;
default:
break;
}
return midiCC_containers[paramID].constraints.pmax*result;
}
+116
View File
@@ -0,0 +1,116 @@
/*
==============================================================================
This file was auto-generated!
It contains the basic startup code for a Juce application.
==============================================================================
*/
#ifndef _JAYSYNTH_MIDICC_
#define _JAYSYNTH_MIDICC_
#include "../JuceLibraryCode/JuceHeader.h"
#include "synth_defs.h"
//==============================================================================
#define MIDICONTROLLER_TYPE_VELKEY 0x00000080
typedef struct midiCC_container_t
{
int controllerID;
bool isAssigned;
bool doChangeParameter;
bool doApplyOnPatchInit;
param_info_t constraints;
param_info_t control;
param_info_t param;
bool isVelAssigned;
bool isKeyAssigned;
param_info_t curve_vel;
param_info_t curve_key;
int velKeyCombineOP;
LinkedListPointer<midiCC_container_t> nextListItem;
} midiCC_container_t;
class JaySynthMidiCC
{
public:
JaySynthMidiCC();
~JaySynthMidiCC();
JaySynthMidiCC& operator= (JaySynthMidiCC& other);
void copyMidiCC(JaySynthMidiCC *pSrc);
JaySynthMidiCC* getMidiCC(void);
bool isMidiCCmodified(void);
const String toParameterNameXML (String name);
int findParamID_byName(String name);
void exportXML(String name);
void exportXML(XmlElement *pXML_doc);
int importXML(String name);
int importXML(XmlElement *pXML_doc);
void add(midiCC_container_t *pObj, int controllerID);
void remove(midiCC_container_t *pObj, int controllerID);
struct midiCC_container_t* getAtParamID(int paramID);
int getNumDestinations(int controllerID);
void removeDestinations(int controllerID);
midiCC_container_t* getDestination(int controllerID, int index);
int getParamID(midiCC_container_t *pObj);
int getControllerID(midiCC_container_t *pObj);
void setControllerID(midiCC_container_t *pObj, int controllerID);
bool isAssigned(midiCC_container_t *pObj);
void setDoChangeParameter(midiCC_container_t *pObj, bool doChangeParameter);
bool doChangeParameter(midiCC_container_t *pObj);
void setDoApplyOnPatchInit(midiCC_container_t *pObj, bool doApplyOnPatchInit);
bool doApplyOnPatchInit(midiCC_container_t *pObj);
synth_float_t getConstraintsMin(midiCC_container_t *pObj);
synth_float_t getConstraintsMax(midiCC_container_t *pObj);
param_info_t* getConstraints(midiCC_container_t *pObj);
synth_float_t getControlMin(midiCC_container_t *pObj);
void setControlMin(midiCC_container_t *pObj, synth_float_t value);
synth_float_t getControlMax(midiCC_container_t *pObj);
void setControlMax(midiCC_container_t *pObj, synth_float_t value);
param_info_t* getControl(midiCC_container_t *pObj);
synth_float_t getParamMin(midiCC_container_t *pObj);
void setParamMin(midiCC_container_t *pObj, synth_float_t value);
synth_float_t getParamMax(midiCC_container_t *pObj);
void setParamMax(midiCC_container_t *pObj, synth_float_t value);
param_info_t* getParam(midiCC_container_t *pObj);
param_info_t* getVelCurve(midiCC_container_t *pObj);
void setVelCurveMin(midiCC_container_t *pObj, synth_float_t value);
void setVelCurveMax(midiCC_container_t *pObj, synth_float_t value);
void setVelCurveSkew(midiCC_container_t *pObj, synth_float_t value);
void setVelCurveShape(midiCC_container_t *pObj, synth_float_t value);
param_info_t* getKeyCurve(midiCC_container_t *pObj);
void setKeyCurveMin(midiCC_container_t *pObj, synth_float_t value);
void setKeyCurveMax(midiCC_container_t *pObj, synth_float_t value);
void setKeyCurveSkew(midiCC_container_t *pObj, synth_float_t value);
void setKeyCurveShape(midiCC_container_t *pObj, synth_float_t value);
bool isAssignedVel(midiCC_container_t *pObj);
bool isAssignedKey(midiCC_container_t *pObj);
void setAssignedVel(midiCC_container_t *pObj, bool active);
void setAssignedKey(midiCC_container_t *pObj, bool active);
int getVelKeyCombineOP(midiCC_container_t *pObj);
void setVelKeyCombineOP(midiCC_container_t *pObj, int combineOP);
bool isAssignedVelKeyControl(int paramID);
synth_float_t getVelKeyControl(int paramID, synth_float_t vel, synth_float_t key);
enum
{
VELKEY_OP_ADD = 0,
VELKEY_OP_SUB,
VELKEY_OP_MUL,
VELKEY_NUM_OPS
};
private:
midiCC_container_t midiCC_containers[SYNTH_NUM_PARAMS];
LinkedListPointer <midiCC_container_t> midiCC_dest[NUM_MIDI_CONTROLLERS];
NamedValueSet paramNamedValueSet;
bool isModified;
};
#endif // _JAYSYNTH_MIDICC_
+136
View File
@@ -0,0 +1,136 @@
/*
==============================================================================
This file was generated by user!
==============================================================================
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include "synth_defs.h"
#include "JaySynthMonophonicMGR.h"
/** A JaySynth voice that just plays incredible sounds.. */
JaySynthMonophonicMGR::JaySynthMonophonicMGR()
{
init();
}
JaySynthMonophonicMGR::~JaySynthMonophonicMGR()
{
}
void JaySynthMonophonicMGR::init(void)
{
int i;
memset (keys, 0, sizeof(keys));
for (i=0; i < 128; i++)
keys[i].note = i;
pLatest = NULL;
}
void JaySynthMonophonicMGR::add(int note, float vel)
{
if ((note < 0) || (note > 127))
return;
// Delete if velocity == 0
if (vel == 0)
{
del(note);
return;
}
// Delete first if note already exists
if (keys[note].vel > 0)
del(note);
// Add key
keys[note].vel = vel;
keys[note].pPrev = NULL;
keys[note].pNext = pLatest;
if (pLatest)
pLatest->pPrev = &keys[note];
pLatest = &keys[note];
}
void JaySynthMonophonicMGR::del(int note)
{
if ((note < 0) || (note > 127))
return;
if (keys[note].pPrev)
keys[note].pPrev->pNext = keys[note].pNext;
if (keys[note].pNext)
keys[note].pNext->pPrev = keys[note].pPrev;
// Do I delete the newest note
if (!keys[note].pPrev)
pLatest = keys[note].pNext;
keys[note].vel = 0;
keys[note].pPrev = NULL;
keys[note].pNext = NULL;
}
int JaySynthMonophonicMGR::getNumNotes(void)
{
key_linkedlist_t *pKey = pLatest;
int num_notes = 0;
while(pKey)
{
num_notes++;
pKey = pKey->pNext;
}
return num_notes;
}
int JaySynthMonophonicMGR::getLatestNote(void)
{
if (!pLatest)
return -1;
return pLatest->note;
}
int JaySynthMonophonicMGR::getHighestNote(void)
{
key_linkedlist_t *pKey = pLatest;
int note = -1;
while(pKey)
{
if (note < pKey->note)
note = pKey->note;
pKey = pKey->pNext;
}
if (note < 0)
return -1;
return keys[note].note;
}
float JaySynthMonophonicMGR::getVel(int note)
{
if ((note < 0) || (note > 127))
return 0;
return keys[note].vel;
}
+41
View File
@@ -0,0 +1,41 @@
/*
==============================================================================
This file was generated by user!
==============================================================================
*/
#ifndef _JAYSYNTHMONOPHONICMGR_H_
#define _JAYSYNTHMONOPHONICMGR_H_
//#include "../JuceLibraryCode/JuceHeader.h"
#include "synth_defs.h"
class JaySynthMonophonicMGR
{
public:
JaySynthMonophonicMGR();
~JaySynthMonophonicMGR();
void init(void);
void add(int note, float vel);
void del(int note);
int getNumNotes(void);
int getLatestNote(void);
int getHighestNote(void);
float getVel(int note);
private:
typedef struct _skey_linkedlist_t
{
int note;
float vel;
struct _skey_linkedlist_t *pPrev, *pNext;
} key_linkedlist_t;
key_linkedlist_t keys[128];
key_linkedlist_t *pLatest;
};
#endif // _JAYSYNTHMONOPHONICMGR_H_
+177
View File
@@ -0,0 +1,177 @@
/*
==============================================================================
This file was generated by user!
==============================================================================
*/
#include <math.h>
#include "synth_defs.h"
#include "JaySynthSound.h"
JaySynthSound::JaySynthSound()
{
name = String("Default");
// Default is "Jump" sound
setParameter(SYNTH_PARAM_VOLUME, 100);
setParameter(SYNTH_PARAM_VOICE_PAN_SPREAD, 50);
setParameter(SYNTH_PARAM_TUNE, 0);
setParameter(SYNTH_PARAM_TOTAL_NUM_VOICES, MAX_POLYPHONY);
setParameter(SYNTH_PARAM_HUMANIZE_ENABLE, 0);
setParameter(SYNTH_PARAM_HUMANIZE_VAR_VCO, 0);
setParameter(SYNTH_PARAM_HUMANIZE_VAR_VCF, 0);
setParameter(SYNTH_PARAM_HUMANIZE_VAR_ENV, 0);
setParameter(SYNTH_PARAM_MONOPHONIC_ENABLE, 0);
setParameter(SYNTH_PARAM_MONOPHONIC_RETRIGGER_ENABLE, 0);
setParameter(SYNTH_PARAM_UNISONO_ENABLE, 0);
setParameter(SYNTH_PARAM_UNISONO_NUM_VOICES, 8);
setParameter(SYNTH_PARAM_PORTAMENTO_TIME, 0.0);
setParameter(SYNTH_PARAM_OSC_0_ENABLE, 1);
setParameter(SYNTH_PARAM_OSC_1_ENABLE, 1);
setParameter(SYNTH_PARAM_OSC_0_RESTART_ON_TRIGGER, 0);
setParameter(SYNTH_PARAM_OSC_1_RESTART_ON_TRIGGER, 0);
setParameter(SYNTH_PARAM_OSC_0_LEVEL, 100);
setParameter(SYNTH_PARAM_OSC_1_LEVEL, 100);
setParameter(SYNTH_PARAM_OSC_0_DUTYCYCLE, 50);
setParameter(SYNTH_PARAM_OSC_1_DUTYCYCLE, 50);
setParameter(SYNTH_PARAM_OSC_0_DETUNE, -4);
setParameter(SYNTH_PARAM_OSC_1_DETUNE, +4);
setParameter(SYNTH_PARAM_OSC_0_TRANSPOSE, 0);
setParameter(SYNTH_PARAM_OSC_1_TRANSPOSE, 0);
setParameter(SYNTH_PARAM_OSC_0_WAVEFORM, 0);
setParameter(SYNTH_PARAM_OSC_1_WAVEFORM, 0);
setParameter(SYNTH_PARAM_OSC_0_PB_RANGE_MIN, -12);
setParameter(SYNTH_PARAM_OSC_1_PB_RANGE_MIN, -12);
setParameter(SYNTH_PARAM_OSC_0_PB_RANGE_MAX, +12);
setParameter(SYNTH_PARAM_OSC_1_PB_RANGE_MAX, +12);
setParameter(SYNTH_PARAM_OSC_0_FM_AMT_0, 0);
setParameter(SYNTH_PARAM_OSC_1_FM_AMT_0, 0);
setParameter(SYNTH_PARAM_OSC_0_FM_AMT_1, 0);
setParameter(SYNTH_PARAM_OSC_1_FM_AMT_1, 0);
setParameter(SYNTH_PARAM_OSC_0_FM_SRC_0, 0);
setParameter(SYNTH_PARAM_OSC_1_FM_SRC_0, 0);
setParameter(SYNTH_PARAM_OSC_0_FM_SRC_1, 0);
setParameter(SYNTH_PARAM_OSC_1_FM_SRC_1, 0);
setParameter(SYNTH_PARAM_OSC_0_FM_SRC_OP, VOICE_MOD_SRC_OP_ADD);
setParameter(SYNTH_PARAM_OSC_1_FM_SRC_OP, VOICE_MOD_SRC_OP_ADD);
setParameter(SYNTH_PARAM_OSC_0_AM_AMT_0, 0);
setParameter(SYNTH_PARAM_OSC_1_AM_AMT_0, 0);
setParameter(SYNTH_PARAM_OSC_0_AM_AMT_1, 0);
setParameter(SYNTH_PARAM_OSC_1_AM_AMT_1, 0);
setParameter(SYNTH_PARAM_OSC_0_AM_SRC_0, 0);
setParameter(SYNTH_PARAM_OSC_1_AM_SRC_0, 0);
setParameter(SYNTH_PARAM_OSC_0_AM_SRC_1, 0);
setParameter(SYNTH_PARAM_OSC_1_AM_SRC_1, 0);
setParameter(SYNTH_PARAM_OSC_0_AM_SRC_OP, VOICE_MOD_SRC_OP_ADD);
setParameter(SYNTH_PARAM_OSC_1_AM_SRC_OP, VOICE_MOD_SRC_OP_ADD);
setParameter(SYNTH_PARAM_OSC_0_PWM_AMT_0, 0);
setParameter(SYNTH_PARAM_OSC_1_PWM_AMT_0, 0);
setParameter(SYNTH_PARAM_OSC_0_PWM_AMT_1, 0);
setParameter(SYNTH_PARAM_OSC_1_PWM_AMT_1, 0);
setParameter(SYNTH_PARAM_OSC_0_PWM_SRC_0, 0);
setParameter(SYNTH_PARAM_OSC_1_PWM_SRC_0, 0);
setParameter(SYNTH_PARAM_OSC_0_PWM_SRC_1, 0);
setParameter(SYNTH_PARAM_OSC_1_PWM_SRC_1, 0);
setParameter(SYNTH_PARAM_OSC_0_PWM_SRC_OP, VOICE_MOD_SRC_OP_ADD);
setParameter(SYNTH_PARAM_OSC_1_PWM_SRC_OP, VOICE_MOD_SRC_OP_ADD);
setParameter(SYNTH_PARAM_NOISE_ENABLE, 0);
setParameter(SYNTH_PARAM_NOISE_LEVEL, 50);
setParameter(SYNTH_PARAM_NOISE_SHAPE, VOICE_NOISE_SHAPE_WHITE);
setParameter(SYNTH_PARAM_VCA_ENV_AMT, 100);
setParameter(SYNTH_PARAM_VCA_ENV_A, 1);
setParameter(SYNTH_PARAM_VCA_ENV_D, 1000);
setParameter(SYNTH_PARAM_VCA_ENV_S, 100);
setParameter(SYNTH_PARAM_VCA_ENV_R, 150);
setParameter(SYNTH_PARAM_VCF_ENV_A, 1);
setParameter(SYNTH_PARAM_VCF_ENV_D, 1000);
setParameter(SYNTH_PARAM_VCF_ENV_S, 100);
setParameter(SYNTH_PARAM_VCF_ENV_R, 500);
setParameter(SYNTH_PARAM_ENV_2_A, 1);
setParameter(SYNTH_PARAM_ENV_2_D, 1000);
setParameter(SYNTH_PARAM_ENV_2_S, 100);
setParameter(SYNTH_PARAM_ENV_2_R, 500);
setParameter(SYNTH_PARAM_ENV_3_A, 1);
setParameter(SYNTH_PARAM_ENV_3_D, 1000);
setParameter(SYNTH_PARAM_ENV_3_S, 100);
setParameter(SYNTH_PARAM_ENV_3_R, 500);
setParameter(SYNTH_PARAM_VCF_TYPE, VCF_FILTERTYPE_LOWPASS);
setParameter(SYNTH_PARAM_VCF_ORDER, VCF_FILTERORDER_4);
setParameter(SYNTH_PARAM_VCF_F, FILTER_F_MAX);
setParameter(SYNTH_PARAM_VCF_Q, 1.0);
setParameter(SYNTH_PARAM_VCF_ENV_AMT, 0);
setParameter(SYNTH_PARAM_LFO_0_SPEED, 1.f);
setParameter(SYNTH_PARAM_LFO_1_SPEED, 1.f);
setParameter(SYNTH_PARAM_LFO_2_SPEED, 1.f);
setParameter(SYNTH_PARAM_LFO_3_SPEED, 1.f);
setParameter(SYNTH_PARAM_LFO_0_SMOOTH, 0.0);
setParameter(SYNTH_PARAM_LFO_1_SMOOTH, 0.0);
setParameter(SYNTH_PARAM_LFO_2_SMOOTH, 0.0);
setParameter(SYNTH_PARAM_LFO_3_SMOOTH, 0.0);
setParameter(SYNTH_PARAM_LFO_0_DELAY, 0.0);
setParameter(SYNTH_PARAM_LFO_1_DELAY, 0.0);
setParameter(SYNTH_PARAM_LFO_2_DELAY, 0.0);
setParameter(SYNTH_PARAM_LFO_3_DELAY, 0.0);
setParameter(SYNTH_PARAM_LFO_0_ATTACK, 0.0);
setParameter(SYNTH_PARAM_LFO_1_ATTACK, 0.0);
setParameter(SYNTH_PARAM_LFO_2_ATTACK, 0.0);
setParameter(SYNTH_PARAM_LFO_3_ATTACK, 0.0);
setParameter(SYNTH_PARAM_LFO_0_SHAPE, LFO_WAVEFORM_SINE);
setParameter(SYNTH_PARAM_LFO_1_SHAPE, LFO_WAVEFORM_SINE);
setParameter(SYNTH_PARAM_LFO_2_SHAPE, LFO_WAVEFORM_SINE);
setParameter(SYNTH_PARAM_LFO_3_SHAPE, LFO_WAVEFORM_SINE);
setParameter(SYNTH_PARAM_LFO_0_MODE, VOICE_LFO_MODE_GLOBAL);
setParameter(SYNTH_PARAM_LFO_1_MODE, VOICE_LFO_MODE_GLOBAL);
setParameter(SYNTH_PARAM_LFO_2_MODE, VOICE_LFO_MODE_GLOBAL);
setParameter(SYNTH_PARAM_LFO_3_MODE, VOICE_LFO_MODE_GLOBAL);
setParameter(SYNTH_PARAM_LFO_0_SYNC, VOICE_LFO_SYNC_FREE);
setParameter(SYNTH_PARAM_LFO_1_SYNC, VOICE_LFO_SYNC_FREE);
setParameter(SYNTH_PARAM_LFO_2_SYNC, VOICE_LFO_SYNC_FREE);
setParameter(SYNTH_PARAM_LFO_3_SYNC, VOICE_LFO_SYNC_FREE);
setParameter(SYNTH_PARAM_LFO_0_SYMMETRY, 0);
setParameter(SYNTH_PARAM_LFO_1_SYMMETRY, 0);
setParameter(SYNTH_PARAM_LFO_2_SYMMETRY, 0);
setParameter(SYNTH_PARAM_LFO_3_SYMMETRY, 0);
setParameter(SYNTH_PARAM_VCF_F_AMT_0, 0);
setParameter(SYNTH_PARAM_VCF_F_AMT_1, 0);
setParameter(SYNTH_PARAM_VCF_F_SRC_0, 0);
setParameter(SYNTH_PARAM_VCF_F_SRC_1, 0);
setParameter(SYNTH_PARAM_VCF_F_SRC_OP, 0);
setParameter(SYNTH_PARAM_VCF_Q_AMT_0, 0);
setParameter(SYNTH_PARAM_VCF_Q_AMT_1, 0);
setParameter(SYNTH_PARAM_VCF_Q_SRC_0, 0);
setParameter(SYNTH_PARAM_VCF_Q_SRC_1, 0);
setParameter(SYNTH_PARAM_VCF_Q_SRC_OP, 0);
setParameter(SYNTH_PARAM_VCA_AM_AMT_0, 0);
setParameter(SYNTH_PARAM_VCA_AM_SRC_0, 0);
setParameter(SYNTH_PARAM_VCA_PAN_AMT_0, 0);
setParameter(SYNTH_PARAM_VCA_PAN_SRC_0, 0);
}
JaySynthSound::~JaySynthSound()
{
}
void JaySynthSound::setName(String ProgramName)
{
name = ProgramName;
}
String JaySynthSound::getName(void)
{
return name;
}
void JaySynthSound::setParameter(int index, synth_float_t param)
{
parameter[index] = param;
}
synth_float_t JaySynthSound::getParameter(int index)
{
return parameter[index];
}
+37
View File
@@ -0,0 +1,37 @@
/*
==============================================================================
This file was generated by user!
==============================================================================
*/
#ifndef _JAYSYNTHSOUND_H_
#define _JAYSYNTHSOUND_H_
#include "../JuceLibraryCode/JuceHeader.h"
#include "synth_defs.h"
#include "JaySynthMidiCC.h"
//==============================================================================
/** A synth sound that's just a bunch of parameters that makes an incredible sound.. */
class JaySynthSound : public SynthesiserSound, public JaySynthMidiCC
{
public:
synth_float_t parameter[SYNTH_NUM_PARAMS];
String name;
JaySynthSound();
~JaySynthSound();
void setName(String ProgramName);
String getName(void);
void setParameter(int index, synth_float_t param);
synth_float_t getParameter(int index);
void initParameter(int index, synth_float_t param);
bool appliesToNote (const int /*midiNoteNumber*/) { return true; }
bool appliesToChannel (const int /*midiChannel*/) { return true; }
};
#endif // _JAYSYNTHSOUND_H_
+105
View File
@@ -0,0 +1,105 @@
/*
==============================================================================
This file was generated by user!
==============================================================================
*/
#include <math.h>
#include "synth_defs.h"
#include "JaySynthSound.h"
#include "JaySynthVoice.h"
/** A JaySynth voice that just plays incredible sounds.. */
JaySynthVoice::JaySynthVoice(voice_t *pVoice, int id, voice_common_t *pCom)
{
m_pVoice = pVoice;
VoiceInit(pVoice, pCom, id, 44100);
}
JaySynthVoice::~JaySynthVoice()
{
VoiceFree(m_pVoice);
}
void JaySynthVoice::setSampleRate (synth_float_t sampleRate)
{
VoiceSetFS(m_pVoice, sampleRate);
}
void JaySynthVoice::setBufsize (int bufsize)
{
VoiceSetBufsize(m_pVoice, bufsize);
}
bool JaySynthVoice::canPlaySound (SynthesiserSound* sound)
{
return dynamic_cast <JaySynthSound*> (sound) != 0;
}
void JaySynthVoice::startNote (const int midiNoteNumber, const float velocity,
SynthesiserSound* sound, const int /*currentPitchWheelPosition*/)
{
VoiceEvent(m_pVoice, voice_event_trigger);
return;
/*
if (m_pVoice->state == note_state_idle)
{
VoiceEvent(m_pVoice, voice_event_trigger);
}
else
{
VoiceEvent(m_pVoice, voice_event_retrigger);
}
*/
}
void JaySynthVoice::stopNote (const bool allowTailOff)
{
if (allowTailOff)
{
VoiceEvent(m_pVoice, voice_event_release);
}
else
{
// we're being told to stop playing immediately, so reset everything..
VoiceEvent(m_pVoice, voice_event_release);
clearCurrentNote();
}
}
void JaySynthVoice::pitchWheelMoved (const int /*newValue*/)
{
}
void JaySynthVoice::controllerMoved (const int /*controllerNumber*/, const int /*newValue*/)
{
}
void JaySynthVoice::renderNextBlock (AudioSampleBuffer& outputBuffer, int startSample, int numSamples)
{
/* Done in JaySynth::renderNextBlock()
float *buf1 = outputBuffer.getSampleData (0, startSample);
float *buf2 = outputBuffer.getSampleData (1, startSample);
VoiceProcessDataV_Common(m_pVoice, buf1, buf2, numSamples);
if (m_pVoice->state == note_state_idle)
return;
VoiceProcessDataV(m_pVoice, buf1, buf2, numSamples);
if (m_pVoice->state == note_state_idle)
clearCurrentNote();
*/
}
void JaySynthVoice::setParameter(int index, synth_float_t value)
{
VoiceParam2Set(m_pVoice, index, value);
}
+79
View File
@@ -0,0 +1,79 @@
/*
==============================================================================
This file was generated by user!
==============================================================================
*/
#ifndef _JAYSYNTHVOICE_H_
#define _JAYSYNTHVOICE_H_
#include "../JuceLibraryCode/JuceHeader.h"
#include "synth_defs.h"
class JaySynthVoice
{
public:
JaySynthVoice(voice_t *pVoice, int id, voice_common_t *pCom);
~JaySynthVoice();
void setSampleRate (synth_float_t sampleRate);
void setBufsize (int bufsize);
bool canPlaySound (SynthesiserSound* sound);
void startNote (const int midiNoteNumber, const float velocity,
SynthesiserSound* /*sound*/, const int /*currentPitchWheelPosition*/);
void stopNote (const bool allowTailOff);
void pitchWheelMoved (const int newValue);
void controllerMoved (const int controllerNumber, const int newValue);
void renderNextBlock (AudioSampleBuffer& outputBuffer, int startSample, int numSamples);
void setParameter(int index, synth_float_t value);
int getCurrentlyPlayingNote() const
{
return currentlyPlayingNote;
}
SynthesiserSound::Ptr getCurrentlyPlayingSound() const
{
return currentlyPlayingSound;
}
bool isPlayingChannel (int midiChannel) const
{
return currentlyPlayingSound != nullptr
&& currentlyPlayingSound->appliesToChannel (midiChannel);
}
void setCurrentPlaybackSampleRate (double newRate)
{
currentSampleRate = newRate;
}
double getSampleRate() const
{
return currentSampleRate;
}
void clearCurrentNote()
{
currentlyPlayingNote = -1;
currentlyPlayingSound = nullptr;
}
private:
friend class JaySynth;
voice_t *m_pVoice;
synth_float_t note_on_time;
double currentSampleRate;
int currentlyPlayingNote;
uint32 noteOnTime;
SynthesiserSound::Ptr currentlyPlayingSound;
bool keyIsDown; // the voice may still be playing when the key is not down (i.e. sustain pedal)
bool sostenutoPedalDown;
};
#endif // _JAYSYNTHVOICE_H_
+618
View File
@@ -0,0 +1,618 @@
/*
==============================================================================
This is an automatically generated file created by the Jucer!
Creation date: 19 Aug 2012 10:54:59am
Be careful when adding custom code to these files, as only the code within
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
and re-saved.
Jucer version: 1.12
------------------------------------------------------------------------------
The Jucer is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-6 by Raw Material Software ltd.
==============================================================================
*/
//[Headers] You can add your own extra header files here...
#include "param_scale.h"
//[/Headers]
#include "MidiCC_PopUp.h"
//[MiscUserDefs] You can add your own user definitions and misc code here...
//[/MiscUserDefs]
//==============================================================================
MidiCC_PopUp::MidiCC_PopUp (JaySynthMidiCC *pMidiCC, int paramID, synth_float_t currParamValue, JaySynth::midiCC_info_t *pCurrMidiCCinfo, String name, MidiCC_PopUp_Listener *listener)
: Component (L"MidiCC PopUp"),
textButton_OK (0),
label_MidiCC_ID (0),
label_control_min (0),
label_control_max (0),
slider_test (0),
button_move_sliders_enable (0),
button_assign_enable (0),
button_midi_learn (0),
label_parameter_name (0),
button_apply_on_patch_init (0)
{
addAndMakeVisible (textButton_OK = new TextButton (L"OK"));
textButton_OK->addListener (this);
addAndMakeVisible (label_MidiCC_ID = new Label (L"MidiCC ID",
L"0"));
label_MidiCC_ID->setTooltip (L"This is the Midi-Controller Number");
label_MidiCC_ID->setFont (Font (15.0000f, Font::plain));
label_MidiCC_ID->setJustificationType (Justification::centredRight);
label_MidiCC_ID->setEditable (true, true, false);
label_MidiCC_ID->setColour (Label::textColourId, Colours::white);
label_MidiCC_ID->setColour (TextEditor::textColourId, Colours::black);
label_MidiCC_ID->setColour (TextEditor::backgroundColourId, Colour (0x0));
label_MidiCC_ID->setColour (TextEditor::highlightColourId, Colours::yellow);
label_MidiCC_ID->addListener (this);
addAndMakeVisible (label_control_min = new Label (L"Control Min",
L"0"));
label_control_min->setTooltip (L"Parameter minimum value");
label_control_min->setFont (Font (15.0000f, Font::plain));
label_control_min->setJustificationType (Justification::centredRight);
label_control_min->setEditable (true, true, false);
label_control_min->setColour (Label::textColourId, Colours::white);
label_control_min->setColour (TextEditor::textColourId, Colours::black);
label_control_min->setColour (TextEditor::backgroundColourId, Colour (0x0));
label_control_min->setColour (TextEditor::highlightColourId, Colours::yellow);
label_control_min->addListener (this);
addAndMakeVisible (label_control_max = new Label (L"Control Max",
L"0"));
label_control_max->setTooltip (L"Parameter maximum value");
label_control_max->setFont (Font (15.0000f, Font::plain));
label_control_max->setJustificationType (Justification::centredRight);
label_control_max->setEditable (true, true, false);
label_control_max->setColour (Label::textColourId, Colours::white);
label_control_max->setColour (TextEditor::textColourId, Colours::black);
label_control_max->setColour (TextEditor::backgroundColourId, Colour (0x0));
label_control_max->setColour (TextEditor::highlightColourId, Colours::yellow);
label_control_max->addListener (this);
addAndMakeVisible (slider_test = new Slider (L"Test Slider"));
slider_test->setTooltip (L"Test Slider");
slider_test->setRange (0, 1, 0);
slider_test->setSliderStyle (Slider::LinearHorizontal);
slider_test->setTextBoxStyle (Slider::NoTextBox, true, 80, 20);
slider_test->addListener (this);
addAndMakeVisible (button_move_sliders_enable = new ToggleButton (L"MoveParams Enable"));
button_move_sliders_enable->setTooltip (L"If \'Absolute = no\', the parameter is alterered relatively from the given slider position on the main window in the specified range. If \'\'Absolute = yes\', the midi controller alters parameter absolutely in the specified range. In this mode sliders really move on the main window.");
button_move_sliders_enable->setButtonText (String::empty);
button_move_sliders_enable->addListener (this);
addAndMakeVisible (button_assign_enable = new ToggleButton (L"Assign Enable"));
button_assign_enable->setTooltip (L"Set this to make MIDI-Controller assignment active");
button_assign_enable->setButtonText (String::empty);
button_assign_enable->addListener (this);
addAndMakeVisible (button_midi_learn = new ToggleButton (L"Midi Learn Button"));
button_midi_learn->setTooltip (L"Set this to learn MIDI-Controller number from MIDI-controller movement");
button_midi_learn->setButtonText (String::empty);
button_midi_learn->addListener (this);
button_midi_learn->setColour (ToggleButton::textColourId, Colours::white);
addAndMakeVisible (label_parameter_name = new Label (L"Parameter Name",
L"Parameter Name"));
label_parameter_name->setFont (Font (20.0000f, Font::plain));
label_parameter_name->setJustificationType (Justification::centred);
label_parameter_name->setEditable (false, false, false);
label_parameter_name->setColour (Label::textColourId, Colours::white);
label_parameter_name->setColour (TextEditor::textColourId, Colours::black);
label_parameter_name->setColour (TextEditor::backgroundColourId, Colour (0x0));
addAndMakeVisible (button_apply_on_patch_init = new ToggleButton (L"Apply on Patch Init Enable"));
button_apply_on_patch_init->setTooltip (L"Set this to apply current Midi-Controller position on initialization of this patch (e.g. Program change)");
button_apply_on_patch_init->setButtonText (String::empty);
button_apply_on_patch_init->addListener (this);
//[UserPreSize]
//[/UserPreSize]
setSize (248, 280);
//[Constructor] You can add your own custom stuff here..
this->pMidiCC = pMidiCC;
pSavedMidiCCinfo = pCurrMidiCCinfo;
pMidiCC_container = pMidiCC->getAtParamID(paramID);
savedParamValue = currParamValue;
lastMidiCCvalue = pSavedMidiCCinfo[pMidiCC->getControllerID(pMidiCC_container)].value;
this->currentParamValue = savedParamValue;
this->currentControlValue = 0;
if (isEnabled())
{
this->currentParamValue = toParam(pMidiCC->getParam(pMidiCC_container), (synth_float_t)lastMidiCCvalue);
this->currentControlValue = toParam(pMidiCC->getControl(pMidiCC_container), (synth_float_t)lastMidiCCvalue);
}
lastParamValue = this->currentParamValue;
lastControlValue = this->currentControlValue;
GetMin();
GetMax();
restoreTestSlider();
label_MidiCC_ID->setText(String(pMidiCC->getControllerID(pMidiCC_container)), false);
label_parameter_name->setText(name, false);
button_assign_enable->setToggleState(pMidiCC->isAssigned(pMidiCC_container), false);
button_move_sliders_enable->setToggleState(pMidiCC->doChangeParameter(pMidiCC_container), false);
button_apply_on_patch_init->setToggleState(pMidiCC->doApplyOnPatchInit(pMidiCC_container), false);
button_assign_enable->setTriggeredOnMouseDown (true);
button_assign_enable->setClickingTogglesState(true);
button_move_sliders_enable->setTriggeredOnMouseDown (true);
button_move_sliders_enable->setClickingTogglesState(true);
button_midi_learn->setTriggeredOnMouseDown (true);
button_midi_learn->setClickingTogglesState(true);
button_apply_on_patch_init->setTriggeredOnMouseDown (true);
button_apply_on_patch_init->setClickingTogglesState(true);
addListener(listener);
listeners.call (&MidiCC_PopUp_Listener::MidiCC_PopUp_event, POPUP_CREATED);
//[/Constructor]
}
MidiCC_PopUp::~MidiCC_PopUp()
{
//[Destructor_pre]. You can add your own custom destruction code here..
//[/Destructor_pre]
deleteAndZero (textButton_OK);
deleteAndZero (label_MidiCC_ID);
deleteAndZero (label_control_min);
deleteAndZero (label_control_max);
deleteAndZero (slider_test);
deleteAndZero (button_move_sliders_enable);
deleteAndZero (button_assign_enable);
deleteAndZero (button_midi_learn);
deleteAndZero (label_parameter_name);
deleteAndZero (button_apply_on_patch_init);
//[Destructor]. You can add your own custom destruction code here..
//[/Destructor]
}
//==============================================================================
void MidiCC_PopUp::paint (Graphics& g)
{
//[UserPrePaint] Add your own custom painting code here..
//[/UserPrePaint]
g.setColour (Colour (0xff2a64a5));
g.fillRoundedRectangle (0.0f, 4.0f, 244.0f, 274.0f, 10.0000f);
g.setColour (Colours::white);
g.drawRoundedRectangle (2.0f, 3.0f, 243.0f, 274.0f, 7.0000f, 4.0000f);
g.setColour (Colours::white);
g.setFont (Font (15.0000f, Font::plain));
g.drawText (L"Midi Controller",
16, 122, 94, 20,
Justification::centredLeft, true);
g.setColour (Colours::white);
g.setFont (Font (15.0000f, Font::plain));
g.drawText (L"Active",
16, 48, 62, 20,
Justification::centredLeft, true);
g.setColour (Colours::white);
g.setFont (Font (15.0000f, Font::plain));
g.drawText (L"Absolute",
16, 68, 59, 20,
Justification::centredLeft, true);
g.setColour (Colours::white);
g.setFont (Font (15.0000f, Font::plain));
g.drawText (L"Minimum",
16, 142, 75, 20,
Justification::centredLeft, true);
g.setColour (Colours::white);
g.setFont (Font (15.0000f, Font::plain));
g.drawText (L"Maximum",
16, 162, 75, 20,
Justification::centredLeft, true);
g.setColour (Colours::white);
g.setFont (Font (15.0000f, Font::plain));
g.drawText (L"Test it",
18, 194, 46, 20,
Justification::centredLeft, true);
g.setColour (Colours::white);
g.setFont (Font (15.0000f, Font::plain));
g.drawText (L"Learn",
192, 122, 38, 20,
Justification::centredLeft, true);
g.setColour (Colours::white);
g.setFont (Font (15.0000f, Font::plain));
g.drawText (L"Apply on patch init",
16, 88, 120, 20,
Justification::centredLeft, true);
//[UserPaint] Add your own custom painting code here..
//[/UserPaint]
}
void MidiCC_PopUp::resized()
{
textButton_OK->setBounds (22, 238, 202, 22);
label_MidiCC_ID->setBounds (135, 122, 32, 20);
label_control_min->setBounds (103, 144, 64, 20);
label_control_max->setBounds (103, 166, 64, 20);
slider_test->setBounds (64, 192, 168, 26);
button_move_sliders_enable->setBounds (148, 68, 20, 20);
button_assign_enable->setBounds (148, 48, 20, 20);
button_midi_learn->setBounds (172, 122, 20, 20);
label_parameter_name->setBounds (12, 12, 212, 24);
button_apply_on_patch_init->setBounds (148, 88, 20, 20);
//[UserResized] Add your own custom resize handling here..
//[/UserResized]
}
void MidiCC_PopUp::buttonClicked (Button* buttonThatWasClicked)
{
//[UserbuttonClicked_Pre]
bool state;
//[/UserbuttonClicked_Pre]
if (buttonThatWasClicked == textButton_OK)
{
//[UserButtonCode_textButton_OK] -- add your button handler code here..
currentControlValue = 0;
if (isEnabled() && !doChangeParameter())
currentControlValue = toParam(pMidiCC->getControl(pMidiCC_container), (synth_float_t)lastMidiCCvalue);
currentParamValue = savedParamValue;
if (isEnabled() && doChangeParameter())
currentParamValue = toParam(pMidiCC->getParam(pMidiCC_container), (synth_float_t)lastMidiCCvalue);
listeners.call (&MidiCC_PopUp_Listener::MidiCC_PopUp_event, POPUP_OK);
//[/UserButtonCode_textButton_OK]
}
else if (buttonThatWasClicked == button_move_sliders_enable)
{
//[UserButtonCode_button_move_sliders_enable] -- add your button handler code here..
state = buttonThatWasClicked->getToggleState();
pMidiCC->setDoChangeParameter(pMidiCC_container, state);
if (state)
{
currentParamValue = lastParamValue;
lastControlValue = currentControlValue;
}
else
{
currentControlValue = lastControlValue;
lastParamValue = currentParamValue;
}
GetMin();
GetMax();
restoreTestSlider();
TestValueUpdate();
//[/UserButtonCode_button_move_sliders_enable]
}
else if (buttonThatWasClicked == button_assign_enable)
{
//[UserButtonCode_button_assign_enable] -- add your button handler code here..
if (buttonThatWasClicked->getToggleState())
pMidiCC->add(pMidiCC_container, label_MidiCC_ID->getText().getIntValue());
else
pMidiCC->remove(pMidiCC_container, label_MidiCC_ID->getText().getIntValue());
if (isEnabled())
{
currentParamValue = toParam(pMidiCC->getParam(pMidiCC_container), (synth_float_t)lastMidiCCvalue);
currentControlValue = toParam(pMidiCC->getControl(pMidiCC_container), (synth_float_t)lastMidiCCvalue);
}
restoreTestSlider();
TestValueUpdate();
//[/UserButtonCode_button_assign_enable]
}
else if (buttonThatWasClicked == button_midi_learn)
{
//[UserButtonCode_button_midi_learn] -- add your button handler code here..
//[/UserButtonCode_button_midi_learn]
}
else if (buttonThatWasClicked == button_apply_on_patch_init)
{
//[UserButtonCode_button_apply_on_patch_init] -- add your button handler code here..
state = buttonThatWasClicked->getToggleState();
pMidiCC->setDoApplyOnPatchInit(pMidiCC_container, state);
restoreTestSlider();
TestValueUpdate();
//[/UserButtonCode_button_apply_on_patch_init]
}
//[UserbuttonClicked_Post]
//[/UserbuttonClicked_Post]
}
void MidiCC_PopUp::labelTextChanged (Label* labelThatHasChanged)
{
//[UserlabelTextChanged_Pre]
//[/UserlabelTextChanged_Pre]
if (labelThatHasChanged == label_MidiCC_ID)
{
//[UserLabelCode_label_MidiCC_ID] -- add your label text handling code here..
pMidiCC->setControllerID(pMidiCC_container, label_MidiCC_ID->getText().getIntValue());
label_MidiCC_ID->setText(String(pMidiCC->getControllerID(pMidiCC_container)), false);
button_midi_learn->setToggleState(false, false);
lastMidiCCvalue = pSavedMidiCCinfo[pMidiCC->getControllerID(pMidiCC_container)].value;
if (isEnabled())
{
currentParamValue = toParam(pMidiCC->getParam(pMidiCC_container), (synth_float_t)lastMidiCCvalue);
currentControlValue = toParam(pMidiCC->getControl(pMidiCC_container), (synth_float_t)lastMidiCCvalue);
}
restoreTestSlider();
TestValueUpdate();
//[/UserLabelCode_label_MidiCC_ID]
}
else if (labelThatHasChanged == label_control_min)
{
//[UserLabelCode_label_control_min] -- add your label text handling code here..
SetMin();
restoreTestSlider();
TestValueUpdate();
//[/UserLabelCode_label_control_min]
}
else if (labelThatHasChanged == label_control_max)
{
//[UserLabelCode_label_control_max] -- add your label text handling code here..
SetMax();
restoreTestSlider();
TestValueUpdate();
//[/UserLabelCode_label_control_max]
}
//[UserlabelTextChanged_Post]
//[/UserlabelTextChanged_Post]
}
void MidiCC_PopUp::sliderValueChanged (Slider* sliderThatWasMoved)
{
//[UsersliderValueChanged_Pre]
//[/UsersliderValueChanged_Pre]
if (sliderThatWasMoved == slider_test)
{
//[UserSliderCode_slider_test] -- add your slider handling code here..
if (doChangeParameter())
{
slider_test->setTooltip (String(toParam(pMidiCC->getParam(pMidiCC_container), (synth_float_t)slider_test->getValue())));
}
else
{
if (lastControlValue == 0)
slider_test->setTooltip (L"0.0");
else
slider_test->setTooltip (String(toParam(pMidiCC->getControl(pMidiCC_container), (synth_float_t)slider_test->getValue())));
}
TestValueUpdate();
//[/UserSliderCode_slider_test]
}
//[UsersliderValueChanged_Post]
//[/UsersliderValueChanged_Post]
}
//[MiscUserCode] You can add your own definitions of your custom methods or any other code here...
void MidiCC_PopUp::mouseWheelMove(const MouseEvent &/*event*/, const MouseWheelDetails &/*wheel*/)
{
}
void MidiCC_PopUp::GetMin()
{
if (doChangeParameter())
{
label_control_min->setText(String(pMidiCC->getParamMin(pMidiCC_container)), false);
}
else
{
label_control_min->setText(String(pMidiCC->getControlMin(pMidiCC_container)), false);
}
}
void MidiCC_PopUp::GetMax()
{
if (doChangeParameter())
{
label_control_max->setText(String(pMidiCC->getParamMax(pMidiCC_container)), false);
}
else
{
label_control_max->setText(String(pMidiCC->getControlMax(pMidiCC_container)), false);
}
}
void MidiCC_PopUp::SetMin()
{
synth_float_t value;
param_info_t *pConstraints = pMidiCC->getConstraints(pMidiCC_container);
param_info_t *pInfo = NULL;
value = (synth_float_t)label_control_min->getText().getFloatValue();
while (doChangeParameter())
{
pInfo = pMidiCC->getParam(pMidiCC_container);
if (value < pConstraints->pmin)
value = pConstraints->pmin;
if (value > pInfo->pmax)
value = pInfo->pmax;
// Min == Max => crash
if (value == pMidiCC->getParamMax(pMidiCC_container))
break;
pMidiCC->setParamMin(pMidiCC_container, value);
break;
}
while (!doChangeParameter())
{
pInfo = pMidiCC->getControl(pMidiCC_container);
if (fabs(value) > fabs(pConstraints->pmax))
value = pConstraints->pmax*fabs(value)/value;
// Min == Max => crash
if (value == pMidiCC->getControlMax(pMidiCC_container))
break;
pMidiCC->setControlMin(pMidiCC_container, value);
break;
}
label_control_min->setText(String(pInfo->pmin), false);
}
void MidiCC_PopUp::SetMax()
{
synth_float_t value;
param_info_t *pConstraints = pMidiCC->getConstraints(pMidiCC_container);
param_info_t *pInfo = NULL;
value = (synth_float_t)label_control_max->getText().getFloatValue();
while (doChangeParameter())
{
pInfo = pMidiCC->getParam(pMidiCC_container);
if (value > pConstraints->pmax)
value = pConstraints->pmax;
if (value < pInfo->pmin)
value = pInfo->pmin;
// Min == Max => crash
if (value == pMidiCC->getParamMin(pMidiCC_container))
break;
pMidiCC->setParamMax(pMidiCC_container, value);
break;
}
while (!doChangeParameter())
{
pInfo = pMidiCC->getControl(pMidiCC_container);
value = (synth_float_t)label_control_max->getText().getFloatValue();
if (fabs(value) > fabs(pConstraints->pmax))
value = pConstraints->pmax*fabs(value)/value;
// Min == Max => crash
if (value == pMidiCC->getControlMin(pMidiCC_container))
break;
pMidiCC->setControlMax(pMidiCC_container, value);
break;
}
label_control_max->setText(String(pInfo->pmax), false);
}
//[/MiscUserCode]
//==============================================================================
#if 0
/* -- Jucer information section --
This is where the Jucer puts all of its metadata, so don't change anything in here!
BEGIN_JUCER_METADATA
<JUCER_COMPONENT documentType="Component" className="MidiCC_PopUp" componentName="MidiCC PopUp"
parentClasses="public Component" constructorParams="JaySynthMidiCC *pMidiCC, int paramID, synth_float_t currParamValue, JaySynth::midiCC_info_t *pCurrMidiCCinfo, String name, MidiCC_PopUp_Listener *listener"
variableInitialisers="" snapPixels="2" snapActive="1" snapShown="1"
overlayOpacity="0.330000013" fixedSize="1" initialWidth="248"
initialHeight="280">
<BACKGROUND backgroundColour="ffffff">
<ROUNDRECT pos="0 4 244 274" cornerSize="10" fill="solid: ff2a64a5" hasStroke="0"/>
<ROUNDRECT pos="2 3 243 274" cornerSize="7" fill="solid: 2a98a5" hasStroke="1"
stroke="4, mitered, butt" strokeColour="solid: ffffffff"/>
<TEXT pos="16 122 94 20" fill="solid: ffffffff" hasStroke="0" text="Midi Controller"
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/>
<TEXT pos="16 48 62 20" fill="solid: ffffffff" hasStroke="0" text="Active"
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/>
<TEXT pos="16 68 59 20" fill="solid: ffffffff" hasStroke="0" text="Absolute"
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/>
<TEXT pos="16 142 75 20" fill="solid: ffffffff" hasStroke="0" text="Minimum"
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/>
<TEXT pos="16 162 75 20" fill="solid: ffffffff" hasStroke="0" text="Maximum"
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/>
<TEXT pos="18 194 46 20" fill="solid: ffffffff" hasStroke="0" text="Test it"
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/>
<TEXT pos="192 122 38 20" fill="solid: ffffffff" hasStroke="0" text="Learn"
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/>
<TEXT pos="16 88 120 20" fill="solid: ffffffff" hasStroke="0" text="Apply on patch init"
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/>
</BACKGROUND>
<TEXTBUTTON name="OK" id="267da4575448eb96" memberName="textButton_OK" virtualName=""
explicitFocusOrder="0" pos="22 238 202 22" buttonText="OK" connectedEdges="0"
needsCallback="1" radioGroupId="0"/>
<LABEL name="MidiCC ID" id="9e3707850116f781" memberName="label_MidiCC_ID"
virtualName="" explicitFocusOrder="0" pos="135 122 32 20" tooltip="This is the Midi-Controller Number"
textCol="ffffffff" edTextCol="ff000000" edBkgCol="0" hiliteCol="ffffff00"
labelText="0" editableSingleClick="1" editableDoubleClick="1"
focusDiscardsChanges="0" fontname="Default font" fontsize="15"
bold="0" italic="0" justification="34"/>
<LABEL name="Control Min" id="21f18ed07994e110" memberName="label_control_min"
virtualName="" explicitFocusOrder="0" pos="103 144 64 20" tooltip="Parameter minimum value"
textCol="ffffffff" edTextCol="ff000000" edBkgCol="0" hiliteCol="ffffff00"
labelText="0" editableSingleClick="1" editableDoubleClick="1"
focusDiscardsChanges="0" fontname="Default font" fontsize="15"
bold="0" italic="0" justification="34"/>
<LABEL name="Control Max" id="3ee0f72a9b303f9e" memberName="label_control_max"
virtualName="" explicitFocusOrder="0" pos="103 166 64 20" tooltip="Parameter maximum value"
textCol="ffffffff" edTextCol="ff000000" edBkgCol="0" hiliteCol="ffffff00"
labelText="0" editableSingleClick="1" editableDoubleClick="1"
focusDiscardsChanges="0" fontname="Default font" fontsize="15"
bold="0" italic="0" justification="34"/>
<SLIDER name="Test Slider" id="f0f88072fbe8ebb6" memberName="slider_test"
virtualName="" explicitFocusOrder="0" pos="64 192 168 26" tooltip="Test Slider"
min="0" max="1" int="0" style="LinearHorizontal" textBoxPos="NoTextBox"
textBoxEditable="0" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<TOGGLEBUTTON name="MoveParams Enable" id="fbf5e58207823635" memberName="button_move_sliders_enable"
virtualName="" explicitFocusOrder="0" pos="148 68 20 20" tooltip="If 'Absolute = no', the parameter is alterered relatively from the given slider position on the main window in the specified range. If ''Absolute = yes', the midi controller alters parameter absolutely in the specified range. In this mode sliders really move on the main window."
buttonText="" connectedEdges="0" needsCallback="1" radioGroupId="0"
state="0"/>
<TOGGLEBUTTON name="Assign Enable" id="ef80c20aeccf72e1" memberName="button_assign_enable"
virtualName="" explicitFocusOrder="0" pos="148 48 20 20" tooltip="Set this to make MIDI-Controller assignment active"
buttonText="" connectedEdges="0" needsCallback="1" radioGroupId="0"
state="0"/>
<TOGGLEBUTTON name="Midi Learn Button" id="df893ef1c6251377" memberName="button_midi_learn"
virtualName="" explicitFocusOrder="0" pos="172 122 20 20" tooltip="Set this to learn MIDI-Controller number from MIDI-controller movement"
txtcol="ffffffff" buttonText="" connectedEdges="0" needsCallback="1"
radioGroupId="0" state="0"/>
<LABEL name="Parameter Name" id="7bc54e014ee69b2f" memberName="label_parameter_name"
virtualName="" explicitFocusOrder="0" pos="12 12 212 24" textCol="ffffffff"
edTextCol="ff000000" edBkgCol="0" labelText="Parameter Name"
editableSingleClick="0" editableDoubleClick="0" focusDiscardsChanges="0"
fontname="Default font" fontsize="20" bold="0" italic="0" justification="36"/>
<TOGGLEBUTTON name="Apply on Patch Init Enable" id="2783ab3e54887ccc" memberName="button_apply_on_patch_init"
virtualName="" explicitFocusOrder="0" pos="148 88 20 20" tooltip="Set this to apply current Midi-Controller position on initialization of this patch (e.g. Program change)"
buttonText="" connectedEdges="0" needsCallback="1" radioGroupId="0"
state="0"/>
</JUCER_COMPONENT>
END_JUCER_METADATA
*/
#endif
+203
View File
@@ -0,0 +1,203 @@
/*
==============================================================================
This is an automatically generated file created by the Jucer!
Creation date: 19 Aug 2012 10:54:59am
Be careful when adding custom code to these files, as only the code within
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
and re-saved.
Jucer version: 1.12
------------------------------------------------------------------------------
The Jucer is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-6 by Raw Material Software ltd.
==============================================================================
*/
#ifndef __JUCER_HEADER_MIDICCPOPUP_MIDICCPOPUP_EA70576__
#define __JUCER_HEADER_MIDICCPOPUP_MIDICCPOPUP_EA70576__
//[Headers] -- You can add your own extra header files here --
#include "../JuceLibraryCode/JuceHeader.h"
#include "PluginProcessor.h"
//#include "juce.h"
class MidiCC_PopUp_Listener
{
public:
virtual void MidiCC_PopUp_event(int /*event*/) {};
};
//[/Headers]
//==============================================================================
/**
//[Comments]
An auto-generated component, created by the Jucer.
Describe your class and how it works here!
//[/Comments]
*/
class MidiCC_PopUp : public Component,
public ButtonListener,
public LabelListener,
public SliderListener
{
public:
//==============================================================================
MidiCC_PopUp (JaySynthMidiCC *pMidiCC, int paramID, synth_float_t currParamValue, JaySynth::midiCC_info_t *pCurrMidiCCinfo, String name, MidiCC_PopUp_Listener *listener);
~MidiCC_PopUp();
//==============================================================================
//[UserMethods] -- You can add your own custom methods in this section.
enum
{
POPUP_DELETED = 0,
POPUP_CREATED,
POPUP_SHOW,
POPUP_PARAM_CHANGED,
POPUP_OK
};
void addListener(MidiCC_PopUp_Listener *listener)
{
listeners.add (listener);
}
void show(void)
{
this->setVisible(true);
listeners.call (&MidiCC_PopUp_Listener::MidiCC_PopUp_event, POPUP_SHOW);
}
bool isEnabled(void)
{
return pMidiCC->isAssigned(pMidiCC_container);
}
bool doChangeParameter(void)
{
return pMidiCC->doChangeParameter(pMidiCC_container);
}
void setControllerID(int controllerID)
{
lastMidiCCvalue = pSavedMidiCCinfo[pMidiCC->getControllerID(pMidiCC_container)].value;
if (isEnabled())
{
currentParamValue = toParam(pMidiCC->getParam(pMidiCC_container), (synth_float_t)lastMidiCCvalue);
currentControlValue = toParam(pMidiCC->getControl(pMidiCC_container), (synth_float_t)lastMidiCCvalue);
}
restoreTestSlider();
TestValueUpdate();
if (!button_midi_learn->getToggleState())
return;
label_MidiCC_ID->setText(String(controllerID), true);
}
synth_float_t getCurrentControlValue(void)
{
return currentControlValue;
}
synth_float_t getCurrentParamValue(void)
{
return currentParamValue;
}
int getParamID(void)
{
return pMidiCC->getParamID(pMidiCC_container);
}
void TestValueUpdate()
{
if (doChangeParameter())
{
currentControlValue = 0;
currentParamValue = toParam(pMidiCC->getParam(pMidiCC_container), (synth_float_t)slider_test->getValue());
}
else
{
currentParamValue = savedParamValue;
currentControlValue = toParam(pMidiCC->getControl(pMidiCC_container), (synth_float_t)slider_test->getValue());
}
listeners.call (&MidiCC_PopUp_Listener::MidiCC_PopUp_event, POPUP_PARAM_CHANGED);
}
void restoreTestSlider()
{
if (doChangeParameter())
{
slider_test->setValue(toSlider(pMidiCC->getParam(pMidiCC_container), (synth_float_t)currentParamValue), true);
}
else
{
slider_test->setValue(toSlider(pMidiCC->getControl(pMidiCC_container), (synth_float_t)currentControlValue), true);
}
}
void GetMin();
void GetMax();
void SetMin();
void SetMax();
ComponentDragger myDragger;
void mouseDown (const MouseEvent& e)
{
myDragger.startDraggingComponent (this, e);
}
void mouseDrag (const MouseEvent& e)
{
myDragger.dragComponent (this, e, nullptr);
}
void mouseWheelMove(const MouseEvent &event, const MouseWheelDetails &wheel);
//[/UserMethods]
void paint (Graphics& g);
void resized();
void buttonClicked (Button* buttonThatWasClicked);
void labelTextChanged (Label* labelThatHasChanged);
void sliderValueChanged (Slider* sliderThatWasMoved);
//==============================================================================
juce_UseDebuggingNewOperator
private:
//[UserVariables] -- You can add your own custom variables in this section.
JaySynthMidiCC *pMidiCC;
midiCC_container_t *pMidiCC_container;
ListenerList <MidiCC_PopUp_Listener> listeners;
JaySynth::midiCC_info_t *pSavedMidiCCinfo;
synth_float_t lastMidiCCvalue;
synth_float_t savedParamValue;
synth_float_t currentParamValue;
synth_float_t currentControlValue;
synth_float_t lastControlValue;
synth_float_t lastParamValue;
//[/UserVariables]
//==============================================================================
TextButton* textButton_OK;
Label* label_MidiCC_ID;
Label* label_control_min;
Label* label_control_max;
Slider* slider_test;
ToggleButton* button_move_sliders_enable;
ToggleButton* button_assign_enable;
ToggleButton* button_midi_learn;
Label* label_parameter_name;
ToggleButton* button_apply_on_patch_init;
//==============================================================================
// (prevent copy constructor and operator= being generated..)
MidiCC_PopUp (const MidiCC_PopUp&);
const MidiCC_PopUp& operator= (const MidiCC_PopUp&);
};
#endif // __JUCER_HEADER_MIDICCPOPUP_MIDICCPOPUP_EA70576__
+879
View File
@@ -0,0 +1,879 @@
/*
==============================================================================
This file was auto-generated!
It contains the basic startup code for a Juce application.
==============================================================================
*/
#include <math.h>
#include "PluginProcessor.h"
#include "JaySynthAudioProcessorEditor.h"
#include "vector_utils.h"
JaySynthAudioProcessorEditor* getEditor(JaySynthAudioProcessor *pThis)
{
return dynamic_cast<JaySynthAudioProcessorEditor*>(pThis->getActiveEditor());
}
//==============================================================================
JaySynthAudioProcessor::JaySynthAudioProcessor()
{
currProgram = 0;
currpatch = &patches[currProgram];
the_editor = NULL;
m_isWavesAvailable = isWavesAvailable();
// Initialise the synth...
pSynth = new JaySynth(MAX_POLYPHONY, wavesGetPath());
pSynth->setNoteStealingEnabled(true);
pSynth->addListener(this);
setCurrentProgram(0);
m_limiter_env = 0;
startTimer (10);
#ifdef DEBUG
SynthDebug ("Jay Synth V %s (DEBUG) initialized.\n", JucePlugin_VersionString);
#else
SynthDebug ("Jay Synth V %s initialized.\n", JucePlugin_VersionString);
#endif
}
JaySynthAudioProcessor::~JaySynthAudioProcessor()
{
delete (pSynth);
}
void JaySynthAudioProcessor::timerCallback()
{
if (getEditor(this))
actionListener.callLimiterChanged(m_limiter_active);
}
String JaySynthAudioProcessor::wavesGetPath()
{
bool isExistent, isValid;
File pluginfile = File::getSpecialLocation (File::currentExecutableFile).getParentDirectory();
String wavespath = pluginfile.getFullPathName() + String("\\waves.bin");
File wavesfile = File(wavespath);
isExistent = wavesfile.existsAsFile();
isValid = true;
if (isExistent && isValid)
return wavespath;
return String::empty;
}
bool JaySynthAudioProcessor::isWavesAvailable()
{
return (wavesGetPath() != String::empty);
}
//==============================================================================
const String JaySynthAudioProcessor::getName() const
{
return JucePlugin_Name;
}
int JaySynthAudioProcessor::getNumParameters()
{
return SYNTH_NUM_PARAMS;
}
void JaySynthAudioProcessor::applyCurrentMidiControllers(void)
{
JaySynth::midiCC_info_t *pMidiCC_info;
int i;
for (i=0; i < NUM_MIDI_CONTROLLERS; i++)
{
pMidiCC_info = pSynth->getLastMidiCC_info(i);
if (pMidiCC_info)
applyMidiController(pMidiCC_info, false);
}
}
void JaySynthAudioProcessor::applyMidiController(JaySynth::midiCC_info_t *pMidiCC_info, bool forceApply)
{
int i, numDst, paramID;
midiCC_container_t *pMidi_container;
numDst = midCC_editBuffer.getNumDestinations(pMidiCC_info->ID);
for (i=0; i < numDst; i++)
{
pMidi_container = midCC_editBuffer.getDestination(pMidiCC_info->ID, i);
paramID = midCC_editBuffer.getParamID(pMidi_container);
if (midCC_editBuffer.doApplyOnPatchInit(pMidi_container) || forceApply)
{
if (midCC_editBuffer.doChangeParameter(pMidi_container))
{
setParam(paramID, toParam(midCC_editBuffer.getParam(pMidi_container), pMidiCC_info->value), false, false);
}
else
{
controlParam(midCC_editBuffer.getParamID(pMidi_container), toParam(midCC_editBuffer.getControl(pMidi_container), pMidiCC_info->value));
}
}
}
}
void JaySynthAudioProcessor::synthChanged(int type, void *pData)
{
JaySynth::midiCC_info_t *pMidiCC_info;
JaySynth::midi_note_info_t *pMidi_note_info;
switch(type)
{
case JaySynth::SYNTH_CHANGED_PARAM:
if (getEditor(this) != NULL)
actionListener.callParamChanged(*((int*)pData));
break;
case JaySynth::SYNTH_CHANGED_MIDICC:
pMidiCC_info = (JaySynth::midiCC_info_t*)pData;
applyMidiController(pMidiCC_info, true);
if (getEditor(this) != NULL)
actionListener.callMidiControllerChanged(pMidiCC_info->channel, pMidiCC_info->ID, (float)pMidiCC_info->value);
break;
case JaySynth::SYNTH_CHANGED_NOTE_PRESSED:
pMidi_note_info = (JaySynth::midi_note_info_t*)pData;
if (getEditor(this) != NULL)
actionListener.callMidiNotePressed(pMidi_note_info->note, (float)pMidi_note_info->velocity);
break;
case JaySynth::SYNTH_CHANGED_NOTE_RELEASED:
pMidi_note_info = (JaySynth::midi_note_info_t*)pData;
if (getEditor(this) != NULL)
actionListener.callMidiNoteReleased(pMidi_note_info->note, (float)pMidi_note_info->velocity);
break;
case JaySynth::SYNTH_CHANGED_NUM_VOICES_PLAYING:
if (getEditor(this) != NULL)
actionListener.callNumVoicesPlaying(*((int*)pData));
break;
default:
break;
}
};
float JaySynthAudioProcessor::getParameter (int index)
{
param_info_t *pParamInfo = getParamInfo(index);
if (!pParamInfo)
return 0;
return (float)toSlider(pParamInfo, pSynth->getParameter(index));
}
void JaySynthAudioProcessor::setParameter (int index, float newValue)
{
param_info_t *pParamInfo = getParamInfo(index);
if (!pParamInfo)
return;
setParam(index, toParam(pParamInfo, (synth_float_t)newValue), true, false);
}
synth_float_t JaySynthAudioProcessor::getParam(int index)
{
return (synth_float_t)pSynth->getParameter(index);
}
void JaySynthAudioProcessor::setParam(int index, synth_float_t param, bool doModifyPatch, bool doNotifyHost)
{
param_info_t *pParamInfo = getParamInfo(index);
if (!pParamInfo)
return;
if (doModifyPatch)
{
setPatchModified();
}
if (doNotifyHost)
sendParamChangeToHost(index, (float)toSlider(pParamInfo, param));
pSynth->setParameter(index, clampParam(pParamInfo, param));
}
void JaySynthAudioProcessor::controlParam(int index, synth_float_t param)
{
pSynth->setControl(index, param);
}
const String JaySynthAudioProcessor::getParameterName (int index)
{
param_info_t *pParamInfo = getParamInfo(index);
if (pParamInfo)
return pParamInfo->pName;
return String::empty;
}
const String JaySynthAudioProcessor::getParameterText (int index)
{
param_info_t *pParamInfo = getParamInfo(index);
switch (index)
{
case SYNTH_PARAM_VCF_TYPE:
switch ((int)pSynth->getParameter(index))
{
case VCF_FILTERTYPE_LOWPASS:
return "LPF";
case VCF_FILTERTYPE_HIGHPASS:
return "HPF";
case VCF_FILTERTYPE_BANDPASS:
return "BPF";
default:
return "Unknown (" + String((int)pSynth->getParameter(index)) + ")";
}
case SYNTH_PARAM_NOISE_ENABLE:
case SYNTH_PARAM_OSC_0_ENABLE:
case SYNTH_PARAM_OSC_1_ENABLE:
if (!(int)pSynth->getParameter(index))
return "Off";
return "On";
case SYNTH_PARAM_NOISE_SHAPE:
switch ((int)pSynth->getParameter(index))
{
case VOICE_NOISE_SHAPE_WHITE:
return "Uniform";
case VOICE_NOISE_SHAPE_PINK:
return "Gauss";
default:
return "Unknown (" + String((int)pSynth->getParameter(index)) + ")";
}
case SYNTH_PARAM_OSC_0_WAVEFORM:
case SYNTH_PARAM_OSC_1_WAVEFORM:
switch ((int)pSynth->getParameter(index))
{
case OSC_WAVEFORM_SAWTOOTH:
return "Saw";
case OSC_WAVEFORM_SQUARE:
return "Pulse";
case OSC_WAVEFORM_TRIANGLE:
return "Tri";
case OSC_WAVEFORM_SINE:
return "Sine";
default:
return "Unknown (" + String((int)pSynth->getParameter(index)) + ")";
}
case SYNTH_PARAM_LFO_0_SHAPE:
case SYNTH_PARAM_LFO_1_SHAPE:
case SYNTH_PARAM_LFO_2_SHAPE:
case SYNTH_PARAM_LFO_3_SHAPE:
switch ((int)pSynth->getParameter(index))
{
case LFO_WAVEFORM_SINE:
return "Sine";
case LFO_WAVEFORM_COSINE:
return "Cosine";
case LFO_WAVEFORM_SAW:
return "Saw";
case LFO_WAVEFORM_SQUARE:
return "Square";
case LFO_WAVEFORM_TRIANGLE:
return "Tri";
case LFO_WAVEFORM_SH_UNI:
return "S/H 1";
case LFO_WAVEFORM_SH_GAUSS:
return "S/H 2";
default:
return "Unknown (" + String((int)pSynth->getParameter(index)) + ")";
}
case SYNTH_PARAM_OSC_0_AM_SRC_0:
case SYNTH_PARAM_OSC_1_AM_SRC_0:
case SYNTH_PARAM_OSC_0_FM_SRC_0:
case SYNTH_PARAM_OSC_1_FM_SRC_0:
case SYNTH_PARAM_OSC_0_PWM_SRC_0:
case SYNTH_PARAM_OSC_1_PWM_SRC_0:
case SYNTH_PARAM_VCF_F_SRC_0:
case SYNTH_PARAM_VCF_Q_SRC_0:
case SYNTH_PARAM_VCA_AM_SRC_0:
case SYNTH_PARAM_VCA_PAN_SRC_0:
case SYNTH_PARAM_OSC_0_AM_SRC_1:
case SYNTH_PARAM_OSC_1_AM_SRC_1:
case SYNTH_PARAM_OSC_0_FM_SRC_1:
case SYNTH_PARAM_OSC_1_FM_SRC_1:
case SYNTH_PARAM_OSC_0_PWM_SRC_1:
case SYNTH_PARAM_OSC_1_PWM_SRC_1:
case SYNTH_PARAM_VCF_F_SRC_1:
case SYNTH_PARAM_VCF_Q_SRC_1:
switch ((int)pSynth->getParameter(index))
{
case 0:
return "Off";
case 1:
return "LFO 1";
case 2:
return "LFO 2";
case 3:
return "LFO 3";
case 4:
return "LFO 4";
default:
return "Unknown (" + String((int)pSynth->getParameter(index)) + ")";
}
case SYNTH_PARAM_LFO_0_MODE:
case SYNTH_PARAM_LFO_1_MODE:
case SYNTH_PARAM_LFO_2_MODE:
case SYNTH_PARAM_LFO_3_MODE:
switch ((int)pSynth->getParameter(index))
{
case VOICE_LFO_MODE_GLOBAL:
return "Global";
case VOICE_LFO_MODE_INDIVIDUAL:
return "Individual";
default:
return "Unknown (" + String((int)pSynth->getParameter(index)) + ")";
}
case SYNTH_PARAM_LFO_0_SYNC:
case SYNTH_PARAM_LFO_1_SYNC:
case SYNTH_PARAM_LFO_2_SYNC:
case SYNTH_PARAM_LFO_3_SYNC:
switch ((int)pSynth->getParameter(index))
{
case VOICE_LFO_SYNC_FREE:
return "Free";
case VOICE_LFO_SYNC_RESTART:
return "Restart";
default:
return "Unknown (" + String((int)pSynth->getParameter(index)) + ")";
}
default:
if (pParamInfo->pinterval == 0.0)
return String (pSynth->getParameter(index));
else
return String (pSynth->getParameter(index), (int)(-log(pParamInfo->pinterval)/log(10.0) + 0.5));
}
}
const String JaySynthAudioProcessor::getInputChannelName (int channelIndex) const
{
return String (channelIndex + 1);
}
const String JaySynthAudioProcessor::getOutputChannelName (int channelIndex) const
{
return String (channelIndex + 1);
}
bool JaySynthAudioProcessor::isInputChannelStereoPair (int /*index*/) const
{
return true;
}
bool JaySynthAudioProcessor::isOutputChannelStereoPair (int /*index*/) const
{
return true;
}
bool JaySynthAudioProcessor::acceptsMidi() const
{
#if JucePlugin_WantsMidiInput
return true;
#else
return false;
#endif
}
bool JaySynthAudioProcessor::producesMidi() const
{
#if JucePlugin_ProducesMidiOutput
return true;
#else
return false;
#endif
}
int JaySynthAudioProcessor::getNumPrograms()
{
return NUM_PROGRAMS;
}
int JaySynthAudioProcessor::getCurrentProgram()
{
return currProgram;
}
void JaySynthAudioProcessor::setCurrentProgram (int index)
{
int i;
param_info_t *pParamInfo;
if ((unsigned)index >= NUM_PROGRAMS)
index = 0;
currProgram = index;
currpatch = &patches[index];
// Set SYNTH_PARAM_TOTAL_NUM_VOICES first
setParam(SYNTH_PARAM_TOTAL_NUM_VOICES, currpatch->getParameter(SYNTH_PARAM_TOTAL_NUM_VOICES), false, false);
midCC_editBuffer = *currpatch->getMidiCC();
pSynth->setMidiCC_editBuffer(&midCC_editBuffer);
pSynth->ClearControls();
for (i=0; i < SYNTH_NUM_PARAMS; i++)
{
pParamInfo = getParamInfo(i);
setParam(i, currpatch->getParameter(i), false, true);
}
unisonoModeChanged();
humanizeModeChanged();
humanizeVarianceChanged_VCO();
humanizeVarianceChanged_VCF();
humanizeVarianceChanged_ENV();
perVoiceControlsChanged();
clearPatchModified();
// toDo: do this by synth->setParam via message
if (getEditor(this))
{
actionListener.callProgramChanged();
for (i=0; i < SYNTH_NUM_PARAMS; i++)
getEditor(this)->paramUpdate(i, false);
}
applyCurrentMidiControllers();
updateHostDisplay();
}
const String JaySynthAudioProcessor::getProgramName (int index)
{
return patches[index].getName();
}
void JaySynthAudioProcessor::changeProgramName (int index, const String& newName)
{
patches[index].setName(newName);
if (getEditor(this))
{
actionListener.callProgramChanged();
}
}
//==============================================================================
void JaySynthAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock)
{
// Use this method as the place to do any pre-playback
// initialisation that you need..
m_fs = sampleRate;
pSynth->setSampleRate (sampleRate);
pSynth->setBufsize (samplesPerBlock);
keyboardState.reset();
}
void JaySynthAudioProcessor::releaseResources()
{
// When playback stops, you can use this as an opportunity to free up any
// spare memory, etc.
keyboardState.reset();
}
void JaySynthAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages)
{
const int numSamples = buffer.getNumSamples();
int i;
float *buf1 = buffer.getSampleData (0, 0);
float *buf2 = buffer.getSampleData (1, 0);
synth_float_t limiter_env[SYNTH_MAX_BUFSIZE];
synth_float_t limiter_gain[SYNTH_MAX_BUFSIZE];
synth_float_t buf[2][SYNTH_MAX_BUFSIZE];
synth_float_t x, limiter_ar, limiter_af, limiter_threshold;
float synth_gain;
// Now pass any incoming midi messages to our keyboard state object, and let it
// add messages to the buffer if the user is clicking on the on-screen keys
keyboardState.processNextMidiBuffer (midiMessages, 0, numSamples, true);
// First remove garbage from buffers
buffer.clear (0, 0, numSamples);
buffer.clear (1, 0, numSamples);
// and now get the synth to process these midi events and generate its output.
// Render individual voices
pSynth->renderNextBlock (buffer, midiMessages, 0, numSamples);
// apply master volume
synth_gain = (float)pSynth->getVolume();
for (i=0; i <numSamples; i++)
buf[0][i] = (synth_float_t)buf1[i] * synth_gain;
for (i=0; i <numSamples; i++)
buf[1][i] = (synth_float_t)buf2[i] * synth_gain;
// Limiter
limiter_ar = 1.0/(SYNTH_LIMITER_RISE_TIME*m_fs);
limiter_af = 5.0/(SYNTH_LIMITER_FALL_TIME*m_fs);
limiter_threshold = pow((synth_float_t)10.0, (synth_float_t)SYNTH_LIMITER_THRESHOLD/20);
for (i=0; i <numSamples; i++)
{
x = max(fabs(buf[0][i]), fabs(buf[1][i]));
if (m_limiter_env < x)
m_limiter_env += limiter_ar*(x - m_limiter_env);
else
m_limiter_env += limiter_af*(x - m_limiter_env);
limiter_env[i] = m_limiter_env;
}
m_limiter_active = 0;
for (i=0; i <numSamples; i++)
{
limiter_gain[i] = (float)(limiter_threshold/max(limiter_threshold, limiter_env[i]));
if (limiter_gain[i] < 1.0)
m_limiter_active = 1;
}
for (i=0; i <numSamples; i++)
buf1[i] = (float)(buf[0][i]*limiter_gain[i]);
for (i=0; i <numSamples; i++)
buf2[i] = (float)(buf[1][i]*limiter_gain[i]);
// In case we have more outputs than inputs, we'll clear any output
// channels that didn't contain input data, (because these aren't
// guaranteed to be empty - they may contain garbage).
// for (int i = getNumInputChannels(); i < getNumOutputChannels(); ++i)
// {
// buffer.clear (i, 0, buffer.getNumSamples());
// }
}
//==============================================================================
bool JaySynthAudioProcessor::hasEditor() const
{
return true; // (change this to false if you choose to not supply an editor)
}
AudioProcessorEditor* JaySynthAudioProcessor::createEditor()
{
int i;
the_editor = (void*) new JaySynthAudioProcessorEditor (this, m_isWavesAvailable);
if (the_editor)
{
actionListener.callProgramChanged();
for (i=0; i < SYNTH_NUM_PARAMS; i++)
((JaySynthAudioProcessorEditor*)the_editor)->paramUpdate(i, false);
}
return (AudioProcessorEditor*)the_editor;
}
//==============================================================================
// magic number to identify memory blocks that we've stored as XML
const uint32 magicXmlNumber = 0x21324356;
void JaySynthAudioProcessor::copyXmlToBinary (const XmlElement& xml, juce::MemoryBlock& destData)
{
const String xmlString (xml.createDocument (String::empty, true, false));
const int stringLength = xmlString.getNumBytesAsUTF8();
destData.setSize ((size_t) stringLength + 10);
char* const d = static_cast<char*> (destData.getData());
*(uint32*) d = ByteOrder::swapIfBigEndian ((const uint32) magicXmlNumber);
*(uint32*) (d + 4) = ByteOrder::swapIfBigEndian ((const uint32) stringLength);
xmlString.copyToUTF8 (d + 8, stringLength + 1);
}
XmlElement* JaySynthAudioProcessor::getXmlFromBinary (const void* data,
const int sizeInBytes)
{
XmlElement *pResult = nullptr;
if (sizeInBytes > 8
&& ByteOrder::littleEndianInt (data) == magicXmlNumber)
{
const int stringLength = (int) ByteOrder::littleEndianInt (addBytesToPointer (data, 4));
XmlDocument doc(String::fromUTF8 ((static_cast<const char*> (data)) + 8, jmin ((sizeInBytes - 8), stringLength)));
if (stringLength > 0)
pResult = doc.getDocumentElement();
if (doc.getLastParseError() != String::empty)
{
deleteAndZero(pResult);
}
}
return pResult;
}
const String JaySynthAudioProcessor::getParameterNameXML (int index)
{
String name = getParameterName(index);
name = name.removeCharacters (String("."));
name = name.replaceCharacter (' ','_');
return name;
}
void JaySynthAudioProcessor::getStateInformation (MemoryBlock& destData)
{
int i, progID;
synth_float_t value;
JaySynthSound *pPatch;
XmlElement *pXML;
// Create an outer XML element..
ScopedPointer<XmlElement>xml = new XmlElement("JSYNTH_BANK");
MemoryOutputStream outputStream(destData, false);
MemoryBlock tmpBlock(8192*1024, /*initialiseToZero*/true);
GZIPCompressorOutputStream GZIPEnc(&outputStream, /*compressionLevel*/0, /*deleteDestStreamWhenDestroyed*/false, /*windowBits*/0);
if (isPatchModified() || midCC_editBuffer.isMidiCCmodified())
{
for (i=0; i < SYNTH_NUM_PARAMS; i++)
{
value = getParam(i);
currpatch->setParameter(i, value); // Copy synth param to current program
}
currpatch->getMidiCC()->copyMidiCC(&midCC_editBuffer); // Copy MidiCC edit buffer to patch
}
for (progID=0; progID < NUM_PROGRAMS; progID++)
{
pXML = xml->createNewChildElement (String("PATCH_") + String(progID));
pPatch = &patches[progID];
pXML->setAttribute ("ID", progID);
pXML->setAttribute ("NAME", pPatch->getName());
for (i=0; i < SYNTH_NUM_PARAMS; i++)
{
value = pPatch->getParameter(i);
pXML->setAttribute (getParameterNameXML(i), String(value, 10));
}
pPatch->getMidiCC()->exportXML(pXML);
}
setCurrentProgram(getCurrentProgram());
// then use this helper function to stuff it into the binary blob and return it..
copyXmlToBinary (*xml, tmpBlock);
GZIPEnc.write(tmpBlock.getData(), tmpBlock.getSize());
outputStream.flush();
#if 0
//#ifdef SYNTH_DEBUG
{
File file(String("C:\\Users\\jens\\JaySynth\\bank.xml"));
file.create();
xml->writeToFile (/*const File &destinationFile*/file, /*const String &dtdToUse*/"JSYNTH_BANK_FILE" /*, const String &encodingType="UTF-8", int lineWrapLength=60*/);
}
#endif
}
void JaySynthAudioProcessor::setStateInformation (const void* data, int sizeInBytes)
{
int i, progID, uncompressedSize;
synth_float_t value;
JaySynthSound *pPatch;
XmlElement *pXML;
String lastError;
ScopedPointer<XmlElement> xmlState = NULL;
void* pData;
int size;
ScopedPointer<char> pUncompressedData;
pUncompressedData = new char[8192*1024];
MemoryInputStream inputStream(data, sizeInBytes, false);
GZIPDecompressorInputStream GZIPDec(inputStream);
uncompressedSize = GZIPDec.read(pUncompressedData, 8192*1024);
pData = (void *)data;
size = sizeInBytes;
if (uncompressedSize)
{
pData = (void *)pUncompressedData;
size = uncompressedSize;
}
xmlState = getXmlFromBinary(pData, size);
if (xmlState != 0)
{
// make sure that it's actually our type of XML object..
if (xmlState->hasTagName ("JSYNTH_BANK"))
{
pXML = xmlState->getFirstChildElement();
while(pXML)
{
progID = pXML->getIntAttribute("ID");
if (progID >= NUM_PROGRAMS)
break;
pPatch = &patches[progID];
// ok, now pull out our parameters..
pPatch->setName(pXML->getStringAttribute("NAME"));
for (i=0; i < SYNTH_NUM_PARAMS; i++)
{
value = (synth_float_t) pXML->getDoubleAttribute (getParameterNameXML(i), pPatch->getParameter(i));
if (i==SYNTH_PARAM_TUNE)
{
if (value > 400.0)
{
value = 1200*log(value/440)/log(2.0);
}
}
pPatch->setParameter(i, value);
}
pPatch->getMidiCC()->importXML(pXML);
pXML = pXML->getNextElement();
}
}
setCurrentProgram(getCurrentProgram());
}
}
void JaySynthAudioProcessor::getCurrentProgramStateInformation (MemoryBlock& destData)
{
// You should use this method to store your parameters in the memory block.
// You could do that either as raw data, or use the XML or ValueTree classes
// as intermediaries to make it easy to save and load complex data.
// You should use this method to store your parameters in the memory block.
// Here's an example of how you can use XML to make it easy and more robust:
int i;
synth_float_t value;
MemoryOutputStream outputStream (destData, false);
MemoryBlock tmpBlock(2*65536, /*initialiseToZero*/true);
GZIPCompressorOutputStream GZIPEnc(&outputStream, /*compressionLevel*/0, /*deleteDestStreamWhenDestroyed*/false, /*windowBits*/0);
// Create an outer XML element..
ScopedPointer<XmlElement>xml = new XmlElement("JSYNTH_PATCH");
if (isPatchModified() || midCC_editBuffer.isMidiCCmodified())
{
for (i=0; i < SYNTH_NUM_PARAMS; i++)
{
value = getParam(i);
currpatch->setParameter(i, value); // Copy synth param to current program
}
currpatch->getMidiCC()->copyMidiCC(&midCC_editBuffer); // Copy MidiCC edit buffer to patch
}
xml->setAttribute ("NAME", currpatch->getName());
for (i=0; i < SYNTH_NUM_PARAMS; i++)
{
value = currpatch->getParameter(i);
xml->setAttribute (getParameterNameXML(i), String(value, 10));
}
currpatch->getMidiCC()->exportXML(xml);
setCurrentProgram(getCurrentProgram());
// then use this helper function to stuff it into the binary blob and return it..
copyXmlToBinary (*xml, tmpBlock);
GZIPEnc.write(tmpBlock.getData(), tmpBlock.getSize());
#if 0
//#ifdef SYNTH_DEBUG
{
File file(String("C:\\Users\\jens\\JaySynth\\") + String(currpatch->getName()) + String(".xml"));
file.create();
xml->writeToFile (/*const File &destinationFile*/file, /*const String &dtdToUse*/"JSYNTH_PATCH_FILE" /*, const String &encodingType="UTF-8", int lineWrapLength=60*/);
}
#endif
}
void JaySynthAudioProcessor::setCurrentProgramStateInformation (const void* data, int sizeInBytes)
{
// You should use this method to restore your parameters from this memory block,
// whose contents will have been created by the getStateInformation() call.
int i, uncompressedSize;
synth_float_t value;
ScopedPointer<XmlElement> xmlState = NULL;
void* pData;
int size;
ScopedPointer<char> pUncompressedData;
pUncompressedData = new char[2*65536];
MemoryInputStream inputStream(data, sizeInBytes, false);
GZIPDecompressorInputStream GZIPDec(inputStream);
uncompressedSize = GZIPDec.read(pUncompressedData, 2*65536);
pData = (void *)data;
size = sizeInBytes;
if (uncompressedSize)
{
pData = (void *)pUncompressedData;
size = uncompressedSize;
}
xmlState = getXmlFromBinary(pData, size);
if (xmlState != 0)
{
// make sure that it's actually our type of XML object..
if (xmlState->hasTagName ("JSYNTH_PATCH"))
{
// ok, now pull out our parameters..
currpatch->setName(xmlState->getStringAttribute("NAME"));
for (i=0; i < SYNTH_NUM_PARAMS; i++)
{
value = (synth_float_t) xmlState->getDoubleAttribute (getParameterNameXML(i), currpatch->getParameter(i));
if (i==SYNTH_PARAM_TUNE)
{
if (value > 400.0)
{
value = 1200*log(value/440)/log(2.0);
}
}
currpatch->setParameter(i, value);
}
}
currpatch->getMidiCC()->importXML(xmlState);
setCurrentProgram(getCurrentProgram());
}
}
//==============================================================================
// This creates new instances of the plugin..
AudioProcessor* JUCE_CALLTYPE createPluginFilter()
{
return new JaySynthAudioProcessor();
}
+342
View File
@@ -0,0 +1,342 @@
/*
==============================================================================
This file was auto-generated!
It contains the basic startup code for a Juce application.
==============================================================================
*/
#ifndef __PLUGINPROCESSOR_H_20F201CA__
#define __PLUGINPROCESSOR_H_20F201CA__
#include "../JuceLibraryCode/JuceHeader.h"
#include "synth_defs.h"
#include "JaySynthSound.h"
#include "JaySynth.h"
//==============================================================================
/**
*/
class JaySynthActionListener : public ActionBroadcaster
{
public:
enum
{
JAYSYNTH_CHANGED_PARAM = 0,
JAYSYNTH_CHANGED_MIDICC,
JAYSYNTH_CHANGED_NOTE_PRESSED,
JAYSYNTH_CHANGED_NOTE_RELEASED,
JAYSYNTH_CHANGED_NUM_VOICES_PLAYING,
JAYSYNTH_CHANGED_PROGRAM,
JAYSYNTH_CHANGED_LIMITER,
JAYSYNTH_CHANGED_SIZE
};
void callParamChanged (int paramID)
{
String s;
s = String("type=") + String(JAYSYNTH_CHANGED_PARAM);
s = s + String(" ");
s = s + String("paramID=") + String(paramID);
s = s + String(" ");
sendActionMessage(s);
}
void callMidiControllerChanged (int channel, int controllerID, float value)
{
String s;
s = String("type=") + String(JAYSYNTH_CHANGED_MIDICC);
s = s + String(" ");
s = s + String("ch=") + String(channel);
s = s + String(" ");
s = s + String("id=") + String(controllerID);
s = s + String(" ");
s = s + String("value=") + String((float)value);
s = s + String(" ");
sendActionMessage(s);
}
void callMidiNotePressed (int midi_note, float velocity)
{
String s;
s = String("type=") + String(JAYSYNTH_CHANGED_NOTE_PRESSED);
s = s + String(" ");
s = s + String("note=") + String(midi_note);
s = s + String(" ");
s = s + String("velocity=") + String((float)velocity);
s = s + String(" ");
sendActionMessage(s);
}
void callMidiNoteReleased (int midi_note, float velocity)
{
String s;
s = String("type=") + String(JAYSYNTH_CHANGED_NOTE_RELEASED);
s = s + String(" ");
s = s + String("note=") + String(midi_note);
s = s + String(" ");
s = s + String("velocity=") + String((float)velocity);
s = s + String(" ");
sendActionMessage(s);
}
void callProgramChanged(void)
{
String s;
s = String("type=") + String(JAYSYNTH_CHANGED_PROGRAM);
s = s + String(" ");
sendActionMessage(s);
}
void callLimiterChanged (int value)
{
String s;
s = String("type=") + String(JAYSYNTH_CHANGED_LIMITER);
s = s + String(" ");
s = s + String("value=") + String(value);
s = s + String(" ");
sendActionMessage(s);
}
void callNumVoicesPlaying (int value)
{
String s;
s = String("type=") + String(JAYSYNTH_CHANGED_NUM_VOICES_PLAYING);
s = s + String(" ");
s = s + String("value=") + String(value);
s = s + String(" ");
sendActionMessage(s);
}
void callBinary(void *pData, int size)
{
String s;
s.createStringFromData(pData, size);
sendActionMessage(s);
}
void add (ActionListener *listener)
{
addActionListener((ActionListener*)listener);
}
void remove (ActionListener *listener)
{
removeActionListener((ActionListener*)listener);
}
private:
};
class JaySynthAudioProcessor :
public Timer,
public AudioProcessor,
public JaySynthSound,
public JaySynthListener
{
public:
//==============================================================================
JaySynthAudioProcessor();
~JaySynthAudioProcessor();
//==============================================================================
void prepareToPlay (double sampleRate, int samplesPerBlock);
void releaseResources();
void processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages);
//==============================================================================
AudioProcessorEditor* createEditor();
bool hasEditor() const;
//==============================================================================
const String getName() const;
int getNumParameters();
void setParameter (int index, float newValue);
float getParameter (int index);
void setParam(int index, synth_float_t param, bool doModifyPatch, bool doNotifyHost);
synth_float_t getParam(int index);
void controlParam(int index, synth_float_t newValue);
const String getParameterName (int index);
const String getParameterText (int index);
const String getInputChannelName (int channelIndex) const;
const String getOutputChannelName (int channelIndex) const;
bool isInputChannelStereoPair (int index) const;
bool isOutputChannelStereoPair (int index) const;
bool acceptsMidi() const;
bool producesMidi() const;
//==============================================================================
int getNumPrograms();
int getCurrentProgram();
void setCurrentProgram (int index);
const String getProgramName (int index);
void changeProgramName (int index, const String& newName);
//==============================================================================
void copyXmlToBinary (const XmlElement& xml, juce::MemoryBlock& destData);
XmlElement* getXmlFromBinary (const void* data, const int sizeInBytes);
const String getParameterNameXML (int index);
void getCurrentProgramStateInformation (MemoryBlock& destData);
void setCurrentProgramStateInformation (const void* data, int sizeInBytes);
void getStateInformation (MemoryBlock& destData);
void setStateInformation (const void* data, int sizeInBytes);
//==============================================================================
// These properties are public so that our editor component can access them
// A bit of a hacky way to do it, but it's only a demo! Obviously in your own
// code you'll do this much more neatly..
// this is kept up to date with the midi messages that arrive, and the UI component
// registers with it so it can represent the incoming messages
MidiKeyboardState keyboardState;
// this keeps a copy of the last set of time info that was acquired during an audio
// callback - the UI component will read this and display it.
AudioPlayHead::CurrentPositionInfo lastPosInfo;
// these are used to persist the UI's size - the values are stored along with the
// filter's other parameters, and the UI component will update them when it gets
// resized.
void synthChanged(int type, void *pData);
void addActionListener(ActionListener* listener)
{
actionListener.add(listener);
}
void removeActionListener(ActionListener* listener)
{
actionListener.remove(listener);
}
void sendParamChangeToHost(int index, float value)
{
AudioProcessor::sendParamChangeMessageToListeners(index, value);
}
JaySynth::midiCC_info_t* getLastMidiControllers(void)
{
return pSynth->getLastMidiCC_infos();
}
JaySynth::midi_note_info_t* getLastMidiNoteInfos(void)
{
return pSynth->getLastMidiNote_infos();
}
void setCurrentProgramName (String name)
{
changeProgramName(getCurrentProgram(), name);
updateHostDisplay();
}
const String getCurrentProgramName (void)
{
String s;
if (isPatchModified() || getMidiCC_editBuffer()->isMidiCCmodified())
{
s = getProgramName(getCurrentProgram()) + String(" [edited]");
}
else
{
s = getProgramName(getCurrentProgram());
}
return s;
};
bool isPatchModified(void)
{
return isModified;
}
void clearPatchModified(void)
{
isModified = false;
}
void setPatchModified(void)
{
isModified = true;
}
JaySynthMidiCC *getMidiCC_editBuffer(void)
{
return &midCC_editBuffer;
}
void applyMidiController(JaySynth::midiCC_info_t *pMidiCC_info, bool forceApply);
void applyCurrentMidiControllers(void);
void humanizeModeChanged(void)
{
pSynth->humanizeModeChanged();
}
void unisonoModeChanged(void)
{
pSynth->unisonoModeChanged();
}
void humanizeVarianceChanged_VCO(void)
{
pSynth->humanizeVarianceChanged_VCO();
}
void humanizeVarianceChanged_VCF(void)
{
pSynth->humanizeVarianceChanged_VCF();
}
void humanizeVarianceChanged_ENV(void)
{
pSynth->humanizeVarianceChanged_ENV();
}
void perVoiceControlChanged(int paramID)
{
pSynth->updateParameter(paramID);
}
void perVoiceControlsChanged(void)
{
pSynth->updateParameters();
}
String wavesGetPath();
bool isWavesAvailable();
void timerCallback();
private:
// the synth!
bool isModified;
bool m_isWavesAvailable;
int lastUIWidth, lastUIHeight;
synth_float_t master_volume, m_fs;
int currProgram;
JaySynthSound patches[NUM_PROGRAMS];
JaySynthSound *currpatch;
JaySynthActionListener actionListener;
JaySynth *pSynth;
void *the_editor;
JaySynthMidiCC midCC_editBuffer;
int m_limiter_active;
synth_float_t m_limiter_env;
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JaySynthAudioProcessor);
};
//typedef JaySynthAudioProcessor::Listener JaySynthAudioProcessorListener;
#endif // __PLUGINPROCESSOR_H_20F201CA__
File diff suppressed because it is too large Load Diff
+194
View File
@@ -0,0 +1,194 @@
/*
==============================================================================
This is an automatically generated file created by the Jucer!
Creation date: 30 Sep 2012 11:31:53am
Be careful when adding custom code to these files, as only the code within
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
and re-saved.
Jucer version: 1.12
------------------------------------------------------------------------------
The Jucer is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-6 by Raw Material Software ltd.
==============================================================================
*/
#ifndef __JUCER_HEADER_VELKEYPOPUP_VELKEYPOPUP_9719552A__
#define __JUCER_HEADER_VELKEYPOPUP_VELKEYPOPUP_9719552A__
//[Headers] -- You can add your own extra header files here --
#include "../JuceLibraryCode/JuceHeader.h"
#include "synth_defs.h"
#include "PluginProcessor.h"
class VelKey_PopUp_Listener
{
public:
virtual void VelKey_PopUp_event(int /*event*/) {};
};
//[/Headers]
#include "graph_window.h"
//==============================================================================
/**
//[Comments]
An auto-generated component, created by the Jucer.
Describe your class and how it works here!
//[/Comments]
*/
class VelKey_PopUp : public Component,
public SliderListener,
public ButtonListener,
public LabelListener,
public ComboBoxListener
{
public:
//==============================================================================
VelKey_PopUp (JaySynthMidiCC *pMidiCC, int paramID, synth_float_t currParamValue, JaySynth::midi_note_info_t *pCurrentMidiNoteInfo, String name, VelKey_PopUp_Listener *listener);
~VelKey_PopUp();
//==============================================================================
//[UserMethods] -- You can add your own custom methods in this section.
enum
{
POPUP_DELETED = 0,
POPUP_CREATED,
POPUP_SHOW,
POPUP_PARAM_CHANGED,
POPUP_OK
};
void setKeyVel(int note, float velocity);
void addListener(VelKey_PopUp_Listener *listener)
{
listeners.add (listener);
}
void show(void)
{
this->setVisible(true);
listeners.call (&VelKey_PopUp_Listener::VelKey_PopUp_event, POPUP_SHOW);
}
int getParamID(void)
{
return m_paramID;
}
ComponentDragger myDragger;
void mouseDown (const MouseEvent& e)
{
myDragger.startDraggingComponent (this, e);
}
void mouseDrag (const MouseEvent& e)
{
myDragger.dragComponent (this, e, nullptr);
}
void createNoteNameTbl(void);
const String getNoteName(int midinotnumber);
void displayUpdate(void);
void setCurrParam(int paramID, float param);
//[/UserMethods]
void paint (Graphics& g);
void resized();
void sliderValueChanged (Slider* sliderThatWasMoved);
void buttonClicked (Button* buttonThatWasClicked);
void labelTextChanged (Label* labelThatHasChanged);
void comboBoxChanged (ComboBox* comboBoxThatHasChanged);
//==============================================================================
juce_UseDebuggingNewOperator
private:
//[UserVariables] -- You can add your own custom variables in this section.
param_info_t m_velKey_constraints;
param_info_t m_shape_xform, m_skew_xform;
JaySynthMidiCC *pMidiCC;
midiCC_container_t *pMidiCC_container;
ListenerList <VelKey_PopUp_Listener> listeners;
synth_float_t m_currParamValue;
int m_paramID;
int m_label_prec, m_label_shape_prec, m_label_skew_prec;
JaySynth::midi_note_info_t m_currentMidiNoteInfo;
bool m_isFlipped_vel, m_isFlipped_key;
String m_text_vel_min, m_text_vel_max;
String m_text_key_min, m_text_key_max;
String notename_tbl[128];
//[/UserVariables]
//==============================================================================
Label* label_parameter_name;
GroupComponent* groupComponent3;
GroupComponent* groupComponent;
GroupComponent* groupComponent2;
GraphWindow* m_graph_vel;
Slider* slider_vel_kexp;
Slider* slider_vel_scenter;
Label* label_vel_kexp;
Label* label_vel_scenter;
Label* label_vel_min;
Slider* slider_vel_min;
TextButton* textButton_OK;
ToggleButton* button_vel_assign_enable;
Label* label_vel_ymin;
Label* label_vel_ymax;
Label* label_vel_x100;
Label* label_vel_x0;
GraphWindow* m_graph_key;
Slider* slider_key_kexp;
Slider* slider_key_scenter;
Label* label_key_kexp;
Label* label_vel_scenter2;
Label* label_key_min;
Slider* slider_key_min;
ToggleButton* button_key_assign_enable;
Label* label_key_ymin;
Label* label_key_ymax;
Label* label_key_x100;
Label* label_key_x0;
ComboBox* comboBoxOPSel;
Label* label_key;
Label* label_vel;
Slider* slider_vel_max;
Label* label_vel_max;
Label* label_key_max;
Slider* slider_key_max;
Label* label_vel_shape;
Label* label_vel_skew;
Label* label_key_shape;
Label* label_key_skew;
Label* label_vel_skew_text;
Label* label_key_skew_text;
Label* label_vel_shape_text;
Label* label_key_shape_text;
Label* label_vel_max_text;
Label* label_vel_min_text;
Label* label_key_min_text;
Label* label_key_max_text;
Label* label_vel_y;
Label* label_key_y;
Label* label_vel_x;
Label* label_key_x;
TextButton* m_btn_flip_vel;
TextButton* m_btn_flip_key;
//==============================================================================
// (prevent copy constructor and operator= being generated..)
VelKey_PopUp (const VelKey_PopUp&);
const VelKey_PopUp& operator= (const VelKey_PopUp&);
};
#endif // __JUCER_HEADER_VELKEYPOPUP_VELKEYPOPUP_9719552A__
+172
View File
@@ -0,0 +1,172 @@
/*
==============================================================================
This is an automatically generated file created by the Jucer!
Creation date: 18 Sep 2012 6:24:20am
Be careful when adding custom code to these files, as only the code within
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
and re-saved.
Jucer version: 1.12
------------------------------------------------------------------------------
The Jucer is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-6 by Raw Material Software ltd.
==============================================================================
*/
//[Headers] You can add your own extra header files here...
//[/Headers]
#include "graph_window.h"
//[MiscUserDefs] You can add your own user definitions and misc code here...
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
//[/MiscUserDefs]
//==============================================================================
GraphWindow::GraphWindow ()
: Component (L"graph_window")
{
//[UserPreSize]
//[/UserPreSize]
setSize (160, 120);
//[Constructor] You can add your own custom stuff here..
frame_width = 1;
m_markerX = 0;
paramInfoInit(&curve, 0, NULL);
paramInfoSet(&curve, 1, 1, 0.5, -1, 0, +1, 0);
//[/Constructor]
}
GraphWindow::~GraphWindow()
{
//[Destructor_pre]. You can add your own custom destruction code here..
//[/Destructor_pre]
//[Destructor]. You can add your own custom destruction code here..
paramInfoFree(&curve);
//[/Destructor]
}
//==============================================================================
void GraphWindow::paint (Graphics& g)
{
//[UserPrePaint] Add your own custom painting code here..
goto skip;
//[/UserPrePaint]
g.setColour (Colours::white);
g.drawRoundedRectangle (3.0f, 3.0f, 156.0f, 116.0f, 1.0000f, 2.0000f);
//[UserPaint] Add your own custom painting code here..
skip:
int minX = 0;
int minY = frame_width;
int maxX = getWidth();
int maxY = getHeight()-frame_width;
int sizeX = maxX-minX;
int sizeY = maxY-minY;
g.setColour (Colour(0xFFB0B0B0));
g.drawLine(minX, (int)((1-evalCurve(m_markerX))*sizeY) + 1.5*minY, maxX, (int)((1-evalCurve(m_markerX))*sizeY) + 1.5*minY);
g.drawLine(m_markerX*sizeX, minY, m_markerX*sizeX, maxY);
g.setColour (Colours::white);
float dx = 1.0/sizeX;
float x0 = 0;
float x1 = dx;
float y0, y1;
for (int i=minX+1; i <= maxX; i++)
{
y0 = evalCurve(x0);
y1 = evalCurve(x1);
x0 = x1;
x1 += dx;
g.drawLine(i-1, /*(1-0.5*(1+y0))*sizeY*/(1-y0)*sizeY + minY, i, /*(1-0.5*(1+y1))*sizeY*/(1-y1)*sizeY + minY);
}
g.setColour (Colours::white);
g.drawRect (0.0, 0.0, (float)getWidth(), (float)getHeight(), frame_width);
//[/UserPaint]
}
void GraphWindow::resized()
{
//[UserResized] Add your own custom resize handling here..
repaint();
//[/UserResized]
}
float GraphWindow::evalCurve(float x)
{
// return min(m_max, max(m_min, toParam(&curve, x)));
if (m_max > m_min)
return (toParam(&curve, x)-m_min)/(m_max - m_min);
else
return (toParam(&curve, x)-m_max)/(m_min - m_max);
}
//[MiscUserCode] You can add your own definitions of your custom methods or any other code here...
void GraphWindow::Draw(float minimum, float maximum, param_info_t *pParamInfo)
{
m_min = minimum;
m_max = maximum;
paramInfoCopy(&curve, pParamInfo);
repaint();
}
void GraphWindow::SetMarkerX(float x)
{
m_markerX = x;
repaint();
}
//[/MiscUserCode]
//==============================================================================
#if 0
/* -- Jucer information section --
This is where the Jucer puts all of its metadata, so don't change anything in here!
BEGIN_JUCER_METADATA
<JUCER_COMPONENT documentType="Component" className="GraphWindow" componentName="graph_window"
parentClasses="public Component" constructorParams="" variableInitialisers=""
snapPixels="4" snapActive="1" snapShown="1" overlayOpacity="0.330000013"
fixedSize="1" initialWidth="160" initialHeight="120">
<BACKGROUND backgroundColour="ffffff">
<ROUNDRECT pos="3 3 156 116" cornerSize="1" fill="solid: ffffff" hasStroke="1"
stroke="2, mitered, butt" strokeColour="solid: ffffffff"/>
</BACKGROUND>
</JUCER_COMPONENT>
END_JUCER_METADATA
*/
#endif
+82
View File
@@ -0,0 +1,82 @@
/*
==============================================================================
This is an automatically generated file created by the Jucer!
Creation date: 18 Sep 2012 6:24:20am
Be careful when adding custom code to these files, as only the code within
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
and re-saved.
Jucer version: 1.12
------------------------------------------------------------------------------
The Jucer is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-6 by Raw Material Software ltd.
==============================================================================
*/
#ifndef __JUCER_HEADER_GRAPHWINDOW_GRAPHWINDOW_E0AFC61E__
#define __JUCER_HEADER_GRAPHWINDOW_GRAPHWINDOW_E0AFC61E__
//[Headers] -- You can add your own extra header files here --
#include "../JuceLibraryCode/JuceHeader.h"
#include "synth_defs.h"
//[/Headers]
//==============================================================================
/**
//[Comments]
An auto-generated component, created by the Jucer.
Describe your class and how it works here!
//[/Comments]
*/
class GraphWindow : public Component
{
public:
//==============================================================================
GraphWindow ();
~GraphWindow();
//==============================================================================
//[UserMethods] -- You can add your own custom methods in this section.
void Draw(float minimum, float maximum, param_info_t *pParamInfo);
void SetMarkerX(float x);
float evalCurve(float x);
//[/UserMethods]
void paint (Graphics& g);
void resized();
//==============================================================================
juce_UseDebuggingNewOperator
private:
//[UserVariables] -- You can add your own custom variables in this section.
float frame_width;
float m_min;
float m_max;
float m_markerX;
param_info_t curve;
//[/UserVariables]
//==============================================================================
//==============================================================================
// (prevent copy constructor and operator= being generated..)
GraphWindow (const GraphWindow&);
const GraphWindow& operator= (const GraphWindow&);
};
#endif // __JUCER_HEADER_GRAPHWINDOW_GRAPHWINDOW_E0AFC61E__
Binary file not shown.

After

Width:  |  Height:  |  Size: 820 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 830 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

+433
View File
@@ -0,0 +1,433 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include "synth_defs.h"
#include "blit.h"
#include "fir/fir2.h"
#include "vector_utils.h"
// --------------------------------------------------------------
// internal funcs
// --------------------------------------------------------------
INT32 smin(INT32 x, INT32 y)
{
if (x < y)
return x;
return y;
}
INT32 smax(INT32 x, INT32 y)
{
if (x > y)
return x;
return y;
}
UINT32 umin(UINT32 x, UINT32 y)
{
if (x < y)
return x;
return y;
}
UINT32 umax(UINT32 x, UINT32 y)
{
if (x > y)
return x;
return y;
}
void IP_ModInit(blit_common_t *pCom)
{
INT32 n, k;
synth_float_t *pN_K = pCom->N_K;
synth_float_t *pK = pCom->K;
for (n=0; n <= BLIT_INTEROLATION_ORDER; n++)
{
for (k=0; k <= BLIT_INTEROLATION_ORDER; k++)
{
if (k == n)
continue;
*(pN_K++) = (synth_float_t)1 / (n-k);
*(pK++) = (synth_float_t)k;
}
}
}
synth_float_t IP_Process(blit_t *pObj, synth_float_t *pLUT, synth_float_t m)
{
INT32 mi, j;
INT32 n, k;
synth_float_t hn, y = 0, delay;
synth_float_t *pN_K = pObj->pCom->N_K;
synth_float_t *pK = pObj->pCom->K;
mi = (INT32)m;
delay = m - (synth_float_t)mi;
j = (INT32)BLIT_INTEROLATION_ORDER;
for (n=0; n <= BLIT_INTEROLATION_ORDER; n++)
{
hn = (synth_float_t)1;
for (k=0; k < BLIT_INTEROLATION_ORDER; k++)
{
hn *= (*(pN_K++) * (delay - *(pK++)));
}
y += hn*pLUT[smax(0, mi-j)];
j--;
}
return y;
}
void BLIT_freq_update(blit_t *pObj, synth_float_t scale)
{
synth_float_t p;
pObj->freq_update_req = 0;
// p = pObj->fs/(pObj->f*scale*pObj->fm);
p = pObj->fs/(scale*pObj->fm);
pObj->dx = (synth_float_t)1.0/p;
pObj->m = umin(BLIT_NUM_HARM_MAX-1, (UINT32)((synth_float_t)SYNTH_BANDWIDTH*2.0*(int)((p/2)) + 0));
}
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void BLIT_ModInit(blit_common_t *pCom)
{
int m, n;
synth_float_t **ppKaiser;
synth_float_t x, dx, a, b, blit, blep;
// Calculate table sizes
pCom->pTableSizes = (UINT32*)malloc(BLIT_NUM_HARM_MAX*sizeof(UINT32));
for (m=0; m < BLIT_NUM_HARM_MAX; m++)
{
pCom->pTableSizes[m] = m*BLIT_TABLE_OVERSAMPLING;
if (pCom->pTableSizes[m] < BLIT_TABLE_SIZE_MIN)
pCom->pTableSizes[m] = BLIT_TABLE_SIZE_MIN;
}
// Generate Kaiser window
ppKaiser = (synth_float_t**)malloc(BLIT_NUM_HARM_MAX*sizeof(synth_float_t*));
for (m=0; m < BLIT_NUM_HARM_MAX; m++)
{
ppKaiser[m] = (synth_float_t*)malloc(pCom->pTableSizes[m]*sizeof(synth_float_t));
CalcKaiser(NULL, ppKaiser[m], 8.f, pCom->pTableSizes[m]);
}
// Allocate BLIT table
pCom->ppBLEP = (synth_float_t**)malloc(BLIT_NUM_HARM_MAX*sizeof(synth_float_t*));
for (m=0; m < BLIT_NUM_HARM_MAX; m++)
{
pCom->ppBLEP[m] = (synth_float_t*)malloc(pCom->pTableSizes[m]*sizeof(synth_float_t));
}
// Generate BLIT
for (m=0; m < BLIT_NUM_HARM_MAX; m++)
{
dx = (synth_float_t)1/(pCom->pTableSizes[m]);
x = -0.5;
blep = 0;
for (n=0; n < pCom->pTableSizes[m]; n++)
{
a = sin(x*pi);
b = sin(m*x*pi);
if (a == 0)
blit = (synth_float_t)m;
else
blit = b/a * ppKaiser[m][n];
blep += blit;
pCom->ppBLEP[m][n] = blep/(pCom->pTableSizes[m]);
x += dx;
}
}
/*
m = BLIT_NUM_HARM_MAX/2;
for (n=0; n < BLIT_TABLE_SIZE; n++)
{
SynthDebug("BLEP[%d][%d] = %.14f\n", m, n, pCom->ppBLEP[m][n]);
}
for (n=0; n < BLIT_TABLE_SIZE; n++)
{
SynthDebug("Kaiser[%d] = %.14f\n", n, pKaiser[n]);
}
*/
for (m=0; m < BLIT_NUM_HARM_MAX; m++)
{
free(ppKaiser[m]);
}
free(ppKaiser);
// Precalculate Interpolation constants
IP_ModInit(pCom);
}
void BLIT_ModFree(blit_common_t *pCom)
{
int m;
if (pCom->ppBLEP)
{
for (m=0; m < BLIT_NUM_HARM_MAX; m++)
{
free(pCom->ppBLEP[m]);
}
free(pCom->ppBLEP);
}
free(pCom->pTableSizes);
}
void BLIT_Init(blit_t *pObj, blit_common_t *pCom, synth_float_t fs)
{
pObj->pCom = pCom;
pObj->fs = fs;
pObj->dutycycle = 0.5;
BLIT_Reset(pObj, 0);
pObj->bufsize = 0;
BLIT_SetBufsize(pObj, SYNTH_MAX_BUFSIZE);
BLIT_Prepare(pObj, SYNTH_MAX_BUFSIZE);
}
void BLIT_Free(blit_t *pObj)
{
BLIT_SetBufsize(pObj, 0);
}
void BLIT_SetBufsize(blit_t *pObj, UINT32 size)
{
if (pObj->bufsize == size)
return;
pObj->bufsize = size;
if (!size)
return;
}
void BLIT_SetFS(blit_t *pObj, synth_float_t fs)
{
pObj->fs = fs;
pObj->freq_update_req = 1;
}
void BLIT_Prepare(blit_t *pObj, UINT32 len)
{
synth_float_t pitch_buf[SYNTH_MAX_BUFSIZE];
synth_float_t out_buf[SYNTH_MAX_BUFSIZE];
len = min(len, SYNTH_MAX_BUFSIZE);
// Let Oscillators run with different pitches to randomize phase
Add_inplace_VS(pitch_buf, 0, 8*440.0*(1+0.01*(synth_float_t)rand()/RAND_MAX), len);
BLIT_Process_SAW_Vector(pObj, pitch_buf, NULL, NULL, NULL, out_buf, len);
BLIT_Process_SQR_Vector(pObj, pitch_buf, NULL, NULL, NULL, NULL, out_buf, len);
BLIT_Process_TRI_Vector(pObj, pitch_buf, NULL, NULL, NULL, out_buf, len);
}
void BLIT_Reset(blit_t *pObj, synth_float_t phase)
{
pObj->saw_x = fmod(0.5f + phase, 1);
pObj->sqr_x1 = fmod(0.5f + phase, 1);
pObj->sqr_x2 = fmod(0.5f + phase, 1);
pObj->sqr_pol1 = 1; // ToDo: Adjust according to phase
pObj->sqr_pol2 = 1; // ToDo: Adjust according to phase
pObj->tri_x = fmod(0.5f + phase, 1);
pObj->tri_sum = 0; // ToDo: Adjust according to phase
pObj->tri_pol = 1; // ToDo: Adjust according to phase
pObj->fm = 1;
pObj->pwm = 0;
pObj->pulse_offset = 0; // ToDo: Adjust according to phase
}
void BLIT_Start(blit_t *pObj)
{
pObj->freq_update_req = 1;
}
void BLIT_SetDutyCycle(blit_t *pObj, synth_float_t duty_cycle)
{
pObj->dutycycle = duty_cycle;
}
void BLIT_Process_SAW_Vector(blit_t *pObj, synth_float_t *pPitch, synth_float_t *pCV_fm, UINT32 *pSyncIn, UINT32 *pSyncOut, synth_float_t *pOut, UINT32 len)
{
UINT32 i, is_slave, m;
synth_float_t out;
synth_float_t blep, n;
blit_common_t *pCom = pObj->pCom;
is_slave = (pSyncIn != NULL) && (pSyncOut == NULL);
if (pSyncOut)
memset(pSyncOut, 0, len*sizeof(synth_float_t));
// Create output
for (i=0; i< len; i++)
{
if (pObj->freq_update_req)
{
BLIT_freq_update(pObj, pPitch[i]);
}
if (pObj->saw_x >= (synth_float_t)0.5)
{
pObj->saw_x -= 1;
if (pCV_fm)
{
pObj->fm = (synth_float_t)pow((synth_float_t)2, pCV_fm[i]);
}
BLIT_freq_update(pObj, pPitch[i]);
}
m = pObj->m;
// Lagrange interpolation
n = (pObj->saw_x+0.5)*((pCom->pTableSizes[m])-1);
blep = IP_Process(pObj, &pCom->ppBLEP[m][0], n);
out = pObj->saw_x - blep;
pObj->saw_x += pObj->dx;
*(pOut++) = 2*(out+0.5);
}
}
void BLIT_Process_SQR_Vector(blit_t *pObj, synth_float_t *pPitch, synth_float_t *pCV_fm, synth_float_t *pCV_pwm, UINT32 *pSyncIn, UINT32 *pSyncOut, synth_float_t *pOut, UINT32 len)
{
UINT32 i, is_slave, m;
synth_float_t blep1, blep2, n;
synth_float_t dutycycle;
blit_common_t *pCom = pObj->pCom;
is_slave = (pSyncIn != NULL) && (pSyncOut == NULL);
if (pSyncOut)
memset(pSyncOut, 0, len*sizeof(synth_float_t));
// Create output
for (i=0; i< len; i++)
{
if (pObj->freq_update_req)
{
BLIT_freq_update(pObj, pPitch[i]);
}
if (pObj->sqr_x1 >= (synth_float_t)0.5)
{
pObj->sqr_x1 -= 1;
pObj->sqr_pol1 = !pObj->sqr_pol1;
if (pCV_fm)
{
pObj->fm = (synth_float_t)pow((synth_float_t)2, pCV_fm[i]);
}
if (pCV_pwm)
{
pObj->pwm = (synth_float_t)pCV_pwm[i];
}
dutycycle = min(1, max(0, pObj->dutycycle + pObj->pwm));
pObj->pulse_offset = 2*(dutycycle-0.5);
pObj->sqr_x2 = pObj->sqr_x1 + dutycycle - 1;
pObj->sqr_pol2 = pObj->sqr_pol1;
BLIT_freq_update(pObj, pPitch[i]);
}
while (pObj->sqr_x2 >= (synth_float_t)0.5)
{
pObj->sqr_pol2 = !pObj->sqr_pol2;
pObj->sqr_x2 -= 1;
}
while (pObj->sqr_x2 < (synth_float_t)-0.5)
{
pObj->sqr_pol2 = !pObj->sqr_pol2;
pObj->sqr_x2 += 1;
}
m = pObj->m;
// Lagrange interpolation
n = (pObj->sqr_x1+0.5)*((pCom->pTableSizes[m])-1);
blep1 = IP_Process(pObj, &pCom->ppBLEP[m][0], n);
if (pObj->sqr_pol1)
blep1 = 1 - blep1;
n = (pObj->sqr_x2+0.5)*((pCom->pTableSizes[m])-1);
blep2 = IP_Process(pObj, &pCom->ppBLEP[m][0], n);
if (pObj->sqr_pol2)
blep2 = 1 - blep2;
*(pOut++) = 4*(blep1-0.5)*(blep2-0.5) - pObj->pulse_offset;
pObj->sqr_x1 += pObj->dx;
pObj->sqr_x2 += pObj->dx;
}
}
void BLIT_Process_TRI_Vector(blit_t *pObj, synth_float_t *pPitch, synth_float_t *pCV_fm, UINT32 *pSyncIn, UINT32 *pSyncOut, synth_float_t *pOut, UINT32 len)
{
UINT32 i, is_slave, m;
synth_float_t out;
synth_float_t blep, n;
blit_common_t *pCom = pObj->pCom;
is_slave = (pSyncIn != NULL) && (pSyncOut == NULL);
if (pSyncOut)
memset(pSyncOut, 0, len*sizeof(synth_float_t));
for (i=0; i< len; i++)
{
if (pObj->freq_update_req)
{
BLIT_freq_update(pObj, pPitch[i]);
}
if (pObj->tri_x >= (synth_float_t)0.5)
{
pObj->tri_x -= 1;
pObj->tri_pol = !pObj->tri_pol;
if (pCV_fm)
{
pObj->fm = (synth_float_t)pow((synth_float_t)2, pCV_fm[i]);
}
BLIT_freq_update(pObj, 2*pPitch[i]);
}
m = pObj->m;
// Lagrange interpolation
n = (pObj->tri_x+0.5)*((pCom->pTableSizes[m])-1);
// blep = IP_Process(&_sg_ppBLEP[m][0], n);
// No interpolation
blep = pCom->ppBLEP[m][(UINT32)n];
if (pObj->tri_pol)
out = 1 - blep;
else
out = blep;
pObj->tri_sum += 4*(out-0.5)*pObj->dx;
*(pOut++) = pObj->tri_sum;
pObj->tri_x += pObj->dx;
}
}
+61
View File
@@ -0,0 +1,61 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#ifndef _BLIT_H_
#define _BLIT_H_
#include "synth_defs.h"
// --------------------------------------------------------------
// Types
// --------------------------------------------------------------
typedef struct _sblit_common_t
{
UINT32 *pTableSizes;
synth_float_t **ppBLEP;
synth_float_t N_K[(BLIT_INTEROLATION_ORDER+0)*(BLIT_INTEROLATION_ORDER+1)];
synth_float_t K[(BLIT_INTEROLATION_ORDER+0)*(BLIT_INTEROLATION_ORDER+1)];
} blit_common_t;
typedef struct _sblit_t
{
blit_common_t *pCom;
synth_float_t fs, fm, pwm, dutycycle, pulse_offset;
synth_float_t saw_x, x2, dx;
synth_float_t sqr_x1, sqr_x2, tri;
synth_float_t tri_x, tri_sum;
UINT32 m, tri_pol, sqr_pol1, sqr_pol2;
UINT32 freq_update_req, bufsize;
} blit_t;
// --------------------------------------------------------------
#if defined(__cplusplus)
extern "C" {
#endif
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void BLIT_ModInit(blit_common_t *pCom);
void BLIT_ModFree(blit_common_t *pCom);
void BLIT_Init(blit_t *pObj, blit_common_t *pCom, synth_float_t fs);
void BLIT_Free(blit_t *pObj);
void BLIT_SetBufsize(blit_t *pObj, UINT32 size);
void BLIT_SetFS(blit_t *pObj, synth_float_t fs);
void BLIT_Reset(blit_t *pObj, synth_float_t phase);
void BLIT_Start(blit_t *pObj);
void BLIT_Prepare(blit_t *pObj, UINT32 len);
void BLIT_SetDutyCycle(blit_t *pObj, synth_float_t duty_cycle);
void BLIT_Process_SAW_Vector(blit_t *pObj, synth_float_t *pPitch, synth_float_t *pCV_fm, UINT32 *pSyncIn, UINT32 *pSyncOut, synth_float_t *pOut, UINT32 len);
void BLIT_Process_SQR_Vector(blit_t *pObj, synth_float_t *pPitch, synth_float_t *pCV_fm, synth_float_t *pCV_pwm, UINT32 *pSyncIn, UINT32 *pSyncOut, synth_float_t *pOut, UINT32 len);
void BLIT_Process_TRI_Vector(blit_t *pObj, synth_float_t *pPitch, synth_float_t *pCV_fm, UINT32 *pSyncIn, UINT32 *pSyncOut, synth_float_t *pOut, UINT32 len);
#if defined(__cplusplus)
}
#endif
// --------------------------------------------------------------
#endif // _BLIT_H_
+208
View File
@@ -0,0 +1,208 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include "synth_defs.h"
#include "env.h"
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void ENV_Init(envgen_t *pObj, synth_float_t fs)
{
pObj->fs = fs;
ENV_Reset(pObj);
ENV_Param2Set(pObj, ENV_PARAM2_A, 0.001);
ENV_Param2Set(pObj, ENV_PARAM2_D, 1.000);
ENV_Param2Set(pObj, ENV_PARAM2_S, 1.000);
ENV_Param2Set(pObj, ENV_PARAM2_R, 1.000);
pObj->bufsize = 0;
pObj->pOut = NULL;
ENV_SetBufsize(pObj, SYNTH_MAX_BUFSIZE);
}
void ENV_Free(envgen_t *pObj)
{
ENV_SetBufsize(pObj, 0);
}
void ENV_SetBufsize(envgen_t *pObj, UINT32 size)
{
if (pObj->bufsize == size)
return;
pObj->bufsize = size;
if (pObj->pOut)
free(pObj->pOut);
pObj->pOut = NULL;
if (!size)
return;
pObj->pOut = (synth_float_t*)malloc(pObj->bufsize*sizeof(synth_float_t));
}
void ENV_SetFS(envgen_t *pObj, synth_float_t fs)
{
pObj->fs = fs;
}
void ENV_Reset(envgen_t *pObj)
{
pObj->state = env_state_idle;
pObj->s = 0;
pObj->k = (synth_float_t)1/ENV_KE;
}
void ENV_Event(envgen_t *pObj, UINT32 type)
{
switch(type)
{
case env_event_trigger:
case env_event_retrigger:
// pObj->sr = 0;
pObj->state = env_state_attack;
// pObj->k = (synth_float_t)1/ENV_KE;
// if (type == env_event_retrigger)
// {
// pObj->a_r = 1.f/(0.001*pObj->fs);
// pObj->b_r = 1.f - pObj->a_r;
// pObj->state = env_state_attack_retrigger;
//
// }
break;
case env_event_release:
if (pObj->state == env_state_idle)
break;
// if (pObj->state == env_state_attack)
// pObj->sf = pObj->sr;
// if (pObj->state == env_state_sustain)
// pObj->sf = pObj->param.Vs/pObj->k;
pObj->state = env_state_release;
break;
default:
break;
}
};
void ENV_Param2Set(envgen_t *pObj, UINT32 type, synth_float_t value)
{
switch(type)
{
case ENV_PARAM2_A:
pObj->param.Ta = max(ENV_MIN_A, value);
pObj->a_a = 1.f/(pObj->param.Ta*pObj->fs);
pObj->b_a = 1.f - pObj->a_a;
break;
case ENV_PARAM2_D:
pObj->param.Td = max(ENV_MIN_D, value);
pObj->a_d = 5.f/(pObj->param.Td*pObj->fs);
pObj->b_d = 1.f - pObj->a_d;
break;
case ENV_PARAM2_S:
pObj->param.Vs = value;
break;
case ENV_PARAM2_R:
pObj->param.Tr = max(ENV_MIN_R, value);
pObj->a_r = 5.f/(pObj->param.Tr*pObj->fs);
pObj->b_r = 1.f - pObj->a_r;
break;
default:
break;
}
}
UINT32 ENV_ParamGet(envgen_t *pObj, UINT32 type)
{
return 0;
}
INT32 ENV_IsIdle(envgen_t *pObj)
{
return pObj->state == env_state_idle;
}
synth_float_t* ENV_ProcessDataV(envgen_t *pObj, UINT32 len)
{
synth_float_t *pX, y;
pX = pObj->pOut;
while(len)
{
y = pObj->k*pObj->s;
switch (pObj->state)
{
case env_state_idle:
break;
case env_state_attack:
// y = pObj->k*pObj->sr;
if (y >= 1.0)
{
// pObj->af = 5.f/(pObj->param.Td*pObj->fs);
// pObj->bf = 1.f - pObj->af;
// pObj->k = (synth_float_t)1/ENV_KE;
// pObj->sf = pObj->sr;
pObj->state = env_state_decay;
}
pObj->s = pObj->a_a + pObj->b_a*pObj->s;
break;
case env_state_attack_retrigger:
pObj->sf = pObj->b_r*pObj->sf;
if (pObj->sf <= ENV_TOL)
{
pObj->a_r = 5.f/(pObj->param.Tr*pObj->fs);
pObj->b_r = 1.f - pObj->a_r;
pObj->state = env_state_attack;
}
break;
case env_state_decay:
if (y <= pObj->param.Vs)
{
pObj->state = env_state_sustain;
}
pObj->s = pObj->b_d*pObj->s;
break;
case env_state_sustain:
y = pObj->param.Vs;
break;
case env_state_release:
if (y <= ENV_TOL)
{
pObj->state = env_state_idle;
}
pObj->s = pObj->b_r*pObj->s;
break;
default:
break;
}
*(pX++) = y;
len--;
}
return pObj->pOut;
}
+94
View File
@@ -0,0 +1,94 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#ifndef _ENV_H_
#define _ENV_H_
#include "synth_defs.h"
#define ENV_TOL ((synth_float_t)(1E-4))
#define ENV_KE ((synth_float_t)(1-exp(-1)))
#define ENV_MIN_A (0.001) // s
#define ENV_MIN_D (0.005) // s
#define ENV_MIN_R (0.005) // s
// --------------------------------------------------------------
// Types
// --------------------------------------------------------------
enum
{
ENV_PARAM2_A,
ENV_PARAM2_D,
ENV_PARAM2_S,
ENV_PARAM2_R,
ENV_PARAM2_END
};
enum
{
env_state_idle = 0,
env_state_attack,
env_state_attack_retrigger,
env_state_decay,
env_state_sustain,
env_state_release
};
enum
{
env_event_trigger = 0,
env_event_retrigger,
env_event_release,
};
typedef struct _senv_param_t
{
synth_float_t Ta;
synth_float_t Td;
synth_float_t Vs;
synth_float_t Tr;
} env_param_t;
typedef struct _senvgen_t
{
synth_float_t fs;
UINT32 bufsize;
UINT32 state;
env_param_t param;
synth_float_t k, s, sr, sf;
synth_float_t a_a, b_a;
synth_float_t a_d, b_d;
synth_float_t a_r, b_r;
synth_float_t *pOut;
} envgen_t;
// --------------------------------------------------------------
#if defined(__cplusplus)
extern "C" {
#endif
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void ENV_Init(envgen_t *pObj, synth_float_t fs);
void ENV_Free(envgen_t *pObj);
void ENV_Reset(envgen_t *pObj);
void ENV_SetBufsize(envgen_t *pObj, UINT32 size);
void ENV_SetFS(envgen_t *pObj, synth_float_t fs);
void ENV_Event(envgen_t *pObj, UINT32 type);
void ENV_Param2Set(envgen_t *pObj, UINT32 type, synth_float_t value);
UINT32 ENV_ParamGet(envgen_t *pObj, UINT32 type);
INT32 ENV_IsIdle(envgen_t *pObj);
INT32 ENV_IsStage(envgen_t *pObj, UINT32 stage_num);
synth_float_t* ENV_ProcessDataV(envgen_t *pObj, UINT32 len);
#if defined(__cplusplus)
}
#endif
// --------------------------------------------------------------
#endif // _ENV_H_
+542
View File
@@ -0,0 +1,542 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include "synth_defs.h"
#include "lfo.h"
// --------------------------------------------------------------
// internal funcs
// --------------------------------------------------------------
void LFO_freq_update(lfo_t *pObj)
{
synth_float_t f;
f = pObj->param[LFO_PARAM2_FREQ];
pObj->b = 2.0 * sin(f*pi / pObj->fs);
pObj->dx = f/pObj->fs;
if (pObj->param[LFO_PARAM2_DELAY] > 0)
{
pObj->delay_dx = 1.0/(pObj->fs*pObj->param[LFO_PARAM2_DELAY]);
}
else
{
pObj->delay_dx = 1.0;
}
pObj->attack_a = 1.0/(pObj->fs*pObj->param[LFO_PARAM2_ATTACK]*LFO_KE);
}
void LFO_smmother_update(lfo_t *pObj)
{
pObj->smooth_is_negative = (pObj->param[LFO_PARAM2_SMOOTH] < 0);
if (fabs(pObj->param[LFO_PARAM2_SMOOTH]) < 0.001)
{
pObj->smooth_b = 1;
pObj->smooth_is_negative = 0;
}
else
{
pObj->smooth_b = fabs((synth_float_t)5/(pObj->param[LFO_PARAM2_SMOOTH]*pObj->fs));
}
pObj->smooth_a = 1 - pObj->smooth_b;
}
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void LFO_Init(lfo_t *pObj, synth_float_t fs)
{
pObj->fs = fs;
pObj->pOut = NULL;
pObj->bufsize = 0;
pObj->param[LFO_PARAM2_WAVEFORM] = LFO_WAVEFORM_SINE;
pObj->param[LFO_PARAM2_FREQ] = 1;
pObj->param[LFO_PARAM2_SMOOTH] = 0.001; // seconds
pObj->param[LFO_PARAM2_DELAY] = 0; // seconds
pObj->param[LFO_PARAM2_ATTACK] = 0; // seconds
pObj->sh_sample = 0;
pObj->out = 0;
pObj->sqr = 0;
pObj->tri = 0;
pObj->gain = 1;
pObj->offset = 0.5;
LFO_Reset(pObj, 0);
pObj->freq_update_req = 0;
LFO_SetBufsize(pObj, SYNTH_MAX_BUFSIZE);
Noise_Init(&pObj->noise, 1+(UINT32)clock() * (UINT32)clock());
}
void LFO_Free(lfo_t *pObj)
{
LFO_SetBufsize(pObj, 0);
}
void LFO_SetBufsize(lfo_t *pObj, UINT32 size)
{
if (pObj->bufsize == size)
return;
pObj->bufsize = size;
if (pObj->pOut)
free(pObj->pOut);
pObj->pOut = NULL;
if (!size)
return;
pObj->pOut = (synth_float_t*)malloc(pObj->bufsize*sizeof(synth_float_t));
}
void LFO_SetFS(lfo_t *pObj, synth_float_t fs)
{
pObj->fs = fs;
LFO_freq_update(pObj);
}
void LFO_Reset(lfo_t *pObj, synth_float_t initial_phase)
{
pObj->a = 0.5;
pObj->y[0] = pObj->a*cos(2*pi*initial_phase);
pObj->y[1] = pObj->a*sin(2*pi*initial_phase);
pObj->x = initial_phase;
pObj->out = 0;
pObj->sqr = 0;
pObj->tri = 0;
pObj->delay_x = 0;
pObj->attack_y = 0;
LFO_freq_update(pObj);
LFO_smmother_update(pObj);
}
void LFO_Param2Set(lfo_t *pObj, UINT32 type, synth_float_t value)
{
switch(type)
{
case LFO_PARAM2_WAVEFORM:
if (pObj->param[type] == (UINT32)value)
break;
pObj->param[type] = (UINT32)value;
pObj->freq_update_req = 1;
break;
case LFO_PARAM2_FREQ:
pObj->param[type] = value;
pObj->freq_update_req = 1;
break;
case LFO_PARAM2_SMOOTH:
pObj->param[type] = value;
LFO_smmother_update(pObj);
break;
case LFO_PARAM2_DELAY:
pObj->param[type] = value;
pObj->freq_update_req = 1;
break;
case LFO_PARAM2_ATTACK:
pObj->param[type] = value;
pObj->freq_update_req = 1;
break;
case LFO_PARAM2_SYMMETRY:
pObj->param[type] = value;
pObj->gain = 1;
pObj->offset = 0.5 *(1 + value) - 1;
break;
default:
break;
}
}
synth_float_t* LFO_ProcessDataV(lfo_t *pObj, UINT32 len)
{
synth_float_t *pOut, out, in;
UINT32 i, i0;
pOut = pObj->pOut;
// Process Delay
for (i=0; i< len; i++)
{
pObj->delay_x += pObj->delay_dx;
if (pObj->delay_x >= 1.0)
break;
in = (synth_float_t)0;
pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in;
out = pObj->out;
if (pObj->smooth_is_negative)
out = 2*in - pObj->out;
*(pOut++) = out;
if (pObj->freq_update_req)
{
pObj->freq_update_req = 0;
LFO_freq_update(pObj);
}
}
i0 = i;
if (pObj->param[LFO_PARAM2_WAVEFORM] == LFO_WAVEFORM_SAW)
{
// Create phase
for (i=i0; i< len; i++)
{
in = pObj->x + pObj->offset;
pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in;
out = pObj->out;
if (pObj->smooth_is_negative)
out = 2*in - pObj->out;
*(pOut++) = out*pObj->attack_y;
pObj->attack_y += pObj->attack_a*(1-pObj->attack_y);
pObj->x += pObj->dx;
if (pObj->x >= 1.f)
{
pObj->x -= 1.f;
}
if (pObj->freq_update_req)
{
pObj->freq_update_req = 0;
LFO_freq_update(pObj);
}
}
}
if (pObj->param[LFO_PARAM2_WAVEFORM] == LFO_WAVEFORM_ONE_MINUS_SAW)
{
// Create phase
for (i=i0; i< len; i++)
{
in = (1-pObj->x) + pObj->offset;
pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in;
out = pObj->out;
if (pObj->smooth_is_negative)
out = 2*in - pObj->out;
*(pOut++) = out*pObj->attack_y;
pObj->attack_y += pObj->attack_a*(1-pObj->attack_y);
pObj->x += pObj->dx;
if (pObj->x >= 1.f)
{
pObj->x -= 1.f;
}
if (pObj->freq_update_req)
{
pObj->freq_update_req = 0;
LFO_freq_update(pObj);
}
}
}
if (pObj->param[LFO_PARAM2_WAVEFORM] == LFO_WAVEFORM_SH_UNI)
{
// Create phase for S/H
for (i=i0; i< len; i++)
{
if (pObj->x >= 1.f)
{
pObj->x -= 1.f;
pObj->sh_sample = Noise_Uniform(&pObj->noise, 1, 0.5);
}
in = pObj->sh_sample + pObj->offset;
pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in;
out = pObj->out;
if (pObj->smooth_is_negative)
out = 2*in - pObj->out;
*(pOut++) = out*pObj->attack_y;
pObj->attack_y += pObj->attack_a*(1-pObj->attack_y);
pObj->x += pObj->dx;
if (pObj->freq_update_req)
{
pObj->freq_update_req = 0;
LFO_freq_update(pObj);
}
}
}
if (pObj->param[LFO_PARAM2_WAVEFORM] == LFO_WAVEFORM_SH_GAUSS)
{
// Create phase for S/H
for (i=i0; i< len; i++)
{
if (pObj->x >= 1.f)
{
pObj->x -= 1.f;
do
{
pObj->sh_sample = Noise_Gaussian(&pObj->noise, sqrt(1.f/36), 0.5);
} while ((pObj->sh_sample < 0) || (pObj->sh_sample > 1.f));
}
in = pObj->sh_sample + pObj->offset;
pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in;
out = pObj->out;
if (pObj->smooth_is_negative)
out = 2*in - pObj->out;
*(pOut++) = out*pObj->attack_y;
pObj->attack_y += pObj->attack_a*(1-pObj->attack_y);
pObj->x += pObj->dx;
if (pObj->freq_update_req)
{
pObj->freq_update_req = 0;
LFO_freq_update(pObj);
}
}
}
// Create output
if (pObj->param[LFO_PARAM2_WAVEFORM] == LFO_WAVEFORM_SINE)
{
for (i=i0; i< len; i++)
{
in = pObj->y[1]+pObj->a + pObj->offset;
pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in;
out = pObj->out;
if (pObj->smooth_is_negative)
out = 2*in - pObj->out;
*(pOut++) = out*pObj->attack_y;
pObj->attack_y += pObj->attack_a*(1-pObj->attack_y);
pObj->y[0] = pObj->y[0] - pObj->b*pObj->y[1];
pObj->y[1] = pObj->y[1] + pObj->b*pObj->y[0];
if (pObj->freq_update_req)
{
pObj->freq_update_req = 0;
LFO_freq_update(pObj);
}
}
}
if (pObj->param[LFO_PARAM2_WAVEFORM] == LFO_WAVEFORM_ONE_MINUS_SINE)
{
for (i=i0; i< len; i++)
{
in = (1-(pObj->y[1]+pObj->a)) + pObj->offset;
pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in;
out = pObj->out;
if (pObj->smooth_is_negative)
out = 2*in - pObj->out;
*(pOut++) = out*pObj->attack_y;
pObj->attack_y += pObj->attack_a*(1-pObj->attack_y);
pObj->y[0] = pObj->y[0] - pObj->b*pObj->y[1];
pObj->y[1] = pObj->y[1] + pObj->b*pObj->y[0];
if (pObj->freq_update_req)
{
pObj->freq_update_req = 0;
LFO_freq_update(pObj);
}
}
}
if (pObj->param[LFO_PARAM2_WAVEFORM] == LFO_WAVEFORM_COSINE)
{
for (i=i0; i< len; i++)
{
in = pObj->y[0]+pObj->a + pObj->offset;
pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in;
out = pObj->out;
if (pObj->smooth_is_negative)
out = 2*in - pObj->out;
*(pOut++) = out*pObj->attack_y;
pObj->attack_y += pObj->attack_a*(1-pObj->attack_y);
pObj->y[0] = pObj->y[0] - pObj->b*pObj->y[1];
pObj->y[1] = pObj->y[1] + pObj->b*pObj->y[0];
if (pObj->freq_update_req)
{
pObj->freq_update_req = 0;
LFO_freq_update(pObj);
}
}
}
if (pObj->param[LFO_PARAM2_WAVEFORM] == LFO_WAVEFORM_ONE_MINUS_COSINE)
{
for (i=i0; i< len; i++)
{
in = (1-(pObj->y[0]+pObj->a)) + pObj->offset;
pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in;
out = pObj->out;
if (pObj->smooth_is_negative)
out = 2*in - pObj->out;
*(pOut++) = out*pObj->attack_y;
pObj->attack_y += pObj->attack_a*(1-pObj->attack_y);
pObj->y[0] = pObj->y[0] - pObj->b*pObj->y[1];
pObj->y[1] = pObj->y[1] + pObj->b*pObj->y[0];
if (pObj->freq_update_req)
{
pObj->freq_update_req = 0;
LFO_freq_update(pObj);
}
}
}
if (pObj->param[LFO_PARAM2_WAVEFORM] == LFO_WAVEFORM_SQUARE)
{
// Create phase
for (i=i0; i< len; i++)
{
in = (synth_float_t)pObj->sqr + pObj->offset;
pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in;
out = pObj->out;
if (pObj->smooth_is_negative)
out = 2*in - pObj->out;
*(pOut++) = out*pObj->attack_y;
pObj->attack_y += pObj->attack_a*(1-pObj->attack_y);
pObj->x += 2*pObj->dx;
if (pObj->x >= 1.f)
{
pObj->x -= 1.f;
pObj->sqr = !pObj->sqr;
}
if (pObj->freq_update_req)
{
pObj->freq_update_req = 0;
LFO_freq_update(pObj);
}
}
}
if (pObj->param[LFO_PARAM2_WAVEFORM] == LFO_WAVEFORM_ONE_MINUS_SQUARE)
{
// Create phase
for (i=i0; i< len; i++)
{
in = (1-((synth_float_t)pObj->sqr)) + pObj->offset;
pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in;
out = pObj->out;
if (pObj->smooth_is_negative)
out = 2*in - pObj->out;
*(pOut++) = out*pObj->attack_y;
pObj->attack_y += pObj->attack_a*(1-pObj->attack_y);
pObj->x += 2*pObj->dx;
if (pObj->x >= 1.f)
{
pObj->x -= 1.f;
pObj->sqr = !pObj->sqr;
}
if (pObj->freq_update_req)
{
pObj->freq_update_req = 0;
LFO_freq_update(pObj);
}
}
}
if (pObj->param[LFO_PARAM2_WAVEFORM] == LFO_WAVEFORM_TRIANGLE)
{
// Create phase
for (i=i0; i< len; i++)
{
in = (synth_float_t)pObj->tri + pObj->offset;
pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in;
out = pObj->out;
if (pObj->smooth_is_negative)
out = 2*in - pObj->out;
*(pOut++) = out*pObj->attack_y;
pObj->attack_y += pObj->attack_a*(1-pObj->attack_y);
if (pObj->x < 0.5)
pObj->tri = 2*pObj->x;
else
pObj->tri = 2*(1-pObj->x);
pObj->x += pObj->dx;
if (pObj->x >= 1.f)
{
pObj->x -= 1.f;
}
if (pObj->freq_update_req)
{
pObj->freq_update_req = 0;
LFO_freq_update(pObj);
}
}
}
if (pObj->param[LFO_PARAM2_WAVEFORM] == LFO_WAVEFORM_ONE_MINUS_TRIANGLE)
{
// Create phase
for (i=i0; i< len; i++)
{
in = (1-((synth_float_t)pObj->tri)) + pObj->offset;
pObj->out = pObj->smooth_a*pObj->out + pObj->smooth_b*in;
out = pObj->out;
if (pObj->smooth_is_negative)
out = 2*in - pObj->out;
*(pOut++) = out*pObj->attack_y;
pObj->attack_y += pObj->attack_a*(1-pObj->attack_y);
if (pObj->x < 0.5)
pObj->tri = 2*pObj->x;
else
pObj->tri = 2*(1-pObj->x);
pObj->x += pObj->dx;
if (pObj->x >= 1.f)
{
pObj->x -= 1.f;
}
if (pObj->freq_update_req)
{
pObj->freq_update_req = 0;
LFO_freq_update(pObj);
}
}
}
return pObj->pOut;
}
+81
View File
@@ -0,0 +1,81 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#ifndef _LFO_H_
#define _LFO_H_
#include "synth_defs.h"
#include "noise.h"
#define LFO_SH_ALPHA 0.002 // S&H smoothing
#define LFO_KE ((synth_float_t)(1-exp(-1)))
// --------------------------------------------------------------
// Types
// --------------------------------------------------------------
enum
{
LFO_WAVEFORM_SINE,
LFO_WAVEFORM_COSINE,
LFO_WAVEFORM_SAW,
LFO_WAVEFORM_SQUARE,
LFO_WAVEFORM_TRIANGLE,
LFO_WAVEFORM_SH_UNI,
LFO_WAVEFORM_SH_GAUSS,
LFO_WAVEFORM_ONE_MINUS_SINE,
LFO_WAVEFORM_ONE_MINUS_COSINE,
LFO_WAVEFORM_ONE_MINUS_SAW,
LFO_WAVEFORM_ONE_MINUS_SQUARE,
LFO_WAVEFORM_ONE_MINUS_TRIANGLE,
LFO_NUM_WAVEFORMS
};
enum
{
LFO_PARAM2_WAVEFORM,
LFO_PARAM2_FREQ,
LFO_PARAM2_SMOOTH,
LFO_PARAM2_DELAY,
LFO_PARAM2_ATTACK,
LFO_PARAM2_SYMMETRY,
LFO_NUM_PARAMS
};
typedef struct _slfo_t
{
synth_float_t param[LFO_NUM_PARAMS];
synth_float_t fs;
synth_float_t a, b, y[2], x, dx, out, sh_sample, tri;
int freq_update_req, sqr;
synth_float_t *pOut;
UINT32 bufsize;
noise_gen_t noise;
synth_float_t smooth_a, smooth_b;
UINT32 smooth_is_negative;
synth_float_t delay_x, delay_dx, attack_y, attack_a;
synth_float_t gain, offset;
} lfo_t;
// --------------------------------------------------------------
#if defined(__cplusplus)
extern "C" {
#endif
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void LFO_Init(lfo_t *pObj, synth_float_t fs);
void LFO_Free(lfo_t *pObj);
void LFO_SetFS(lfo_t *pObj, synth_float_t fs);
void LFO_SetBufsize(lfo_t *pObj, UINT32 bufsize);
void LFO_Reset(lfo_t *pObj, synth_float_t initial_phase);
void LFO_Param2Set(lfo_t *pObj, UINT32 type, synth_float_t value);
synth_float_t* LFO_ProcessDataV(lfo_t *pObj, UINT32 len);
#if defined(__cplusplus)
}
#endif
// --------------------------------------------------------------
#endif // _LFO_H_
File diff suppressed because it is too large Load Diff
+94
View File
@@ -0,0 +1,94 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include "synth_defs.h"
#include "noise.h"
// --------------------------------------------------------------
// internal funcs
// --------------------------------------------------------------
#define PM_IA 16807
#define PM_IM 2147483647
#define PM_AM (1.0/PM_IM)
#define PM_IQ 127773
#define PM_IR 2836
#define PM_MASK 123459876
// 'Minimal' random number generator of Park and Miller. Returns a uniform random deviate
// between 0.0 and 1.0. Set or resetidumto any integer value (except the unlikely value MASK)
// to initialize the sequence; idummust not be altered between calls for successive deviates in
// a sequence.
double ran0(long *idum)
{
long k;
double ans;
*idum ^= PM_MASK; // XORing with MASKallows use of zero and other
k=(*idum)/PM_IQ; // simple bit patterns for idum.
*idum=PM_IA*(*idum-k*PM_IQ)-PM_IR *k; // Compute idum=(IA*idum) % IM without over-
// flows by Schrages method.
if (*idum < 0)
*idum += PM_IM;
ans=PM_AM*(*idum); // Convert idumto a floating result.
*idum ^= PM_MASK; // Unmask before return.
return ans;
}
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void Noise_Init(noise_gen_t *pObj, UINT32 seed)
{
pObj->state = (long)(seed & NOISE_LFSR_MAX);
}
void Noise_Free(noise_gen_t *pObj)
{
}
synth_float_t Noise_Uniform(noise_gen_t *pObj, synth_float_t var, synth_float_t mu)
{
/*
if (pObj->lfsr & 0x800000)
pObj->lfsr = ((pObj->lfsr << 1) | 1) ^ NOISE_LFSR_POLY;
else
pObj->lfsr = (pObj->lfsr << 1);
pObj->lfsr &= NOISE_LFSR_MAX;
*/
/* taps: 32 31 29 1; characteristic polynomial: x^32 + x^31 + x^29 + x + 1 */
// pObj->lfsr = (pObj->lfsr >> 1) ^ (-(pObj->lfsr & 1) & NOISE_LFSR_POLY);
// return var * ((synth_float_t)rand()/(RAND_MAX+1) + mu -0.5);
return var*(ran0(&pObj->state) + mu -0.5);
}
synth_float_t Noise_Gaussian(noise_gen_t *pObj, synth_float_t std, synth_float_t mu)
{
synth_float_t U1, U2, V1, V2, S, Y;
do
{
U1 = Noise_Uniform(pObj, 1, 0.5); // U1=[0,1]
U2 = Noise_Uniform(pObj, 1, 0.5); // U2=[0,1]
V1 = 2 * U1 - 1; // V1=[-1,1]
V2 = 2 * U2 - 1; // V2=[-1,1]
S = V1 * V1 + V2 * V2;
} while (S >= 1);
// X = sqrt(-2 * log(S) / S) * V1;
Y = sqrt(-2 * log(S) / S) * V2;
Y = mu + std*Y;
return Y;
}
+38
View File
@@ -0,0 +1,38 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#ifndef _NOISE_H_
#define _NOISE_H_
#include "synth_defs.h"
#define NOISE_LFSR_POLY 0xD0000001
#define NOISE_LFSR_MAX 0xFFFFFFFF
// --------------------------------------------------------------
// Types
// --------------------------------------------------------------
typedef struct _snoise_gen_t
{
long state;
} noise_gen_t;
// --------------------------------------------------------------
#if defined(__cplusplus)
extern "C" {
#endif
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void Noise_Init(noise_gen_t *pObj, UINT32 seed);
void Noise_Free(noise_gen_t *pObj);
synth_float_t Noise_Uniform(noise_gen_t *pObj, synth_float_t vmax, synth_float_t mu);
synth_float_t Noise_Gaussian(noise_gen_t *pObj, synth_float_t std, synth_float_t mu);
#if defined(__cplusplus)
}
#endif
// --------------------------------------------------------------
#endif // _NOISE_H_
+886
View File
@@ -0,0 +1,886 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#include <string.h>
#include <stdlib.h>
#include <float.h>
#include <math.h>
#include "synth_defs.h"
#include "vcf.h"
#include "voice.h"
#include "param_scale.h"
static const param_info_t param_info[] =
{
{
SYNTH_PARAM_VOLUME,
"Master Volume",
/*Base*/10.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_VOICE_PAN_SPREAD,
"Voice Pan Spread",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_TUNE,
"Master Tune",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/+100, /*interval*/0.1
},
{
SYNTH_PARAM_TOTAL_NUM_VOICES,
"Total num. Voices",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/1, /*pcenter*/-1, /*max*/MAX_POLYPHONY, /*interval*/1
},
{
SYNTH_PARAM_HUMANIZE_ENABLE,
"Humanize Enable",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/1.0, /*interval*/1
},
{
SYNTH_PARAM_HUMANIZE_VAR_VCO,
"Humanize Spread VCO",
/*Base*/10.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/10, /*interval*/0.01
},
{
SYNTH_PARAM_HUMANIZE_VAR_VCF,
"Humanize Spread VCF",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/200, /*interval*/0.1
},
{
SYNTH_PARAM_HUMANIZE_VAR_ENV,
"Humanize Spread ENV",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_MONOPHONIC_ENABLE,
"Monophonic Enable",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/1.0, /*interval*/1
},
{
SYNTH_PARAM_MONOPHONIC_RETRIGGER_ENABLE,
"Monophonic Retrigger Enable",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/1.0, /*interval*/1
},
{
SYNTH_PARAM_UNISONO_ENABLE,
"Unisono Enable",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/1.0, /*interval*/1
},
{
SYNTH_PARAM_UNISONO_NUM_VOICES,
"Unisono num. Voices",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/1, /*pcenter*/-1, /*max*/MAX_POLYPHONY, /*interval*/1
},
{
SYNTH_PARAM_PORTAMENTO_TIME,
"Portamento Time",
/*Base*/10.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0.001, /*pcenter*/-1, /*max*/0.5, /*interval*/0.001
},
{
SYNTH_PARAM_OSC_0_ENABLE,
"OSC1 enable",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/1.0, /*interval*/1
},
{
SYNTH_PARAM_OSC_1_ENABLE,
"OSC2 enable",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/1.0, /*interval*/1
},
{
SYNTH_PARAM_OSC_0_RESTART_ON_TRIGGER,
"OSC1 restart on trigger",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/1.0, /*interval*/1
},
{
SYNTH_PARAM_OSC_1_RESTART_ON_TRIGGER,
"OSC2 restart on trigger",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/1.0, /*interval*/1
},
{
SYNTH_PARAM_OSC_0_LEVEL,
"OSC1 level",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_OSC_1_LEVEL,
"OSC2 level",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_OSC_0_DUTYCYCLE,
"OSC1 pulse width",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_OSC_1_DUTYCYCLE,
"OSC2 pulse width",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_OSC_0_DETUNE,
"OSC1 detune",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-50, /*pcenter*/0, /*max*/+50, /*interval*/0.1
},
{
SYNTH_PARAM_OSC_1_DETUNE,
"OSC2 detune",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-50, /*pcenter*/0, /*max*/+50, /*interval*/0.1
},
{
SYNTH_PARAM_OSC_0_TRANSPOSE,
"OSC1 transpose",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-48.0, /*pcenter*/0, /*max*/+48.0, /*interval*/1
},
{
SYNTH_PARAM_OSC_1_TRANSPOSE,
"OSC2 transpose",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-48.0, /*pcenter*/0, /*max*/+48.0, /*interval*/1
},
{
SYNTH_PARAM_OSC_0_WAVEFORM,
"OSC1 shape",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/OSC_NUM_WAVEFORMS-1, /*interval*/1
},
{
SYNTH_PARAM_OSC_1_WAVEFORM,
"OSC2 shape",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/OSC_NUM_WAVEFORMS-1, /*interval*/1
},
{
SYNTH_PARAM_OSC_0_PB_RANGE_MIN,
"OSC1 pitch bender minimum",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-48.0, /*pcenter*/0, /*max*/+48.0, /*interval*/1
},
{
SYNTH_PARAM_OSC_1_PB_RANGE_MIN,
"OSC2 pitch bender minimum",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-48.0, /*pcenter*/0, /*max*/+48.0, /*interval*/1
},
{
SYNTH_PARAM_OSC_0_PB_RANGE_MAX,
"OSC1 pitch bender maximum",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-48.0, /*pcenter*/0, /*max*/+48.0, /*interval*/1
},
{
SYNTH_PARAM_OSC_1_PB_RANGE_MAX,
"OSC2 pitch bender maximum",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-48.0, /*pcenter*/0, /*max*/+48.0, /*interval*/1
},
{
SYNTH_PARAM_OSC_0_FM_AMT_0,
"OSC1 FM amt 1",
/*Base*/10, /*kexp*/2.5, /*scenter*/0.5, /*min*/-48, /*pcenter*/0, /*max*/+48, /*interval*/0.01
},
{
SYNTH_PARAM_OSC_1_FM_AMT_0,
"OSC2 FM amt 1",
/*Base*/10, /*kexp*/2.5, /*scenter*/0.5, /*min*/-48, /*pcenter*/0, /*max*/+48, /*interval*/0.01
},
{
SYNTH_PARAM_OSC_0_FM_AMT_1,
"OSC1 FM amt 2",
/*Base*/1, /*kexp*/1, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/+100, /*interval*/0.01
},
{
SYNTH_PARAM_OSC_1_FM_AMT_1,
"OSC2 FM amt 2",
/*Base*/1, /*kexp*/1, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/+100, /*interval*/0.01
},
{
SYNTH_PARAM_OSC_0_FM_SRC_0,
"OSC1 FM src 1",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_SOURCES_0-1, /*interval*/1
},
{
SYNTH_PARAM_OSC_1_FM_SRC_0,
"OSC2 FM src 1",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_SOURCES_0-1, /*interval*/1
},
{
SYNTH_PARAM_OSC_0_FM_SRC_1,
"OSC1 FM src 2",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/(VOICE_NUM_MOD_SOURCES_1-1)*VOICE_NUM_MOD_OPS + 1-1, /*interval*/1
},
{
SYNTH_PARAM_OSC_1_FM_SRC_1,
"OSC2 FM src 2",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/(VOICE_NUM_MOD_SOURCES_1-1)*VOICE_NUM_MOD_OPS + 1-1, /*interval*/1
},
{
SYNTH_PARAM_OSC_0_FM_SRC_OP,
"OSC1 FM src OP",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_OPS-1, /*interval*/1
},
{
SYNTH_PARAM_OSC_1_FM_SRC_OP,
"OSC2 FM src OP",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_OPS-1, /*interval*/1
},
{
SYNTH_PARAM_OSC_0_AM_AMT_0,
"OSC1 AM amt 1",
/*Base*/1, /*kexp*/1, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/+100, /*interval*/0.01
},
{
SYNTH_PARAM_OSC_1_AM_AMT_0,
"OSC2 AM amt 1",
/*Base*/1, /*kexp*/1, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/+100, /*interval*/0.01
},
{
SYNTH_PARAM_OSC_0_AM_AMT_1,
"OSC1 AM amt 2",
/*Base*/1, /*kexp*/1, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/+100, /*interval*/0.01
},
{
SYNTH_PARAM_OSC_1_AM_AMT_1,
"OSC2 AM amt 2",
/*Base*/1, /*kexp*/1, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/+100, /*interval*/0.01
},
{
SYNTH_PARAM_OSC_0_AM_SRC_0,
"OSC1 AM src 1",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_SOURCES_0-1, /*interval*/1
},
{
SYNTH_PARAM_OSC_1_AM_SRC_0,
"OSC2 AM src 1",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_SOURCES_0-1, /*interval*/1
},
{
SYNTH_PARAM_OSC_0_AM_SRC_1,
"OSC1 AM src 2",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/(VOICE_NUM_MOD_SOURCES_1-1)*VOICE_NUM_MOD_OPS + 1-1, /*interval*/1
},
{
SYNTH_PARAM_OSC_1_AM_SRC_1,
"OSC2 AM src 2",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/(VOICE_NUM_MOD_SOURCES_1-1)*VOICE_NUM_MOD_OPS + 1-1, /*interval*/1
},
{
SYNTH_PARAM_OSC_0_AM_SRC_OP,
"OSC1 AM src OP",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_OPS-1, /*interval*/1
},
{
SYNTH_PARAM_OSC_1_AM_SRC_OP,
"OSC2 AM src OP",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_OPS-1, /*interval*/1
},
{
SYNTH_PARAM_OSC_0_PWM_AMT_0,
"OSC1 PWM amt 1",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/+100, /*interval*/0.1
},
{
SYNTH_PARAM_OSC_1_PWM_AMT_0,
"OSC2 PWM amt 1",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/+100, /*interval*/0.1
},
{
SYNTH_PARAM_OSC_0_PWM_AMT_1,
"OSC1 PWM amt 2",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/+100, /*interval*/0.1
},
{
SYNTH_PARAM_OSC_1_PWM_AMT_1,
"OSC2 PWM amt 2",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/+100, /*interval*/0.1
},
{
SYNTH_PARAM_OSC_0_PWM_SRC_0,
"OSC1 PWM src 1",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_SOURCES_0-1, /*interval*/1
},
{
SYNTH_PARAM_OSC_1_PWM_SRC_0,
"OSC2 PWM src 1",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_SOURCES_0-1, /*interval*/1
},
{
SYNTH_PARAM_OSC_0_PWM_SRC_1,
"OSC1 PWM src 2",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/(VOICE_NUM_MOD_SOURCES_1-1)*VOICE_NUM_MOD_OPS + 1-1, /*interval*/1
},
{
SYNTH_PARAM_OSC_1_PWM_SRC_1,
"OSC2 PWM src 2",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/(VOICE_NUM_MOD_SOURCES_1-1)*VOICE_NUM_MOD_OPS + 1-1, /*interval*/1
},
{
SYNTH_PARAM_OSC_0_PWM_SRC_OP,
"OSC1 PWM src OP",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_OPS-1, /*interval*/1
},
{
SYNTH_PARAM_OSC_1_PWM_SRC_OP,
"OSC2 PWM src OP",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_OPS-1, /*interval*/1
},
{
SYNTH_PARAM_NOISE_ENABLE,
"Noise enable",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/1, /*interval*/1
},
{
SYNTH_PARAM_NOISE_LEVEL,
"Noise level",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_NOISE_SHAPE,
"Noise shape",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NOISE_NUM_SHAPES-1, /*interval*/1
},
{
SYNTH_PARAM_VCA_ENV_AMT,
"VCA Env amt",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_VCA_AM_AMT_0,
"VCA AM amt 1",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_VCA_AM_SRC_0,
"VCA AM src 1",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_SOURCES_0-1, /*interval*/1
},
{
SYNTH_PARAM_VCA_PAN_AMT_0,
"VCA PAN amt 1",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_VCA_PAN_SRC_0,
"VCA PAN src 1",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_SOURCES_0-1, /*interval*/1
},
{
SYNTH_PARAM_VCA_ENV_A,
"VCA Attack",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/1, /*pcenter*/-1, /*max*/10000, /*interval*/1
},
{
SYNTH_PARAM_VCA_ENV_D,
"VCA Decay",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/5, /*pcenter*/-1, /*max*/30000, /*interval*/1
},
{
SYNTH_PARAM_VCA_ENV_S,
"VCA Sustain",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_VCF_ENV_A,
"VCF Attack",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/1, /*pcenter*/-1, /*max*/10000, /*interval*/1
},
{
SYNTH_PARAM_VCF_ENV_D,
"VCF Decay",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/5, /*pcenter*/-1, /*max*/30000, /*interval*/1
},
{
SYNTH_PARAM_VCF_ENV_S,
"VCF Sustain",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_VCF_ENV_R,
"VCF Release",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/5, /*pcenter*/-1, /*max*/30000, /*interval*/1
},
{
SYNTH_PARAM_ENV_2_A,
"ENV 2 Attack",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/1, /*pcenter*/-1, /*max*/10000, /*interval*/1
},
{
SYNTH_PARAM_ENV_2_D,
"ENV 2 Decay",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/5, /*pcenter*/-1, /*max*/30000, /*interval*/1
},
{
SYNTH_PARAM_ENV_2_S,
"ENV 2 Sustain",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_ENV_2_R,
"ENV 2 Release",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/5, /*pcenter*/-1, /*max*/30000, /*interval*/1
},
{
SYNTH_PARAM_ENV_3_A,
"ENV 3 Attack",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/1, /*pcenter*/-1, /*max*/10000, /*interval*/1
},
{
SYNTH_PARAM_ENV_3_D,
"ENV 3 Decay",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/5, /*pcenter*/-1, /*max*/30000, /*interval*/1
},
{
SYNTH_PARAM_ENV_3_S,
"ENV 3 Sustain",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_ENV_3_R,
"ENV 3 Release",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/5, /*pcenter*/-1, /*max*/30000, /*interval*/1
},
{
SYNTH_PARAM_VCA_ENV_R,
"VCA Release",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/5, /*pcenter*/-1, /*max*/30000, /*interval*/1
},
{
SYNTH_PARAM_VCF_TYPE,
"VCF type",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VCF_NUM_FILTERTYPES-1, /*interval*/1
},
{
SYNTH_PARAM_VCF_ORDER,
"VCF order",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VCF_NUM_FILTERORDER-1, /*interval*/1
},
{
SYNTH_PARAM_VCF_F,
"VCF Cutoff",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/FILTER_F_MIN, /*pcenter*/-1, /*max*/FILTER_F_MAX, /*interval*/0.1
},
{
SYNTH_PARAM_VCF_Q,
"VCF Res",
/*Base*/10, /*kexp*/2.0, /*scenter*/0.0, /*min*/FILTER_Q_MIN, /*pcenter*/-1, /*max*/FILTER_Q_MAX, /*interval*/0.1
},
{
SYNTH_PARAM_VCF_ENV_AMT,
"VCF Env amt",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_VCF_F_AMT_0,
"VCF Cutoff amt 1",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_VCF_F_AMT_1,
"VCF Cutoff amt 2",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_VCF_F_SRC_0,
"VCF Cutoff src 1",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_SOURCES_0-1, /*interval*/1
},
{
SYNTH_PARAM_VCF_F_SRC_1,
"VCF Cutoff src 2",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/(VOICE_NUM_MOD_SOURCES_1-1)*VOICE_NUM_MOD_OPS + 1-1, /*interval*/1
},
{
SYNTH_PARAM_VCF_F_SRC_OP,
"VCF Cutoff src OP",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_OPS-1, /*interval*/1
},
{
SYNTH_PARAM_VCF_Q_AMT_0,
"VCF Resonance amt 1",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_VCF_Q_AMT_1,
"VCF Resonance amt 2",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_VCF_Q_SRC_0,
"VCF Resonance src 1",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_SOURCES_0-1, /*interval*/1
},
{
SYNTH_PARAM_VCF_Q_SRC_1,
"VCF Resonance src 2",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/(VOICE_NUM_MOD_SOURCES_1-1)*VOICE_NUM_MOD_OPS + 1-1, /*interval*/1
},
{
SYNTH_PARAM_VCF_Q_SRC_OP,
"VCF Resonance src OP",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_NUM_MOD_OPS-1, /*interval*/1
},
{
SYNTH_PARAM_LFO_0_SPEED,
"LFO 1 speed",
/*Base*/20, /*kexp*/1.0, /*scenter*/0.0, /*min*/0.01, /*pcenter*/-1, /*max*/20.0, /*interval*/0.01
},
{
SYNTH_PARAM_LFO_1_SPEED,
"LFO 2 speed",
/*Base*/20, /*kexp*/1.0, /*scenter*/0.0, /*min*/0.01, /*pcenter*/-1, /*max*/20.0, /*interval*/0.01
},
{
SYNTH_PARAM_LFO_2_SPEED,
"LFO 3 speed",
/*Base*/20, /*kexp*/1.0, /*scenter*/0.0, /*min*/0.01, /*pcenter*/-1, /*max*/20.0, /*interval*/0.01
},
{
SYNTH_PARAM_LFO_3_SPEED,
"LFO 4 speed",
/*Base*/20, /*kexp*/1.0, /*scenter*/0.0, /*min*/0.01, /*pcenter*/-1, /*max*/20.0, /*interval*/0.01
},
{
SYNTH_PARAM_LFO_0_SMOOTH,
"LFO 1 smooth",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_LFO_1_SMOOTH,
"LFO 2 smooth",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_LFO_2_SMOOTH,
"LFO 3 smooth",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_LFO_3_SMOOTH,
"LFO 4 smooth",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_LFO_0_DELAY,
"LFO 1 Delay",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/30000, /*interval*/1
},
{
SYNTH_PARAM_LFO_1_DELAY,
"LFO 2 Delay",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/30000, /*interval*/1
},
{
SYNTH_PARAM_LFO_2_DELAY,
"LFO 3 Delay",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/30000, /*interval*/1
},
{
SYNTH_PARAM_LFO_3_DELAY,
"LFO 4 Delay",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/30000, /*interval*/1
},
{
SYNTH_PARAM_LFO_0_ATTACK,
"LFO 1 Attack",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/1, /*pcenter*/-1, /*max*/10000, /*interval*/1
},
{
SYNTH_PARAM_LFO_1_ATTACK,
"LFO 2 Attack",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/1, /*pcenter*/-1, /*max*/10000, /*interval*/1
},
{
SYNTH_PARAM_LFO_2_ATTACK,
"LFO 3 Attack",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/1, /*pcenter*/-1, /*max*/10000, /*interval*/1
},
{
SYNTH_PARAM_LFO_3_ATTACK,
"LFO 4 Attack",
/*Base*/150, /*kexp*/1.0, /*scenter*/0.0, /*min*/1, /*pcenter*/-1, /*max*/10000, /*interval*/1
},
{
SYNTH_PARAM_LFO_0_SHAPE,
"LFO 1 shape",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/LFO_NUM_WAVEFORMS-1, /*interval*/1
},
{
SYNTH_PARAM_LFO_1_SHAPE,
"LFO 2 shape",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/LFO_NUM_WAVEFORMS-1, /*interval*/1
},
{
SYNTH_PARAM_LFO_2_SHAPE,
"LFO 3 shape",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/LFO_NUM_WAVEFORMS-1, /*interval*/1
},
{
SYNTH_PARAM_LFO_3_SHAPE,
"LFO 4 shape",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/LFO_NUM_WAVEFORMS-1, /*interval*/1
},
{
SYNTH_PARAM_LFO_0_MODE,
"LFO 1 mode",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_LFO_NUM_MODES-1, /*interval*/1
},
{
SYNTH_PARAM_LFO_1_MODE,
"LFO 2 mode",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_LFO_NUM_MODES-1, /*interval*/1
},
{
SYNTH_PARAM_LFO_2_MODE,
"LFO 3 mode",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_LFO_NUM_MODES-1, /*interval*/1
},
{
SYNTH_PARAM_LFO_3_MODE,
"LFO 4 mode",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_LFO_NUM_MODES-1, /*interval*/1
},
{
SYNTH_PARAM_LFO_0_SYNC,
"LFO 1 sync",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_LFO_NUM_SYNCS-1, /*interval*/1
},
{
SYNTH_PARAM_LFO_1_SYNC,
"LFO 2 sync",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_LFO_NUM_SYNCS-1, /*interval*/1
},
{
SYNTH_PARAM_LFO_2_SYNC,
"LFO 3 sync",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_LFO_NUM_SYNCS-1, /*interval*/1
},
{
SYNTH_PARAM_LFO_3_SYNC,
"LFO 4 sync",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.0, /*min*/0, /*pcenter*/-1, /*max*/VOICE_LFO_NUM_SYNCS-1, /*interval*/1
},
{
SYNTH_PARAM_LFO_0_SYMMETRY,
"LFO 1 symmetry",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_LFO_1_SYMMETRY,
"LFO 2 symmetry",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_LFO_2_SYMMETRY,
"LFO 3 symmetry",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1
},
{
SYNTH_PARAM_LFO_3_SYMMETRY,
"LFO 4 symmetry",
/*Base*/1.0, /*kexp*/1.0, /*scenter*/0.5, /*min*/-100, /*pcenter*/0, /*max*/100, /*interval*/0.1
}
};
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
synth_float_t quantizeParam(param_info_t *pObj, synth_float_t p)
{
synth_float_t k, pq;
if (pObj->pinterval == 0)
return p;
k = (synth_float_t)1/(pObj->pinterval - 0);
if (p < 0)
pq = ((int)(p*k - 0.5))*pObj->pinterval;
else
pq = ((int)(p*k + 0.5))*pObj->pinterval;
return pq;
}
synth_float_t clampParam(param_info_t *pObj, synth_float_t p)
{
return (synth_float_t)min(pObj->pmax, max(pObj->pmin, quantizeParam(pObj, p)));
}
synth_float_t toParam(param_info_t *pObj, synth_float_t s)
{
synth_float_t p, pcenter;
synth_float_t pmax, pmin, base, kexp, scenter;
pmax = pObj->pmax;
pmin = pObj->pmin;
if (pmin == pmax)
pmax += 1E-9;
base = pObj->base;
kexp = pObj->kexp;
if (kexp == 0)
kexp = 1E-9;
scenter = pObj->scenter;
pcenter = pObj->pcenter;
if ((pcenter < pmin) || (pcenter > pmax))
pcenter = pmax*scenter + pmin*(1-scenter);
s = (synth_float_t)min(1, max(0, s));
if (s < scenter)
{
if (base == 1)
{
// pcenter-(pcenter-pmin)*(scenter-s)/scenter;
p = pcenter-(pcenter-pmin)*(scenter-s)/scenter;
}
else
{
// pcenter-(pcenter-pmin)*(B^(k*(scenter-s)/scenter)-1)/(B^k-1);
p = pcenter-(pcenter-pmin)*(pow(base,kexp*(scenter-s)/scenter)-1)/(pow(base,kexp)-1);
}
}
else
{
if (base == 1)
{
// pcenter+(pmax-pcenter)*(-scenter+s)/(1-scenter);
p = pcenter+(pmax-pcenter)*(-scenter+s)/(1-scenter);
}
else
{
// pcenter+(pmax-pcenter)*(B^(k*(-scenter+s)/(1-scenter))-1)/(B^k-1);
p = pcenter+(pmax-pcenter)*(pow(base,kexp*(-scenter+s)/(1-scenter))-1)/(pow(base,kexp)-1);
}
}
return quantizeParam(pObj, p);
}
synth_float_t toSlider(param_info_t *pObj, synth_float_t p)
{
synth_float_t s, pcenter;
synth_float_t pmax, pmin, base, kexp, scenter;
pmax = pObj->pmax;
pmin = pObj->pmin;
if (pmin == pmax)
pmax += 1E-9;
base = pObj->base;
kexp = pObj->kexp;
if (kexp == 0)
kexp = 1E-9;
scenter = pObj->scenter;
pcenter = pObj->pcenter;
if ((pcenter < pmin) || (pcenter > pmax))
pcenter = pmax*scenter + pmin*(1-scenter);
p = clampParam(pObj, p);
if (p < pcenter)
{
if (base == 1)
{
// (-pmin+p)*scenter/(pcenter-pmin);
s = (-pmin+p)*scenter/(pcenter-pmin);
}
else
{
// scenter*(log(B)*k-log(-(-pcenter*B^k+pmin+p*B^k-p)/(pcenter-pmin)))/log(B)/k;
s = scenter*(log(base)*kexp-log(-(-pcenter*pow(base,kexp)+pmin+p*pow(base,kexp)-p)/(pcenter-pmin)))/log(base)/kexp;
}
}
else
{
if (base == 1)
{
// (pcenter-scenter*pmax-p+scenter*p)/(-pmax+pcenter);
s = (pcenter-scenter*pmax-p+scenter*p)/(-pmax+pcenter);
}
else
{
// (k*log(B)*scenter+log(-(-pcenter*B^k+pmax+p*B^k-p)/(-pmax+pcenter))-log(-(-pcenter*B^k+pmax+p*B^k-p)/(-pmax+pcenter))*scenter)/log(B)/k;
s = (kexp*log(base)*scenter+log(-(-pcenter*pow(base,kexp)+pmax+p*pow(base,kexp)-p)/(-pmax+pcenter))-log(-(-pcenter*pow(base,kexp)+pmax+p*pow(base,kexp)-p)/(-pmax+pcenter))*scenter)/log(base)/kexp;
}
}
return s;
}
void paramInfoInit(param_info_t *pObj, UINT32 id, char *pName)
{
pObj->id = id;
pObj->pName = NULL;
if (pName)
{
pObj->pName = (char*)malloc(strlen(pName)+1);
memcpy(pObj->pName, pName, strlen(pName)+1);
}
pObj->base = 1;
pObj->kexp = 1;
pObj->scenter = 0;
pObj->pmin = 0;
pObj->pcenter = 0;
pObj->pmax = 1;
pObj->pinterval = 0;
}
void paramInfoFree(param_info_t *pObj)
{
if (pObj->pName)
free(pObj->pName);
}
void paramInfoSetPMIN(param_info_t *pObj, synth_float_t value)
{
pObj->pmin = value;
}
void paramInfoSetPMAX(param_info_t *pObj, synth_float_t value)
{
pObj->pmax = value;
}
void paramInfoSet(param_info_t *pObj,
synth_float_t base,
synth_float_t kexp,
synth_float_t scenter,
synth_float_t pmin,
synth_float_t pcenter,
synth_float_t pmax,
synth_float_t pinterval)
{
pObj->base = base;
pObj->kexp = kexp;
pObj->scenter = scenter;
pObj->pmin = pmin;
pObj->pcenter = pcenter;
pObj->pmax = pmax;
pObj->pinterval = pinterval;
}
void paramInfoCopy(param_info_t *pDst, param_info_t *pSrc)
{
pDst->base = pSrc->base;
pDst->kexp = pSrc->kexp;
pDst->scenter = pSrc->scenter;
pDst->pmin = pSrc->pmin;
pDst->pcenter = pSrc->pcenter;
pDst->pmax = pSrc->pmax;
pDst->pinterval = pSrc->pinterval;
}
param_info_t* getParamInfo(UINT32 type)
{
UINT32 i;
if (type >= SYNTH_NUM_PARAMS)
return NULL;
for (i=0; i < SYNTH_NUM_PARAMS; i++)
{
if (param_info[i].id == type)
break;
}
if (i == SYNTH_NUM_PARAMS)
return NULL;
return (param_info_t*)&param_info[i];
}
+188
View File
@@ -0,0 +1,188 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#ifndef _PARAM_SCALE_H_
#define _PARAM_SCALE_H_
#include "synth_types.h"
enum
{
SYNTH_PARAM_VOLUME = 0,
SYNTH_PARAM_TUNE,
SYNTH_PARAM_TOTAL_NUM_VOICES,
SYNTH_PARAM_VOICE_PAN_SPREAD,
SYNTH_PARAM_HUMANIZE_ENABLE,
SYNTH_PARAM_MONOPHONIC_ENABLE,
SYNTH_PARAM_MONOPHONIC_RETRIGGER_ENABLE,
SYNTH_PARAM_UNISONO_ENABLE,
SYNTH_PARAM_UNISONO_NUM_VOICES,
SYNTH_PARAM_HUMANIZE_VAR_VCO,
SYNTH_PARAM_HUMANIZE_VAR_VCF,
SYNTH_PARAM_HUMANIZE_VAR_ENV,
SYNTH_PARAM_PORTAMENTO_TIME,
SYNTH_PARAM_OSC_0_RESTART_ON_TRIGGER,
SYNTH_PARAM_OSC_1_RESTART_ON_TRIGGER,
SYNTH_PARAM_OSC_0_ENABLE,
SYNTH_PARAM_OSC_1_ENABLE,
SYNTH_PARAM_OSC_0_LEVEL,
SYNTH_PARAM_OSC_1_LEVEL,
SYNTH_PARAM_OSC_0_DUTYCYCLE,
SYNTH_PARAM_OSC_1_DUTYCYCLE,
SYNTH_PARAM_OSC_0_DETUNE,
SYNTH_PARAM_OSC_1_DETUNE,
SYNTH_PARAM_OSC_0_TRANSPOSE,
SYNTH_PARAM_OSC_1_TRANSPOSE,
SYNTH_PARAM_OSC_0_PB_RANGE_MIN,
SYNTH_PARAM_OSC_1_PB_RANGE_MIN,
SYNTH_PARAM_OSC_0_PB_RANGE_MAX,
SYNTH_PARAM_OSC_1_PB_RANGE_MAX,
SYNTH_PARAM_OSC_0_WAVEFORM,
SYNTH_PARAM_OSC_1_WAVEFORM,
SYNTH_PARAM_OSC_0_FM_AMT_0,
SYNTH_PARAM_OSC_1_FM_AMT_0,
SYNTH_PARAM_OSC_0_FM_AMT_1,
SYNTH_PARAM_OSC_1_FM_AMT_1,
SYNTH_PARAM_OSC_0_FM_SRC_0,
SYNTH_PARAM_OSC_1_FM_SRC_0,
SYNTH_PARAM_OSC_0_FM_SRC_1,
SYNTH_PARAM_OSC_1_FM_SRC_1,
SYNTH_PARAM_OSC_0_FM_SRC_OP,
SYNTH_PARAM_OSC_1_FM_SRC_OP,
SYNTH_PARAM_OSC_0_AM_AMT_0,
SYNTH_PARAM_OSC_1_AM_AMT_0,
SYNTH_PARAM_OSC_0_AM_AMT_1,
SYNTH_PARAM_OSC_1_AM_AMT_1,
SYNTH_PARAM_OSC_0_AM_SRC_0,
SYNTH_PARAM_OSC_1_AM_SRC_0,
SYNTH_PARAM_OSC_0_AM_SRC_1,
SYNTH_PARAM_OSC_1_AM_SRC_1,
SYNTH_PARAM_OSC_0_AM_SRC_OP,
SYNTH_PARAM_OSC_1_AM_SRC_OP,
SYNTH_PARAM_OSC_0_PWM_AMT_0,
SYNTH_PARAM_OSC_1_PWM_AMT_0,
SYNTH_PARAM_OSC_0_PWM_AMT_1,
SYNTH_PARAM_OSC_1_PWM_AMT_1,
SYNTH_PARAM_OSC_0_PWM_SRC_0,
SYNTH_PARAM_OSC_1_PWM_SRC_0,
SYNTH_PARAM_OSC_0_PWM_SRC_1,
SYNTH_PARAM_OSC_1_PWM_SRC_1,
SYNTH_PARAM_OSC_0_PWM_SRC_OP,
SYNTH_PARAM_OSC_1_PWM_SRC_OP,
SYNTH_PARAM_NOISE_ENABLE,
SYNTH_PARAM_NOISE_LEVEL,
SYNTH_PARAM_NOISE_SHAPE,
SYNTH_PARAM_VCA_ENV_AMT,
SYNTH_PARAM_VCA_AM_AMT_0,
SYNTH_PARAM_VCA_AM_SRC_0,
SYNTH_PARAM_VCA_PAN_AMT_0,
SYNTH_PARAM_VCA_PAN_SRC_0,
SYNTH_PARAM_ENV_0_A, SYNTH_PARAM_VCF_ENV_A = SYNTH_PARAM_ENV_0_A,
SYNTH_PARAM_ENV_1_A, SYNTH_PARAM_VCA_ENV_A = SYNTH_PARAM_ENV_1_A,
SYNTH_PARAM_ENV_2_A,
SYNTH_PARAM_ENV_3_A,
SYNTH_PARAM_ENV_0_D, SYNTH_PARAM_VCF_ENV_D = SYNTH_PARAM_ENV_0_D,
SYNTH_PARAM_ENV_1_D, SYNTH_PARAM_VCA_ENV_D = SYNTH_PARAM_ENV_1_D,
SYNTH_PARAM_ENV_2_D,
SYNTH_PARAM_ENV_3_D,
SYNTH_PARAM_ENV_0_S, SYNTH_PARAM_VCF_ENV_S = SYNTH_PARAM_ENV_0_S,
SYNTH_PARAM_ENV_1_S, SYNTH_PARAM_VCA_ENV_S = SYNTH_PARAM_ENV_1_S,
SYNTH_PARAM_ENV_2_S,
SYNTH_PARAM_ENV_3_S,
SYNTH_PARAM_ENV_0_R, SYNTH_PARAM_VCF_ENV_R = SYNTH_PARAM_ENV_0_R,
SYNTH_PARAM_ENV_1_R, SYNTH_PARAM_VCA_ENV_R = SYNTH_PARAM_ENV_1_R,
SYNTH_PARAM_ENV_2_R,
SYNTH_PARAM_ENV_3_R,
SYNTH_PARAM_VCF_TYPE,
SYNTH_PARAM_VCF_ORDER,
SYNTH_PARAM_VCF_F,
SYNTH_PARAM_VCF_Q,
SYNTH_PARAM_VCF_ENV_AMT,
SYNTH_PARAM_VCF_F_AMT_0,
SYNTH_PARAM_VCF_F_AMT_1,
SYNTH_PARAM_VCF_F_SRC_0,
SYNTH_PARAM_VCF_F_SRC_1,
SYNTH_PARAM_VCF_F_SRC_OP,
SYNTH_PARAM_VCF_Q_AMT_0,
SYNTH_PARAM_VCF_Q_AMT_1,
SYNTH_PARAM_VCF_Q_SRC_0,
SYNTH_PARAM_VCF_Q_SRC_1,
SYNTH_PARAM_VCF_Q_SRC_OP,
SYNTH_PARAM_LFO_0_SPEED,
SYNTH_PARAM_LFO_1_SPEED,
SYNTH_PARAM_LFO_2_SPEED,
SYNTH_PARAM_LFO_3_SPEED,
SYNTH_PARAM_LFO_0_SMOOTH,
SYNTH_PARAM_LFO_1_SMOOTH,
SYNTH_PARAM_LFO_2_SMOOTH,
SYNTH_PARAM_LFO_3_SMOOTH,
SYNTH_PARAM_LFO_0_DELAY,
SYNTH_PARAM_LFO_1_DELAY,
SYNTH_PARAM_LFO_2_DELAY,
SYNTH_PARAM_LFO_3_DELAY,
SYNTH_PARAM_LFO_0_ATTACK,
SYNTH_PARAM_LFO_1_ATTACK,
SYNTH_PARAM_LFO_2_ATTACK,
SYNTH_PARAM_LFO_3_ATTACK,
SYNTH_PARAM_LFO_0_SHAPE,
SYNTH_PARAM_LFO_1_SHAPE,
SYNTH_PARAM_LFO_2_SHAPE,
SYNTH_PARAM_LFO_3_SHAPE,
SYNTH_PARAM_LFO_0_MODE,
SYNTH_PARAM_LFO_1_MODE,
SYNTH_PARAM_LFO_2_MODE,
SYNTH_PARAM_LFO_3_MODE,
SYNTH_PARAM_LFO_0_SYNC,
SYNTH_PARAM_LFO_1_SYNC,
SYNTH_PARAM_LFO_2_SYNC,
SYNTH_PARAM_LFO_3_SYNC,
SYNTH_PARAM_LFO_0_SYMMETRY,
SYNTH_PARAM_LFO_1_SYMMETRY,
SYNTH_PARAM_LFO_2_SYMMETRY,
SYNTH_PARAM_LFO_3_SYMMETRY,
SYNTH_NUM_PARAMS
};
// --------------------------------------------------------------
// Types
// --------------------------------------------------------------
typedef struct _sparam_info_t
{
UINT32 id;
char *pName;
synth_float_t base, kexp, scenter, pmin, pcenter, pmax, pinterval;
} param_info_t;
// --------------------------------------------------------------
#if defined(__cplusplus)
extern "C" {
#endif
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void paramInfoInit(param_info_t *pObj, UINT32 id, char *pName);
void paramInfoFree(param_info_t *pObj);
void paramInfoSetPMIN(param_info_t *pObj, synth_float_t value);
void paramInfoSetPMAX(param_info_t *pObj, synth_float_t value);
void paramInfoSet(param_info_t *pObj,
synth_float_t base,
synth_float_t kexp,
synth_float_t scenter,
synth_float_t pmin,
synth_float_t pcenter,
synth_float_t pmax,
synth_float_t pinterval);
void paramInfoCopy(param_info_t *pDst, param_info_t *pSrc);
synth_float_t clampParam(param_info_t *pObj, synth_float_t p);
synth_float_t toParam(param_info_t *pObj, synth_float_t s);
synth_float_t toSlider(param_info_t *pObj, synth_float_t p);
param_info_t* getParamInfo(UINT32 type);
#if defined(__cplusplus)
}
#endif
// --------------------------------------------------------------
#endif // _PARAM_SCALE_H_
+97
View File
@@ -0,0 +1,97 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include "synth_defs.h"
#include "sine.h"
// --------------------------------------------------------------
// internal funcs
// --------------------------------------------------------------
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void Sine_Init(sine_gen_t *pObj, synth_float_t fs)
{
Sine_SetFS(pObj, fs);
Sine_Prepare(pObj);
}
void Sine_Free(sine_gen_t *pObj)
{
}
void Sine_SetFS(sine_gen_t *pObj, synth_float_t fs)
{
pObj->fs = SINE_OVERSAMPLING*fs;
pObj->pitch = -1;
}
void Sine_Reset(sine_gen_t *pObj, synth_float_t phase)
{
pObj->y[0] = cos(2*pi*phase);
pObj->y[1] = sin(2*pi*phase);
pObj->fscale = 1;
}
void Sine_Start(sine_gen_t *pObj)
{
pObj->pitch = -1;
pObj->CV_fm = -1;
}
void Sine_Prepare(sine_gen_t *pObj)
{
Sine_Reset(pObj, (synth_float_t)rand()/RAND_MAX);
}
void Sine_Update(sine_gen_t *pObj)
{
synth_float_t freq;
freq = pObj->fscale * pObj->pitch;
pObj->b = 2.0 * sin(freq*pi / pObj->fs);
}
synth_float_t Sine_Process_Scalar(sine_gen_t *pObj, synth_float_t pitch, synth_float_t CV_fm)
{
int i;
synth_float_t a, phi;
// ToDo: amplitude drift correction
// y[0]^2 + y[1]^2 = a;
if (pObj->CV_fm != CV_fm)
{
pObj->CV_fm = CV_fm;
pObj->fscale = (synth_float_t)pow((synth_float_t)2, CV_fm);
Sine_Update(pObj);
}
if (pObj->pitch != pitch)
{
pObj->pitch = pitch;
Sine_Update(pObj);
}
for (i=0; i < SINE_OVERSAMPLING; i++)
{
pObj->y[0] = pObj->y[0] - pObj->b*pObj->y[1];
pObj->y[1] = pObj->y[1] + pObj->b*pObj->y[0];
}
a = pObj->y[0]*pObj->y[0] + pObj->y[1]*pObj->y[1];
if (fabs(a - 1) > 0.5)
{
phi = atan2(pObj->y[0], pObj->y[1]);
pObj->y[0] = sin(phi);
pObj->y[1] = cos(phi);
}
return -pObj->y[0];
}
+43
View File
@@ -0,0 +1,43 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#ifndef _SINE_H_
#define _SINE_H_
#include "synth_defs.h"
#define SINE_OVERSAMPLING 3
// --------------------------------------------------------------
// Types
// --------------------------------------------------------------
typedef struct _ssine_gen_t
{
synth_float_t fs, fscale, pitch, CV_fm;
synth_float_t b, y[2];
} sine_gen_t;
// --------------------------------------------------------------
#if defined(__cplusplus)
extern "C" {
#endif
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void Sine_Init(sine_gen_t *pObj, synth_float_t fs);
void Sine_Free(sine_gen_t *pObj);
void Sine_SetFS(sine_gen_t *pObj, synth_float_t fs);
void Sine_Reset(sine_gen_t *pObj, synth_float_t phi);
void Sine_Prepare(sine_gen_t *pObj);
void Sine_Start(sine_gen_t *pObj);
void Sine_Update(sine_gen_t *pObj);
synth_float_t Sine_Process_Scalar(sine_gen_t *pObj, synth_float_t pitch, synth_float_t CV_fm);
#if defined(__cplusplus)
}
#endif
// --------------------------------------------------------------
#endif // _SINE_H_
+129
View File
@@ -0,0 +1,129 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include "synth_defs.h"
#include "smooth.h"
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void Smooth_Update(smooth_t *pObj)
{
pObj->a_r = (synth_float_t)1/(pObj->fs*pObj->T_r*SMOOTH_KE);
pObj->a_f = (synth_float_t)1/(pObj->fs*pObj->T_f);
}
void Smooth_Init(smooth_t *pObj, synth_float_t fs, synth_float_t T_r, synth_float_t T_f, synth_float_t inital_value)
{
pObj->fs = fs;
pObj->T_r = T_r;
pObj->T_f = T_f;
pObj->y = inital_value;
Smooth_Update(pObj);
}
void Smooth_Free(smooth_t *pObj)
{
}
void Smooth_SetValue(smooth_t *pObj, synth_float_t value)
{
pObj->y = value;
}
void Smooth_SetFS(smooth_t *pObj, synth_float_t fs)
{
pObj->fs = fs;
Smooth_Update(pObj);
}
void Smooth_SetT(smooth_t *pObj, synth_float_t T_r, synth_float_t T_f)
{
pObj->T_r = T_r;
pObj->T_f = T_f;
Smooth_Update(pObj);
}
synth_float_t Smooth_ProcessScalar(smooth_t *pObj, synth_float_t x_hard, synth_float_t in)
{
if (pObj->y < x_hard)
pObj->y += pObj->a_r*(x_hard - pObj->y);
else
pObj->y += pObj->a_f*(x_hard - pObj->y);
return pObj->y*in;
}
void Smooth_Process_VV(smooth_t *pObj, synth_float_t x_hard, synth_float_t *pIn, synth_float_t *pOut, UINT32 len)
{
UINT32 i;
if (Smooth_is_settled(pObj, x_hard) && (fabs(x_hard) < 1E-18))
{
for (i = 0; i < len; i++)
{
pOut[i] = 0;
}
return;
}
if (Smooth_is_settled(pObj, x_hard))
{
for (i = 0; i < len; i++)
{
pOut[i] = x_hard*pIn[i];
}
return;
}
for (i = 0; i < len; i++)
{
if (pObj->y < x_hard)
pObj->y += pObj->a_r*(x_hard - pObj->y);
else
pObj->y += pObj->a_f*(x_hard - pObj->y);
pOut[i] = pObj->y*pIn[i];
}
}
void Smooth_Process_V(smooth_t *pObj, synth_float_t x_hard, synth_float_t *pOut, UINT32 len)
{
UINT32 i;
if (Smooth_is_settled(pObj, x_hard) && (fabs(x_hard) < 1E-18))
{
for (i = 0; i < len; i++)
{
pOut[i] = 0;
}
return;
}
if (Smooth_is_settled(pObj, x_hard))
{
for (i = 0; i < len; i++)
{
pOut[i] = x_hard;
}
return;
}
for (i = 0; i < len; i++)
{
if (pObj->y < x_hard)
pObj->y += pObj->a_r*(x_hard - pObj->y);
else
pObj->y += pObj->a_f*(x_hard - pObj->y);
pOut[i] = pObj->y;
}
}
UINT32 Smooth_is_settled(smooth_t *pObj, synth_float_t x_hard)
{
return (fabs(pObj->y - x_hard) < SMOOTH_TOL);
}
+46
View File
@@ -0,0 +1,46 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#ifndef _SMOOTH_H_
#define _SMOOTH_H_
#include "synth_defs.h"
#define SMOOTH_TOL ((synth_float_t)(1E-4))
#define SMOOTH_KE ((synth_float_t)(1-exp(-1)))
// --------------------------------------------------------------
// Types
// --------------------------------------------------------------
typedef struct _ssmooth_t
{
synth_float_t y, fs;
synth_float_t T_r, a_r;
synth_float_t T_f, a_f;
} smooth_t;
// --------------------------------------------------------------
#if defined(__cplusplus)
extern "C" {
#endif
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void Smooth_Init(smooth_t *pObj, synth_float_t fs, synth_float_t T_r, synth_float_t T_f, synth_float_t inital_value);
void Smooth_Free(smooth_t *pObj);
void Smooth_SetValue(smooth_t *pObj, synth_float_t value);
void Smooth_SetFS(smooth_t *pObj, synth_float_t fs);
void Smooth_SetT(smooth_t *pObj, synth_float_t T_r, synth_float_t T_f);
synth_float_t Smooth_ProcessScalar(smooth_t *pObj, synth_float_t x_hard, synth_float_t in);
void Smooth_Process_VV(smooth_t *pObj, synth_float_t x_hard, synth_float_t *pIn, synth_float_t *pOut, UINT32 len);
void Smooth_Process_V(smooth_t *pObj, synth_float_t x_hard, synth_float_t *pOut, UINT32 len);
UINT32 Smooth_is_settled(smooth_t *pObj, synth_float_t x_hard);
#if defined(__cplusplus)
}
#endif
// --------------------------------------------------------------
#endif // _SMOOTH_H_
+33
View File
@@ -0,0 +1,33 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#include <windows.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
// --------------------------------------------------------------
// internal funcs
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void SynthDebug(char *fmtstr, ...)
{
#ifndef SYNTH_DEBUG
/* Empty body, so a good compiler will optimise calls
to pmesg away */
#else
char buf[1024];
va_list args;
va_start(args, fmtstr);
vsprintf(buf, fmtstr, args);
va_end(args);
OutputDebugString(buf);
#endif /* SYNTH_DEBUG */
}
+79
View File
@@ -0,0 +1,79 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#ifndef _SYNTH_DEFS_H_
#define _SYNTH_DEFS_H_
#include "synth_types.h"
// --------------------------------------------------------------
// Defs
// --------------------------------------------------------------
#define GAIN_EPSILON 10.0
#define MAX_POLYPHONY 256
#define SYNTH_BANDWIDTH 0.833
#define NUM_PROGRAMS 64
#define NUM_FREQS 128
#define NUM_MIDI_CONTROLLERS 128
#define VOICE_NUM_OSC 2
#define VOICE_NUM_LFO 4
#define VOICE_NUM_ENV 4
#define FILTER_ORDER 2
#define FILTER_SWEEP_BASE ((synth_float_t)10)
#define FILTER_MAX_ORDER 4
#define FILTER_F_MIN ((synth_float_t)18)
#define FILTER_F_MAX ((synth_float_t)18000)
#define FILTER_Q_MIN 0.7
#define FILTER_Q_MAX 100
#define FILTER_TABLE_SIZE (4096)
#define FILTER_INTEROLATION_ORDER 1
#define BLIT_NUM_HARM_MAX (900)
#define BLIT_TABLE_SIZE_MIN (1024)
#define BLIT_TABLE_SIZE_MAX (4096)
#define BLIT_TABLE_OVERSAMPLING (4)
#define BLIT_INTEROLATION_ORDER (2)
#define SYNTH_LIMITER_RISE_TIME 0.001 //s
#define SYNTH_LIMITER_FALL_TIME 1.000 //s
#define SYNTH_LIMITER_THRESHOLD 3 // dbFS
#define SYNTH_MAX_BUFSIZE 8192
#ifndef pi
#define pi 3.1415926535897932384626433832795
#define pi_mult_2 (2*pi)
#define pi_div_2 (0.5*pi)
#endif
#if defined(__cplusplus)
extern "C" {
#endif
void SynthDebug(char *fmtstr, ...);
#if defined(__cplusplus)
}
#endif
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
#include "voice.h"
#include "vco.h"
#include "noise.h"
#include "smooth.h"
#include "vcf.h"
#include "lfo.h"
#include "env.h"
#include "param_scale.h"
#endif // _SYNTH_DEFS_H_
+38
View File
@@ -0,0 +1,38 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#ifndef _SYNTH_TYPES_H_
#define _SYNTH_TYPES_H_
// --------------------------------------------------------------
// Types
// --------------------------------------------------------------
#define synth_float_t double
#ifndef UINT32
#define UINT32 unsigned int
#endif
#ifndef INT32
#define INT32 signed int
#endif
#ifndef UINT16
#define UINT16 unsigned short
#endif
#ifndef INT16
#define INT16 signed short
#endif
//#define SYNTH_DOUBLE_PRECISION 1
//typedef struct _ssynth_gbl_data_t
//{
// synth_float_t **osc_ppH;
// iir_coef_t **ppIIR_coef;
//} synth_gbl_data_t;
//extern synth_gbl_data_t g_synth_data;
#endif // _SYNTH_TYPES_H_
+485
View File
@@ -0,0 +1,485 @@
/*************************************************************************/
/* vcf.c */
/*************************************************************************/
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include "synth_defs.h"
#include "vcf.h"
#include "fast_trig/fast_trig.h"
/*************************************************************************/
/* Global Variables */
/*************************************************************************/
/******************************************************************************/
void VCF_Init(vcf_t *pObj, UINT32 id, vcf_common_t *pCom, synth_float_t fs)
{
pObj->pCom = pCom;
pObj->id = id;
pObj->fs = fs;
if (id == 0)
{
VCF_ModInit(pObj);
}
pObj->pOut = NULL;
pObj->pCoef = NULL;
pObj->bufsize = 0;
VCF_SetType(pObj, VCF_FILTERTYPE_LOWPASS);
VCF_SetOrder(pObj, 4);
pObj->req_filter_update = 0;
VCF_clear_state(pObj);
VCF_SetBufsize(pObj, SYNTH_MAX_BUFSIZE);
VCF_FilterParamUpdate(pObj);
VCF_SetF(pObj, 20000);
VCF_SetQ(pObj, 1);
}
void VCF_Free(vcf_t *pObj)
{
VCF_SetBufsize(pObj, 0);
if (pObj->id == 0)
{
VCF_ModFree(pObj);
}
}
void VCF_ModInit(vcf_t *pObj)
{
vcf_common_t *pCom = pObj->pCom;
pCom->pLUT_cos = (synth_float_t*)malloc(FILTER_TABLE_SIZE*sizeof(synth_float_t));
pCom->pLUT_sin = (synth_float_t*)malloc(FILTER_TABLE_SIZE*sizeof(synth_float_t));
}
void VCF_ModFree(vcf_t *pObj)
{
vcf_common_t *pCom = pObj->pCom;
free(pCom->pLUT_cos);
free(pCom->pLUT_sin);
}
void VCF_LUT_gen(vcf_t *pObj)
{
int i;
synth_float_t cv, omega;
vcf_common_t *pCom = pObj->pCom;
for (i=0; i < FILTER_TABLE_SIZE; i++)
{
cv = (synth_float_t)i/(FILTER_TABLE_SIZE-1);
omega = VCF_cv2omega(pObj, cv);
pCom->pLUT_cos[i] = cos(pi*omega);
pCom->pLUT_sin[i] = sin(pi*omega);
}
}
void VCF_FilterParamUpdate(vcf_t *pObj)
{
pObj->omega_max = 2*FILTER_F_MAX/pObj->fs;
pObj->omega_min = 2*FILTER_F_MIN/pObj->fs;
pObj->num_octaves = log(FILTER_F_MAX/FILTER_F_MIN)/log(FILTER_SWEEP_BASE);
if (pObj->id == 0)
{
VCF_LUT_gen(pObj);
}
}
synth_float_t VCF_LUT_get_cos(vcf_t *pObj, synth_float_t cv)
{
int ni, ni_next;
synth_float_t n, nf;
vcf_common_t *pCom = pObj->pCom;
n = min(1, max(0, cv))*(FILTER_TABLE_SIZE-1);
ni = (int)n;
nf = n - (synth_float_t)ni;
ni_next = min(FILTER_TABLE_SIZE-1, ni+1);
return (pCom->pLUT_cos[ni_next] - pCom->pLUT_cos[ni])*nf + pCom->pLUT_cos[ni];
}
synth_float_t VCF_LUT_get_sin(vcf_t *pObj, synth_float_t cv)
{
int ni, ni_next;
synth_float_t n, nf;
vcf_common_t *pCom = pObj->pCom;
n = min(1, max(0, cv))*(FILTER_TABLE_SIZE-1);
ni = (int)n;
nf = n - (synth_float_t)ni;
ni_next = min(FILTER_TABLE_SIZE-1, ni+1);
return (pCom->pLUT_sin[ni_next] - pCom->pLUT_sin[ni])*nf + pCom->pLUT_sin[ni];
}
void VCF_SetBufsize(vcf_t *pObj, UINT32 size)
{
if (pObj->bufsize == size)
return;
pObj->bufsize = size;
if (pObj->pOut)
free(pObj->pOut);
if (pObj->pCoef)
free(pObj->pCoef);
pObj->pOut = NULL;
pObj->pCoef = NULL;
if (!size)
return;
pObj->pOut = (synth_float_t*)malloc(pObj->bufsize*sizeof(synth_float_t));
pObj->pCoef = (vcf_coef_t*)malloc(pObj->bufsize*sizeof(vcf_coef_t));
pObj->pCoeff_last = pObj->pCoef;
VCF_Coeff_update(pObj);
}
void VCF_SetFS(vcf_t *pObj, synth_float_t fs)
{
pObj->fs = fs;
VCF_FilterParamUpdate(pObj);
pObj->req_filter_update = 1;
}
void VCF_SetF(vcf_t *pObj, synth_float_t f)
{
if (f > pObj->fs/2)
f = FILTER_F_MAX;
if (f < FILTER_F_MIN)
f = FILTER_F_MIN;
if (f < 0)
f = FILTER_F_MIN;
pObj->cv_f_bias = VCF_omega2cv(pObj, 2*f/pObj->fs);
pObj->req_filter_update = 1;
}
void VCF_SetQ(vcf_t *pObj, synth_float_t q)
{
pObj->cv_q_bias = max(FILTER_Q_MIN, q);
pObj->req_filter_update = 1;
}
void VCF_SetType(vcf_t *pObj, UINT32 type)
{
pObj->type = type;
VCF_SetQ(pObj, pObj->cv_q_bias);
VCF_Coeff_update(pObj);
}
synth_float_t IIRCalcQp(unsigned p, unsigned N)
{
return 1.0f/(synth_float_t)(2*sin(pi*(2*p-1)/(2*N)));
}
void VCF_SetOrder(vcf_t *pObj, UINT32 order)
{
UINT32 p;
if (pObj->order == order)
return;
if (order % 2)
return;
if (order > FILTER_MAX_ORDER)
return;
pObj->order = order;
pObj->num_sections = pObj->order/2;
for(p=0; p < pObj->num_sections; p++)
{
pObj->pQP_inv[p] = (synth_float_t)1.0/IIRCalcQp(p+1, pObj->order);
}
VCF_clear_state(pObj);
VCF_SetQ(pObj, pObj->cv_q_bias);
VCF_Coeff_update(pObj);
}
void VCF_Coeff_update(vcf_t *pObj)
{
pObj->req_filter_update = 1;
}
void VCF_clear_state(vcf_t *pObj)
{
UINT32 p;
for(p=0; p < pObj->num_sections; p++)
{
pObj->pState[p].xn1 = 0;
pObj->pState[p].xn2 = 0;
pObj->pState[p].yn1 = 0;
pObj->pState[p].yn2 = 0;
}
VCF_Coeff_update(pObj);
}
synth_float_t VCF_omega2cv(vcf_t *pObj, synth_float_t omega)
{
synth_float_t cv;
cv = log(omega/pObj->omega_min)/(pObj->num_octaves * log(FILTER_SWEEP_BASE));
return min(1, max(0, cv));
}
synth_float_t VCF_cv2omega(vcf_t *pObj, synth_float_t cv)
{
synth_float_t omega;
omega = pObj->omega_min*pow(FILTER_SWEEP_BASE, pObj->num_octaves*min(1, max(0, cv)));
return omega;
}
void VCF_CalcCoeff_LPF(vcf_t *pObj, vcf_coef_t *pCoeff, synth_float_t *pCV_f, synth_float_t *pCV_q, UINT32 len)
{
synth_float_t a0_inv;
synth_float_t alpha, ks, kc, Q_inv, q, cv;
unsigned p, n, filter_changed;
ks = 0;
kc = 0;
Q_inv = 0;
for(n=0; n < len; n++)
{
filter_changed = pObj->req_filter_update;
if (fabs(pObj->cv_f_last - pCV_f[n]) > FILTER_RECALC_F_THRESH)
filter_changed = 1;
if (fabs(pObj->cv_q_last - pCV_q[n]) > FILTER_RECALC_Q_THRESH)
filter_changed = 1;
if (filter_changed)
{
pObj->req_filter_update = 0;
pObj->cv_f_last = pCV_f[n];
cv = pObj->cv_f_bias + pCV_f[n];
ks = VCF_LUT_get_sin(pObj, cv);
kc = VCF_LUT_get_cos(pObj, cv);
q = min(FILTER_Q_MAX, max(FILTER_Q_MIN, pObj->cv_q_bias + FILTER_Q_MAX*pCV_q[n]));
pObj->cv_q_last = q;
if (pObj->order == 2)
q *= q;
Q_inv = (synth_float_t)1.0/q;
pObj->pCoeff_last = pCoeff;
}
for(p=0; p < pObj->num_sections; p++)
{
if (filter_changed)
{
alpha = 0.5f*ks * Q_inv * pObj->pQP_inv[p];
a0_inv = (synth_float_t)1.0/(1 + alpha);
(*pCoeff).ak1 = -2.0f*kc *a0_inv;
(*pCoeff).ak2 = (1 - alpha) *a0_inv;
(*pCoeff).bk1 = (1 - kc) *a0_inv;
(*pCoeff).bk0 = 0.5f*(1 - kc) *a0_inv;
(*pCoeff).bk2 = (*pCoeff).bk0;
}
else
{
*pCoeff = pObj->pCoeff_last[p];
}
pCoeff++;
}
}
}
void VCF_CalcCoeff_HPF(vcf_t *pObj, vcf_coef_t *pCoeff, synth_float_t *pCV_f, synth_float_t *pCV_q, UINT32 len)
{
synth_float_t a0_inv;
synth_float_t alpha, ks, kc, Q_inv, q, cv;
unsigned p, n, filter_changed;
ks = 0;
kc = 0;
Q_inv = 0;
for(n=0; n < len; n++)
{
filter_changed = pObj->req_filter_update;
if (fabs(pObj->cv_f_last - pCV_f[n]) > FILTER_RECALC_F_THRESH)
filter_changed = 1;
if (fabs(pObj->cv_q_last - pCV_q[n]) > FILTER_RECALC_Q_THRESH)
filter_changed = 1;
if (filter_changed)
{
pObj->req_filter_update = 0;
pObj->cv_f_last = pCV_f[n];
cv = pObj->cv_f_bias + pCV_f[n];
ks = VCF_LUT_get_sin(pObj, cv);
kc = VCF_LUT_get_cos(pObj, cv);
q = min(FILTER_Q_MAX, max(FILTER_Q_MIN, pObj->cv_q_bias + FILTER_Q_MAX*pCV_q[n]));
pObj->cv_q_last = q;
if (pObj->order == 2)
q *= q;
Q_inv = (synth_float_t)1.0/q;
pObj->pCoeff_last = pCoeff;
}
for(p=0; p < pObj->num_sections; p++)
{
if (filter_changed)
{
alpha = 0.5f*ks * Q_inv * pObj->pQP_inv[p];
a0_inv = (synth_float_t)1.0/(1 + alpha);
(*pCoeff).ak1 = -2.0f*kc *a0_inv;
(*pCoeff).ak2 = (1 - alpha) *a0_inv;
(*pCoeff).bk1 = - (1 + kc) *a0_inv;
(*pCoeff).bk0 = 0.5f*(1 + kc) *a0_inv;
(*pCoeff).bk2 = (*pCoeff).bk0;
}
else
{
*pCoeff = pObj->pCoeff_last[p];
}
pCoeff++;
}
}
}
void VCF_CalcCoeff_BPF(vcf_t *pObj, vcf_coef_t *pCoeff, synth_float_t *pCV_f, synth_float_t *pCV_q, UINT32 len)
{
synth_float_t a0_inv;
synth_float_t alpha, ks, kc, Q_inv, q, cv;
unsigned p, n, filter_changed;
ks = 0;
kc = 0;
Q_inv = 0;
for(n=0; n < len; n++)
{
filter_changed = pObj->req_filter_update;
if (fabs(pObj->cv_f_last - pCV_f[n]) > FILTER_RECALC_F_THRESH)
filter_changed = 1;
if (fabs(pObj->cv_q_last - pCV_q[n]) > FILTER_RECALC_Q_THRESH)
filter_changed = 1;
if (filter_changed)
{
pObj->req_filter_update = 0;
pObj->cv_f_last = pCV_f[n];
cv = pObj->cv_f_bias + pCV_f[n];
ks = VCF_LUT_get_sin(pObj, cv);
kc = VCF_LUT_get_cos(pObj, cv);
q = min(FILTER_Q_MAX, max(FILTER_Q_MIN, pObj->cv_q_bias + FILTER_Q_MAX*pCV_q[n]));
pObj->cv_q_last = q;
if (pObj->order == 2)
q *= q;
Q_inv = (synth_float_t)1.0/q;
pObj->pCoeff_last = pCoeff;
}
for(p=0; p < pObj->num_sections; p++)
{
if (filter_changed)
{
alpha = 0.5f*ks * Q_inv * pObj->pQP_inv[p];
a0_inv = (synth_float_t)1.0/(1 + alpha);
(*pCoeff).ak1 = -2.0f*kc *a0_inv;
(*pCoeff).ak2 = (1 - alpha) *a0_inv;
(*pCoeff).bk1 = 0;
(*pCoeff).bk0 = 0.5*ks *a0_inv;
(*pCoeff).bk2 = -(*pCoeff).bk0;
}
else
{
*pCoeff = pObj->pCoeff_last[p];
}
pCoeff++;
}
}
}
void VCF_CalcCoeff(vcf_t *pObj, vcf_coef_t *pCoeff, synth_float_t *pFG, synth_float_t *pQ, UINT32 len)
{
switch(pObj->type)
{
case VCF_FILTERTYPE_LOWPASS:
VCF_CalcCoeff_LPF(pObj, pCoeff, pFG, pQ, len);
break;
case VCF_FILTERTYPE_HIGHPASS:
VCF_CalcCoeff_HPF(pObj, pCoeff, pFG, pQ, len);
break;
case VCF_FILTERTYPE_BANDPASS:
VCF_CalcCoeff_BPF(pObj, pCoeff, pFG, pQ, len);
break;
default:
VCF_CalcCoeff_LPF(pObj, pCoeff, pFG, pQ, len);
break;
}
}
synth_float_t* VCF_ProcessDataV(vcf_t *pObj, synth_float_t *pCV_f, synth_float_t *pCV_q, synth_float_t *pX, UINT32 len)
{
synth_float_t xp, yp, *pY;
unsigned i, p;
vcf_state_t *pState = pObj->pState;
vcf_coef_t *pCoeff;
VCF_CalcCoeff(pObj, pObj->pCoef, pCV_f, pCV_q, len);
pCoeff = pObj->pCoef;
yp = 0;
pY = pObj->pOut;
for (i=0; i<len; i++)
{
xp = pX[i];
for (p=0; p < pObj->num_sections; p++)
{
yp = (*pCoeff).bk0*xp
+ (*pCoeff).bk1*pState[p].xn1
+ (*pCoeff).bk2*pState[p].xn2
- (*pCoeff).ak1*pState[p].yn1
- (*pCoeff).ak2*pState[p].yn2;
pCoeff++;
pState[p].yn2 = pState[p].yn1;
pState[p].yn1 = yp;
pState[p].xn2 = pState[p].xn1;
pState[p].xn1 = xp;
xp = yp;
}
pY[i] = yp;
}
return pObj->pOut;
}
+109
View File
@@ -0,0 +1,109 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#ifndef _FILTER_H_
#define _FILTER_H_
#include "synth_defs.h"
#define FILTER_RECALC_F_THRESH (0.000)
#define FILTER_RECALC_Q_THRESH (0.000)
// --------------------------------------------------------------
// Types
// --------------------------------------------------------------
enum
{
VCF_FILTERTYPE_LOWPASS = 0,
VCF_FILTERTYPE_HIGHPASS,
VCF_FILTERTYPE_BANDPASS,
VCF_NUM_FILTERTYPES
};
enum
{
VCF_FILTERORDER_2 = 0,
VCF_FILTERORDER_4,
VCF_NUM_FILTERORDER
};
typedef struct _svcf_coef_t
{
synth_float_t ak0, ak1, ak2;
synth_float_t bk0, bk1, bk2;
} vcf_coef_t;
typedef struct _svcf_state_t
{
synth_float_t xn1, xn2;
synth_float_t yn1, yn2;
} vcf_state_t;
typedef struct _svcf_common_t
{
synth_float_t *pLUT_cos;
synth_float_t *pLUT_sin;
} vcf_common_t;
typedef struct _svcf_t
{
vcf_common_t *pCom;
UINT32 id;
UINT32 type;
UINT32 order;
UINT32 num_sections;
synth_float_t fs;
vcf_coef_t *pCoef;
vcf_coef_t *pCoeff_last;
vcf_state_t pState[FILTER_MAX_ORDER/2];
synth_float_t pQP_inv[FILTER_MAX_ORDER/2];
synth_float_t *pOut;
synth_float_t cv_f_bias;
synth_float_t cv_q_bias;
synth_float_t cv_f_last;
synth_float_t cv_q_last;
UINT32 req_filter_update;
UINT32 bufsize;
synth_float_t num_octaves;
synth_float_t omega_min;
synth_float_t omega_max;
} vcf_t;
// --------------------------------------------------------------
#if defined(__cplusplus)
extern "C" {
#endif
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void VCF_ModInit(vcf_t *pObj);
void VCF_ModFree(vcf_t *pObj);
void VCF_Init(vcf_t *pObj, UINT32 id, vcf_common_t *pCom, synth_float_t fs);
void VCF_Free(vcf_t *pObj);
void VCF_SetBufsize(vcf_t *pObj, UINT32 bufsize);
void VCF_FilterParamUpdate(vcf_t *pObj);
void VCF_Coeff_update(vcf_t *pObj);
void VCF_SetFS(vcf_t *pObj, synth_float_t fs);
void VCF_SetF(vcf_t *pObj, synth_float_t f);
void VCF_SetQ(vcf_t *pObj, synth_float_t q);
void VCF_SetType(vcf_t *pObj, UINT32 type);
void VCF_SetOrder(vcf_t *pObj, UINT32 order);
synth_float_t VCF_cv2omega(vcf_t *pObj, synth_float_t omega);
synth_float_t VCF_omega2cv(vcf_t *pObj, synth_float_t cv);
void VCF_clear_state(vcf_t *pObj);
void VCF_CalcCoeff(vcf_t *pObj, vcf_coef_t *pCoeff, synth_float_t *pCV_f, synth_float_t *pCV_q, UINT32 len);
synth_float_t* VCF_ProcessDataV(vcf_t *pObj, synth_float_t *pCV_f, synth_float_t *pCV_q, synth_float_t *pX, UINT32 len);
#if defined(__cplusplus)
}
#endif
// --------------------------------------------------------------
#endif // _FILTER_H_
+209
View File
@@ -0,0 +1,209 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include "synth_defs.h"
#include "blit.h"
#include "vco.h"
#include "wavetable.h"
#include "fir/fir2.h"
extern unsigned char _g_wave_rawdata[38400];
extern wt_descr_t _g_wt_descr[WT_NUM_WAVETABLES];
// --------------------------------------------------------------
// internal funcs
// --------------------------------------------------------------
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void VCO_ModInit(vco_common_t *pCom)
{
BLIT_ModInit(&pCom->blit);
}
void VCO_ModFree(vco_common_t *pCom)
{
BLIT_ModFree(&pCom->blit);
}
void VCO_Init(osc_t *pObj, UINT32 id, vco_common_t *pCom, synth_float_t fs)
{
pObj->pCom = pCom;
pObj->id = id;
pObj->fs = fs;
if (pObj->id == 0)
{
VCO_ModInit(pCom);
}
pObj->pOut = NULL;
pObj->bufsize = 0;
VCO_SetBufsize(pObj, SYNTH_MAX_BUFSIZE);
pObj->param[OSC_PARAM2_WAVEFORM] = OSC_WAVEFORM_SAWTOOTH;
Sine_Init(&pObj->sine, fs);
BLIT_Init(&pObj->blep, &pCom->blit, fs);
WT_Init(&pObj->wt, id, &pCom->wt, fs);
pObj->impulse = 10;
}
void VCO_Free(osc_t *pObj)
{
Sine_Free(&pObj->sine);
BLIT_Free(&pObj->blep);
WT_Free(&pObj->wt);
VCO_SetBufsize(pObj, 0);
if (pObj->id == 0)
{
VCO_ModFree(pObj->pCom);
}
}
void VCO_SetFS(osc_t *pObj, synth_float_t fs)
{
pObj->fs = fs;
Sine_SetFS(&pObj->sine, fs);
BLIT_SetFS(&pObj->blep, fs);
WT_SetFS(&pObj->wt, fs);
}
void VCO_SetBufsize(osc_t *pObj, UINT32 size)
{
BLIT_SetBufsize(&pObj->blep, size);
if (pObj->bufsize == size)
return;
pObj->bufsize = size;
if (pObj->pOut)
free(pObj->pOut);
pObj->pOut = NULL;
if (!size)
return;
pObj->pOut = (synth_float_t*)malloc(pObj->bufsize*sizeof(synth_float_t));
}
void VCO_Reset(osc_t *pObj, synth_float_t phase)
{
Sine_Reset(&pObj->sine, phase);
BLIT_Reset(&pObj->blep, phase);
WT_Reset(&pObj->wt, phase);
pObj->impulse = 10;
}
void VCO_Start(osc_t *pObj)
{
Sine_Start(&pObj->sine);
BLIT_Start(&pObj->blep);
WT_Start(&pObj->wt);
}
void VCO_Param2Set(osc_t *pObj, UINT32 type, synth_float_t value)
{
UINT32 wt_table;
switch(type)
{
case OSC_PARAM2_WAVEFORM:
if (pObj->param[type] == (UINT32)value)
break;
pObj->param[type] = (UINT32)value;
if ((pObj->param[OSC_PARAM2_WAVEFORM] >= OSC_WAVEFORM_WAVETABLE) && (pObj->param[OSC_PARAM2_WAVEFORM] < (OSC_WAVEFORM_WAVETABLE+WT_NUM_WAVETABLES)))
{
wt_table = (UINT32)(pObj->param[OSC_PARAM2_WAVEFORM]-OSC_WAVEFORM_WAVETABLE);
// WT_Param2Set(&pObj->wt, WT_PARAM2_WAVEFORM, WT_WAVEFORM_REGULAR);
WT_Param2Set(&pObj->wt, WT_PARAM2_WAVEFORM, WT_WAVEFORM_INTERPOLATED);
WT_Param2Set(&pObj->wt, WT_PARAM2_WAVETABLE_ID, wt_table);
}
Sine_Prepare(&pObj->sine);
BLIT_Prepare(&pObj->blep, 1024);
WT_Prepare(&pObj->wt);
break;
case OSC_PARAM2_DUTYCYCLE:
pObj->param[type] = value;
BLIT_SetDutyCycle(&pObj->blep, value);
WT_Param2Set(&pObj->wt, WT_PARAM2_WAVETABLE_ENTRY, value);
break;
default:
break;
}
}
void VCO_ProcessDataV(osc_t *pObj, synth_float_t *pPitch, synth_float_t *pCV_fm, synth_float_t *pCV_pwm, UINT32 *pSyncIn, UINT32 *pSyncOut, UINT32 len)
{
UINT32 i, is_slave;
synth_float_t *pOut;
synth_float_t out;
pOut = pObj->pOut;
is_slave = (pSyncIn != NULL) && (pSyncOut == NULL);
if (pSyncOut)
memset(pSyncOut, 0, len*sizeof(synth_float_t));
// Create output
if (pObj->param[OSC_PARAM2_WAVEFORM] == OSC_WAVEFORM_SAWTOOTH)
{
BLIT_Process_SAW_Vector(&pObj->blep, pPitch, pCV_fm, pSyncIn, pSyncOut, pObj->pOut, len);
}
if (pObj->param[OSC_PARAM2_WAVEFORM] == OSC_WAVEFORM_SQUARE)
{
BLIT_Process_SQR_Vector(&pObj->blep, pPitch, pCV_fm, pCV_pwm, pSyncIn, pSyncOut, pObj->pOut, len);
}
if (pObj->param[OSC_PARAM2_WAVEFORM] == OSC_WAVEFORM_TRIANGLE)
{
BLIT_Process_TRI_Vector(&pObj->blep, pPitch, pCV_fm, pSyncIn, pSyncOut, pObj->pOut, len);
}
if (pObj->param[OSC_PARAM2_WAVEFORM] == OSC_WAVEFORM_SINE)
{
for (i=0; i< len; i++)
{
out = Sine_Process_Scalar(&pObj->sine, pPitch[i], pCV_fm[i]);
if(is_slave && pSyncIn[i])
{
Sine_Reset(&pObj->sine, 0);
}
*(pOut++) = out;
}
}
if (pObj->param[OSC_PARAM2_WAVEFORM] == OSC_WAVEFORM_IMPULSE)
{
for (i=0; i< len; i++)
{
out = pObj->impulse;
pObj->impulse = 0;
*(pOut++) = out;
}
}
if ((pObj->param[OSC_PARAM2_WAVEFORM] >= OSC_WAVEFORM_WAVETABLE) && (pObj->param[OSC_PARAM2_WAVEFORM] < (OSC_WAVEFORM_WAVETABLE+WT_NUM_WAVETABLES)))
{
WT_ProcessDataV(&pObj->wt, pPitch, pCV_fm, pCV_pwm, pObj->pOut, len);
}
}
synth_float_t* VCO_GetProcessBuffer(osc_t *pObj)
{
return pObj->pOut;
}
+83
View File
@@ -0,0 +1,83 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#ifndef _VCO_H_
#define _VCO_H_
#include "synth_types.h"
#include "noise.h"
#include "sine.h"
#include "blit.h"
#include "wavetable.h"
#define OSC_RECALC_THRESH 0.001f
// --------------------------------------------------------------
// Types
// --------------------------------------------------------------
enum
{
OSC_WAVEFORM_SAWTOOTH,
OSC_WAVEFORM_SQUARE,
OSC_WAVEFORM_TRIANGLE,
OSC_WAVEFORM_SINE,
OSC_WAVEFORM_IMPULSE,
OSC_WAVEFORM_WAVETABLE,
OSC_NUM_WAVEFORMS = OSC_WAVEFORM_WAVETABLE+WT_NUM_WAVETABLES
};
enum
{
OSC_PARAM2_WAVEFORM,
OSC_PARAM2_DUTYCYCLE,
OSC_NUM_PARAMS
};
typedef struct _svco_common_t
{
blit_common_t blit;
wt_common_t wt;
// synth_float_t wavetable[300][128];
} vco_common_t;
typedef struct _sosc_t
{
UINT32 id;
vco_common_t *pCom;
synth_float_t param[OSC_NUM_PARAMS];
synth_float_t fs;
blit_t blep;
wt_t wt;
UINT32 bufsize;
synth_float_t *pOut;
sine_gen_t sine;
synth_float_t impulse;
} osc_t;
// --------------------------------------------------------------
#if defined(__cplusplus)
extern "C" {
#endif
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void VCO_ModInit(vco_common_t *pCom);
void VCO_ModFree(vco_common_t *pCom);
void VCO_Init(osc_t *pObj, UINT32 id, vco_common_t *pCom, synth_float_t fs);
void VCO_Free(osc_t *pObj);
void VCO_SetBufsize(osc_t *pObj, UINT32 size);
void VCO_SetFS(osc_t *pObj, synth_float_t fs);
void VCO_Reset(osc_t *pObj, synth_float_t phase);
void VCO_Start(osc_t *pObj);
void VCO_Param2Set(osc_t *pObj, UINT32 type, synth_float_t value);
void VCO_ProcessDataV(osc_t *pObj, synth_float_t *pPitch, synth_float_t *pCV_fm, synth_float_t *pCV_pwm, UINT32 *pSyncIn, UINT32 *pSyncOut, UINT32 len);
synth_float_t* VCO_GetProcessBuffer(osc_t *pObj);
#if defined(__cplusplus)
}
#endif
// --------------------------------------------------------------
#endif // _VCO_H_
+191
View File
@@ -0,0 +1,191 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include "synth_defs.h"
#include "vector_utils.h"
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void Add_inplace_VS(synth_float_t *pSrcDst1, synth_float_t gain1, synth_float_t src2, UINT32 len)
{
if (gain1 == 0)
{
while(len--)
{
*(pSrcDst1) = src2;
pSrcDst1++;
}
return;
}
while(len--)
{
*(pSrcDst1) = *(pSrcDst1)*gain1 + src2;
pSrcDst1++;
}
}
void Add_inplace_VV(synth_float_t *pSrcDst1, synth_float_t gain1, synth_float_t *pSrc2, synth_float_t gain2, UINT32 len)
{
if (gain1 == 0)
{
while(len--)
{
*(pSrcDst1++) = *(pSrc2++)*gain2;
}
return;
}
if ((gain1 == 1.0) && (gain2 == 1.0))
{
while(len--)
{
*(pSrcDst1++) += *(pSrc2++);
}
return;
}
while(len--)
{
*(pSrcDst1) = *(pSrcDst1)*gain1 + *(pSrc2++)*gain2;
pSrcDst1++;
}
}
void Add_VS(synth_float_t *pDst, synth_float_t *pSrc1, synth_float_t gain1, synth_float_t src2, UINT32 len)
{
while(len--)
{
*(pDst++) = *(pSrc1++)*gain1 + src2;
}
}
void Add_VV(synth_float_t *pDst, synth_float_t *pSrc1, synth_float_t gain1, synth_float_t *pSrc2, synth_float_t gain2, UINT32 len)
{
while(len--)
{
*(pDst++) = *(pSrc1++)*gain1 + *(pSrc2++)*gain2;
}
}
void Sub_inplace_VS(synth_float_t *pSrcDst1, synth_float_t gain1, synth_float_t src2, UINT32 len)
{
while(len--)
{
*(pSrcDst1) = *(pSrcDst1)*gain1 - src2;
pSrcDst1++;
}
}
void Sub_inplace_VV(synth_float_t *pSrcDst1, synth_float_t gain1, synth_float_t *pSrc2, synth_float_t gain2, UINT32 len)
{
while(len--)
{
*(pSrcDst1) = *(pSrcDst1)*gain1 - *(pSrc2++)*gain2;
pSrcDst1++;
}
}
void Sub_VS(synth_float_t *pDst, synth_float_t *pSrc1, synth_float_t gain1, synth_float_t src2, UINT32 len)
{
while(len--)
{
*(pDst++) = *(pSrc1++)*gain1 - src2;
}
}
void Sub_VV(synth_float_t *pDst, synth_float_t *pSrc1, synth_float_t gain1, synth_float_t *pSrc2, synth_float_t gain2, UINT32 len)
{
while(len--)
{
*(pDst++) = *(pSrc1++)*gain1 - *(pSrc2++)*gain2;
}
}
void Mul_inplace_VS(synth_float_t *pSrcDst, synth_float_t src, UINT32 len)
{
while(len--)
{
*(pSrcDst++) *= src;
}
}
void Mul_inplace_VV(synth_float_t *pSrcDst, synth_float_t *pSrc, UINT32 len)
{
while(len--)
{
*(pSrcDst++) *= *(pSrc++);
}
}
void Mul_VS(synth_float_t *pDst, synth_float_t *pSrc1, synth_float_t src2, UINT32 len)
{
while(len--)
{
*(pDst++) = *(pSrc1++) * src2;
}
}
void Mul_VV(synth_float_t *pDst, synth_float_t *pSrc1, synth_float_t *pSrc2, UINT32 len)
{
while(len--)
{
*(pDst++) = *(pSrc1++) * *(pSrc2++);
}
}
void Clamp_inplace_V(synth_float_t *pSrcDst, synth_float_t minimum, synth_float_t maximum, UINT32 len)
{
while(len--)
{
*(pSrcDst) = max(minimum, min(maximum, *(pSrcDst)));
pSrcDst++;
}
}
void Clamp_V(synth_float_t *pDst, synth_float_t *pSrc, synth_float_t minimum, synth_float_t maximum, UINT32 len)
{
while(len--)
{
*(pDst++) = max(minimum, min(maximum, *(pSrc++)));
}
}
void uMax_VS(synth_float_t *pDst, synth_float_t *pSrc1, synth_float_t src2, UINT32 len)
{
while(len--)
{
*(pDst++) = max(fabs(*(pSrc1++)), src2);
}
}
void uMax_VV(synth_float_t *pDst, synth_float_t *pSrc1, synth_float_t *pSrc2, UINT32 len)
{
while(len--)
{
*(pDst++) = max(fabs(*(pSrc1++)), *(pSrc2++));
}
}
void uMin_VS(synth_float_t *pDst, synth_float_t *pSrc1, synth_float_t src2, UINT32 len)
{
while(len--)
{
*(pDst++) = min(fabs(*(pSrc1++)), src2);
}
}
void uMin_VV(synth_float_t *pDst, synth_float_t *pSrc1, synth_float_t *pSrc2, UINT32 len)
{
while(len--)
{
*(pDst++) = min(fabs(*(pSrc1++)), *(pSrc2++));
}
}
+45
View File
@@ -0,0 +1,45 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#ifndef _VECTOR_UTILS_H_
#define _VECTOR_UTILS_H_
#include "synth_defs.h"
// --------------------------------------------------------------
// Types
// --------------------------------------------------------------
// --------------------------------------------------------------
#if defined(__cplusplus)
extern "C" {
#endif
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void Add_inplace_VS(synth_float_t *pSrcDst1, synth_float_t gain1, synth_float_t src2, UINT32 len);
void Add_inplace_VV(synth_float_t *pSrcDst1, synth_float_t gain1, synth_float_t *pSrc2, synth_float_t gain2, UINT32 len);
void Add_VS(synth_float_t *pDst, synth_float_t *pSrc1, synth_float_t gain1, synth_float_t src2, UINT32 len);
void Add_VV(synth_float_t *pDst, synth_float_t *pSrc1, synth_float_t gain1, synth_float_t *pSrc2, synth_float_t gain2, UINT32 len);
void Sub_inplace_VS(synth_float_t *pSrcDst1, synth_float_t gain1, synth_float_t src2, UINT32 len);
void Sub_inplace_VV(synth_float_t *pSrcDst1, synth_float_t gain1, synth_float_t *pSrc2, synth_float_t gain2, UINT32 len);
void Sub_VS(synth_float_t *pDst, synth_float_t *pSrc1, synth_float_t gain1, synth_float_t src2, UINT32 len);
void Sub_VV(synth_float_t *pDst, synth_float_t *pSrc1, synth_float_t gain1, synth_float_t *pSrc2, synth_float_t gain2, UINT32 len);
void Mul_inplace_VS(synth_float_t *pSrcDst, synth_float_t src, UINT32 len);
void Mul_inplace_VV(synth_float_t *pSrcDst, synth_float_t *pSrc, UINT32 len);
void Mul_VS(synth_float_t *pDst, synth_float_t *pSrc1, synth_float_t src2, UINT32 len);
void Mul_VV(synth_float_t *pDst, synth_float_t *pSrc1, synth_float_t *pSrc2, UINT32 len);
void Clamp_inplace_V(synth_float_t *pSrcDst, synth_float_t minimum, synth_float_t maximum, UINT32 len);
void Clamp_V(synth_float_t *pDst, synth_float_t *pSrc, synth_float_t minimum, synth_float_t maximum, UINT32 len);
void uMax_VS(synth_float_t *pDst, synth_float_t *pSrc1, synth_float_t src2, UINT32 len);
void uMax_VV(synth_float_t *pDst, synth_float_t *pSrc1, synth_float_t *pSrc2, UINT32 len);
void uMin_VS(synth_float_t *pDst, synth_float_t *pSrc1, synth_float_t src2, UINT32 len);
void uMin_VV(synth_float_t *pDst, synth_float_t *pSrc1, synth_float_t *pSrc2, UINT32 len);
#if defined(__cplusplus)
}
#endif
// --------------------------------------------------------------
#endif // _VECTOR_UTILS_H_
+1230
View File
File diff suppressed because it is too large Load Diff
+322
View File
@@ -0,0 +1,322 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#ifndef _VOICE_H_
#define _VOICE_H_
#include "synth_defs.h"
#include "env.h"
#include "vco.h"
#include "vcf.h"
#include "lfo.h"
#include "smooth.h"
#define VOICE_OSC_SPREAD_PHASE_AMT 0.01
// --------------------------------------------------------------
// Types
// --------------------------------------------------------------
enum
{
VOICE_PARAM_MASTER_TUNE = 0,
VOICE_PARAM_MASTER_FREF,
VOICE_PARAM_VOICE_PAN,
VOICE_PARAM_PORTAMENTO_TIME,
VOICE_PARAM_OSC_0_ENABLE,
VOICE_PARAM_OSC_1_ENABLE,
VOICE_PARAM_OSC_0_RESTART_ON_TRIGGER,
VOICE_PARAM_OSC_1_RESTART_ON_TRIGGER,
VOICE_PARAM_OSC_0_LEVEL,
VOICE_PARAM_OSC_1_LEVEL,
VOICE_PARAM_OSC_0_PHASE,
VOICE_PARAM_OSC_1_PHASE,
VOICE_PARAM_OSC_0_DUTYCYCLE,
VOICE_PARAM_OSC_1_DUTYCYCLE,
VOICE_PARAM_OSC_0_DETUNE,
VOICE_PARAM_OSC_1_DETUNE,
VOICE_PARAM_OSC_0_TRANSPOSE,
VOICE_PARAM_OSC_1_TRANSPOSE,
VOICE_PARAM_OSC_0_SCALE,
VOICE_PARAM_OSC_1_SCALE,
VOICE_PARAM_OSC_0_WAVEFORM,
VOICE_PARAM_OSC_1_WAVEFORM,
VOICE_PARAM_OSC_0_FM_AMT_0,
VOICE_PARAM_OSC_1_FM_AMT_0,
VOICE_PARAM_OSC_0_FM_AMT_1,
VOICE_PARAM_OSC_1_FM_AMT_1,
VOICE_PARAM_OSC_0_FM_SRC_0,
VOICE_PARAM_OSC_1_FM_SRC_0,
VOICE_PARAM_OSC_0_FM_SRC_1,
VOICE_PARAM_OSC_1_FM_SRC_1,
VOICE_PARAM_OSC_0_FM_SRC_OP,
VOICE_PARAM_OSC_1_FM_SRC_OP,
VOICE_PARAM_OSC_0_AM_AMT_0,
VOICE_PARAM_OSC_1_AM_AMT_0,
VOICE_PARAM_OSC_0_AM_AMT_1,
VOICE_PARAM_OSC_1_AM_AMT_1,
VOICE_PARAM_OSC_0_AM_SRC_0,
VOICE_PARAM_OSC_1_AM_SRC_0,
VOICE_PARAM_OSC_0_AM_SRC_1,
VOICE_PARAM_OSC_1_AM_SRC_1,
VOICE_PARAM_OSC_0_AM_SRC_OP,
VOICE_PARAM_OSC_1_AM_SRC_OP,
VOICE_PARAM_OSC_0_PWM_AMT_0,
VOICE_PARAM_OSC_1_PWM_AMT_0,
VOICE_PARAM_OSC_0_PWM_AMT_1,
VOICE_PARAM_OSC_1_PWM_AMT_1,
VOICE_PARAM_OSC_0_PWM_SRC_0,
VOICE_PARAM_OSC_1_PWM_SRC_0,
VOICE_PARAM_OSC_0_PWM_SRC_1,
VOICE_PARAM_OSC_1_PWM_SRC_1,
VOICE_PARAM_OSC_0_PWM_SRC_OP,
VOICE_PARAM_OSC_1_PWM_SRC_OP,
VOICE_PARAM_NOISE_ENABLE,
VOICE_PARAM_NOISE_LEVEL,
VOICE_PARAM_NOISE_SHAPE,
VOICE_PARAM_KEY,
VOICE_PARAM_VCA_ENV_GAIN,
VOICE_PARAM_VCA_AM_AMT_0,
VOICE_PARAM_VCA_AM_SRC_0,
VOICE_PARAM_VCA_PAN_AMT_0,
VOICE_PARAM_VCA_PAN_SRC_0,
VOICE_PARAM_ENV_0_A, VOICE_PARAM_VCF_ENV_A = VOICE_PARAM_ENV_0_A,
VOICE_PARAM_ENV_1_A, VOICE_PARAM_VCA_ENV_A = VOICE_PARAM_ENV_1_A,
VOICE_PARAM_ENV_2_A,
VOICE_PARAM_ENV_3_A,
VOICE_PARAM_ENV_0_S, VOICE_PARAM_VCF_ENV_S = VOICE_PARAM_ENV_0_S,
VOICE_PARAM_ENV_1_S, VOICE_PARAM_VCA_ENV_S = VOICE_PARAM_ENV_1_S,
VOICE_PARAM_ENV_2_S,
VOICE_PARAM_ENV_3_S,
VOICE_PARAM_ENV_0_D, VOICE_PARAM_VCF_ENV_D = VOICE_PARAM_ENV_0_D,
VOICE_PARAM_ENV_1_D, VOICE_PARAM_VCA_ENV_D = VOICE_PARAM_ENV_1_D,
VOICE_PARAM_ENV_2_D,
VOICE_PARAM_ENV_3_D,
VOICE_PARAM_ENV_0_R, VOICE_PARAM_VCF_ENV_R = VOICE_PARAM_ENV_0_R,
VOICE_PARAM_ENV_1_R, VOICE_PARAM_VCA_ENV_R = VOICE_PARAM_ENV_1_R,
VOICE_PARAM_ENV_2_R,
VOICE_PARAM_ENV_3_R,
VOICE_PARAM_VCF_TYPE,
VOICE_PARAM_VCF_ORDER,
VOICE_PARAM_VCF_F,
VOICE_PARAM_VCF_Q,
VOICE_PARAM_VCF_Q_GAIN_0,
VOICE_PARAM_VCF_Q_CTRL_0,
VOICE_PARAM_VCF_ENV_GAIN,
VOICE_PARAM_VCF_F_AMT_0,
VOICE_PARAM_VCF_F_AMT_1,
VOICE_PARAM_VCF_F_SRC_0,
VOICE_PARAM_VCF_F_SRC_1,
VOICE_PARAM_VCF_F_SRC_OP,
VOICE_PARAM_VCF_Q_AMT_0,
VOICE_PARAM_VCF_Q_AMT_1,
VOICE_PARAM_VCF_Q_SRC_0,
VOICE_PARAM_VCF_Q_SRC_1,
VOICE_PARAM_VCF_Q_SRC_OP,
VOICE_PARAM_LFO_0_SPEED,
VOICE_PARAM_LFO_1_SPEED,
VOICE_PARAM_LFO_2_SPEED,
VOICE_PARAM_LFO_3_SPEED,
VOICE_PARAM_LFO_0_SMOOTH,
VOICE_PARAM_LFO_1_SMOOTH,
VOICE_PARAM_LFO_2_SMOOTH,
VOICE_PARAM_LFO_3_SMOOTH,
VOICE_PARAM_LFO_0_DELAY,
VOICE_PARAM_LFO_1_DELAY,
VOICE_PARAM_LFO_2_DELAY,
VOICE_PARAM_LFO_3_DELAY,
VOICE_PARAM_LFO_0_ATTACK,
VOICE_PARAM_LFO_1_ATTACK,
VOICE_PARAM_LFO_2_ATTACK,
VOICE_PARAM_LFO_3_ATTACK,
VOICE_PARAM_LFO_0_SHAPE,
VOICE_PARAM_LFO_1_SHAPE,
VOICE_PARAM_LFO_2_SHAPE,
VOICE_PARAM_LFO_3_SHAPE,
VOICE_PARAM_LFO_0_MODE,
VOICE_PARAM_LFO_1_MODE,
VOICE_PARAM_LFO_2_MODE,
VOICE_PARAM_LFO_3_MODE,
VOICE_PARAM_LFO_0_SYNC,
VOICE_PARAM_LFO_1_SYNC,
VOICE_PARAM_LFO_2_SYNC,
VOICE_PARAM_LFO_3_SYNC,
VOICE_PARAM_LFO_0_SYMMETRY,
VOICE_PARAM_LFO_1_SYMMETRY,
VOICE_PARAM_LFO_2_SYMMETRY,
VOICE_PARAM_LFO_3_SYMMETRY,
VOICE_NUM_PARAMS
};
enum
{
VOICE_ENV_ENV_0 = 0,
VOICE_ENV_VCF = VOICE_ENV_ENV_0,
VOICE_ENV_ENV_1,
VOICE_ENV_VCA = VOICE_ENV_ENV_1,
VOICE_ENV_2,
VOICE_ENV_3,
};
enum
{
VOICE_MOD_SRC_ZEROS = 0,
VOICE_MOD_SRC_LFO_0,
VOICE_MOD_SRC_LFO_1,
VOICE_MOD_SRC_LFO_2,
VOICE_MOD_SRC_LFO_3,
VOICE_MOD_SRC_ENV_0,
VOICE_MOD_SRC_ENV_1,
VOICE_MOD_SRC_ENV_2,
VOICE_MOD_SRC_ENV_3,
VOICE_MOD_SRC_VCO_0,
VOICE_MOD_SRC_VCO_1,
VOICE_NUM_MOD_SOURCES
};
enum
{
VOICE_MOD_SRC_0_DISABLED = 0,
VOICE_MOD_SRC_0_LFO_0,
VOICE_MOD_SRC_0_LFO_1,
VOICE_MOD_SRC_0_LFO_2,
VOICE_MOD_SRC_0_LFO_3,
VOICE_MOD_SRC_0_ENV_0,
VOICE_MOD_SRC_0_ENV_1,
VOICE_MOD_SRC_0_ENV_2,
VOICE_MOD_SRC_0_ENV_3,
VOICE_MOD_SRC_0_VCO_0,
VOICE_NUM_MOD_SOURCES_0
};
enum
{
VOICE_MOD_SRC_1_DISABLED = 0,
VOICE_MOD_SRC_1_LFO_0,
VOICE_MOD_SRC_1_LFO_1,
VOICE_MOD_SRC_1_LFO_2,
VOICE_MOD_SRC_1_LFO_3,
VOICE_MOD_SRC_1_ENV_0,
VOICE_MOD_SRC_1_ENV_1,
VOICE_MOD_SRC_1_ENV_2,
VOICE_MOD_SRC_1_ENV_3,
VOICE_NUM_MOD_SOURCES_1
};
enum
{
VOICE_MOD_SRC_OP_ADD = 0,
VOICE_MOD_SRC_OP_MUL,
VOICE_NUM_MOD_OPS
};
enum
{
VOICE_LFO_MODE_GLOBAL,
VOICE_LFO_MODE_INDIVIDUAL,
VOICE_LFO_NUM_MODES
};
enum
{
VOICE_LFO_SYNC_FREE,
VOICE_LFO_SYNC_RESTART,
VOICE_LFO_NUM_SYNCS
};
enum
{
VOICE_NOISE_SHAPE_WHITE,
VOICE_NOISE_SHAPE_PINK,
VOICE_NOISE_NUM_SHAPES
};
enum
{
note_state_idle = 0,
note_state_triggered,
note_state_released
};
enum
{
voice_event_shutdown = 0,
voice_event_trigger,
voice_event_retrigger,
voice_event_release
};
typedef struct _svoice_common_t
{
synth_float_t freqTab[NUM_FREQS];
// Global LFO
lfo_t glfo[VOICE_NUM_LFO];
// Global Envelopes
envgen_t genv[VOICE_NUM_ENV];
// Global VCF
vcf_t gvcf[2];
// Global Noise generator
noise_gen_t gnoise;
synth_float_t pBuf_zeros[SYNTH_MAX_BUFSIZE];
synth_float_t pBuf_ones[SYNTH_MAX_BUFSIZE];
synth_float_t *pBuf_LFO_gbl[VOICE_NUM_LFO];
synth_float_t *pBuf_ENV_gbl[VOICE_NUM_ENV];
synth_float_t *pBuf_VCF_gbl_in;
synth_float_t *pBuf_VCF_gbl_out;
synth_float_t noise_out[SYNTH_MAX_BUFSIZE];
vco_common_t vco;
vcf_common_t vcf;
} voice_common_t;
typedef struct _svoice_t
{
voice_common_t *pCom;
UINT32 id;
UINT32 state;
UINT32 bufsize;
envgen_t env[VOICE_NUM_ENV];
synth_float_t fs;
osc_t vco[VOICE_NUM_OSC];
lfo_t lfo[VOICE_NUM_LFO];
vcf_t vcf;
synth_float_t param[VOICE_NUM_PARAMS];
synth_float_t *pBuf_Q;
smooth_t smooth_vco_enable[VOICE_NUM_OSC];
smooth_t smooth_vco_portamento[VOICE_NUM_OSC];
synth_float_t vco_pitch[VOICE_NUM_OSC];
// smooth_t *pParam_smoother[VOICE_NUM_PARAMS];
// synth_float_t param_smoothed[VOICE_NUM_PARAMS][SYNTH_MAX_BUFSIZE];
} voice_t;
// --------------------------------------------------------------
#if defined(__cplusplus)
extern "C" {
#endif
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void Voice_ModInit(voice_common_t *pCom);
void Voice_ModFree(voice_common_t *pCom);
void VoiceInit(voice_t *pObj, voice_common_t *pCom, UINT32 id, synth_float_t fs);
void VoiceFree(voice_t *pObj);
void VoiceSetFS(voice_t *pObj, synth_float_t fs);
void VoiceSetBufsize(voice_t *pObj, UINT32 size);
void VoiceEvent(voice_t *pObj, UINT32 type);
void VoiceParam2Set(voice_t *pObj, UINT32 type, synth_float_t value);
synth_float_t VoiceParamGet(voice_t *pObj, UINT32 type);
UINT32 VoiceStateGet(voice_t *pObj);
void VoiceProcessDataV(voice_t *pObj, float *pOut1, float *pOut2, UINT32 len);
void VoiceProcessDataV_Common(voice_t *pObj, float *pOut1, float *pOut2, UINT32 len);
#if defined(__cplusplus)
}
#endif
// --------------------------------------------------------------
#endif // _VOICE_H_
+358
View File
@@ -0,0 +1,358 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include "synth_defs.h"
#include "blit.h"
#include "vco.h"
#include "vector_utils.h"
#include "wavetable.h"
const wt_descr_t _g_wt_descr[WT_NUM_WAVETABLES] =
{
{8, 0, 101, 8, 69, 16, 70, 24, 71, 32, 72, 40, 73, 48, 74, 60, 75},
{8, 0, 77, 8, 78, 16, 79, 24, 80, 32, 81, 40, 82, 48, 83, 60, 84},
{6, 0, 101, 30, 47, 38, 131, 46, 132, 54, 141, 60, 142},
{7, 0, 101, 8, 94, 16, 95, 24, 96, 32, 97, 40, 98, 60, 100},
{3, 0, 2, 24, 1, 60, 1},
{6, 0, 131, 8, 132, 16, 141, 24, 142, 32, 143, 60, 144},
{9, 0, 101, 8, 54, 16, 55, 24, 56, 32, 57, 40, 88, 48, 89, 54, 53, 60, 104},
{4, 0, 114, 20, 115, 40, 116, 60, 99},
{4, 0, 108, 24, 65, 40, 63, 60, 90},
{7, 0, 101, 8, 61, 16, 62, 24, 63, 32, 66, 40, 67, 60, 68},
{5, 0, 42, 14, 43, 30, 44, 46, 45, 60, 46},
{5, 0, 41, 16, 40, 32, 39, 48, 38, 60, 37},
{8, 0, 101, 8, 54, 16, 55, 24, 56, 32, 57, 40, 58, 48, 59, 60, 60},
{8, 0, 241, 8, 242, 16, 243, 24, 244, 32, 245, 40, 241, 48, 242, 60, 243},
{6, 0, 101, 12, 5, 24, 6, 36, 85, 48, 8, 60, 48},
{4, 0, 12, 20, 11, 50, 53, 60, 104},
{31, 0, 146, 2, 147, 4, 148, 6, 149, 8, 150, 10, 151, 12, 152, 14, 153, 16, 154, 18, 155, 20, 156, 22, 157, 24, 158, 26, 159, 28, 160, 30, 161, 32, 162, 34, 163, 36, 164, 38, 165, 40, 166, 42, 167, 44, 168, 46, 169, 48, 170, 50, 171, 52, 172, 54, 173, 56, 174, 58, 175, 60, 176},
{6, 0, 106, 8, 109, 14, 113, 22, 90, 28, 13, 60, 113},
{9, 0, 85, 8, 85, 16, 86, 24, 91, 32, 62, 40, 71, 48, 86, 56, 85, 60, 85},
{5, 0, 117, 28, 117, 40, 116, 52, 119, 60, 119},
{26, 0, 101, 3, 101, 4, 80, 7, 80, 8, 69, 11, 69, 12, 81, 15, 81, 16, 70, 19, 70, 20, 82, 23, 82, 24, 71, 27, 71, 28, 83, 31, 83, 32, 72, 35, 72, 36, 84, 39, 84, 40, 73, 43, 73, 44, 85, 47, 85, 48, 74, 60, 74},
{12, 0, 32, 12, 30, 17, 29, 22, 28, 27, 27, 32, 26, 37, 25, 42, 24, 46, 23, 50, 22, 54, 21, 60, 21},
{8, 0, 32, 14, 33, 15, 32, 29, 34, 30, 32, 43, 35, 44, 32, 60, 36},
{7, 0, 136, 8, 136, 20, 137, 32, 138, 44, 139, 56, 140, 60, 140},
{7, 0, 106, 10, 107, 20, 108, 30, 109, 40, 110, 50, 111, 60, 112},
{8, 0, 101, 16, 112, 17, 101, 32, 113, 33, 101, 48, 112, 49, 101, 60, 91},
{31, 0, 178, 2, 179, 4, 180, 6, 181, 8, 182, 10, 183, 12, 184, 14, 185, 16, 186, 18, 187, 20, 188, 22, 189, 24, 190, 26, 191, 28, 192, 30, 193, 32, 194, 34, 195, 36, 196, 38, 197, 40, 198, 42, 199, 44, 200, 46, 201, 48, 202, 50, 203, 52, 204, 54, 205, 56, 206, 58, 207, 60, 208},
{31, 0, 211, 2, 212, 4, 213, 6, 214, 8, 215, 10, 216, 12, 217, 14, 218, 16, 219, 18, 220, 20, 221, 22, 222, 24, 223, 26, 224, 28, 225, 30, 226, 32, 227, 34, 228, 36, 229, 38, 230, 40, 231, 42, 232, 44, 233, 46, 234, 48, 235, 50, 236, 52, 237, 54, 238, 56, 239, 58, 240, 60, 241},
{17, 0, 8, 4, 9, 8, 10, 12, 11, 16, 12, 20, 13, 24, 14, 28, 15, 32, 16, 36, 17, 40, 18, 44, 19, 48, 20, 52, 21, 56, 22, 60, 23, 63, 22},
{16, 0, 3, 4, 24, 8, 19, 12, 219, 16, 382, 20, 376, 24, 370, 28, 143, 32, 377, 36, 15, 40, 20, 44, 241, 48, 243, 52, 93, 56, 121, 60, 126},
{16, 0, 239, 4, 240, 8, 241, 12, 242, 16, 243, 20, 244, 24, 245, 28, 368, 32, 391, 36, 388, 40, 392, 44, 386, 48, 384, 52, 382, 56, 133, 60, 375},
{16, 0, 382, 4, 30, 8, 31, 12, 32, 16, 33, 20, 34, 24, 35, 28, 36, 32, 240, 36, 241, 40, 242, 44, 243, 48, 244, 52, 245, 56, 140, 60, 369},
{12, 0, 3, 5, 4, 11, 7, 16, 9, 22, 10, 27, 14, 33, 15, 38, 16, 44, 17, 49, 18, 53, 19, 60, 20},
{12, 0, 31, 1, 49, 2, 50, 3, 51, 4, 52, 7, 64, 13, 76, 18, 87, 23, 92, 37, 93, 47, 102, 60, 103},
{20, 0, 105, 2, 118, 5, 120, 8, 121, 10, 122, 12, 123, 16, 124, 19, 125, 23, 126, 26, 127, 30, 128, 32, 129, 35, 130, 39, 133, 42, 134, 45, 135, 49, 145, 54, 177, 58, 209, 60, 210},
{16, 0, 368, 4, 369, 8, 370, 12, 371, 16, 372, 20, 373, 24, 374, 28, 375, 32, 376, 36, 377, 40, 378, 44, 379, 48, 380, 52, 381, 56, 382, 60, 383},
{5, 0, 384, 15, 385, 30, 386, 45, 387, 60, 388},
{6, 0, 389, 12, 390, 24, 391, 36, 392, 48, 393, 60, 394},
{5, 0, 395, 10, 396, 26, 397, 43, 398, 60, 399},
{22, 0, 400, 1, 401, 4, 402, 8, 403, 11, 404, 13, 405, 17, 406, 19, 407, 22, 408, 25, 409, 29, 410, 30, 411, 34, 412, 36, 413, 39, 414, 43, 415, 48, 416, 52, 417, 53, 418, 54, 419, 59, 420, 60, 421}
};
void WT_ModInit(wt_common_t *pCom)
{
UINT32 i, j, k, offset, last_pos, distance;
INT16 sample, wave[WT_WAVE_SIZE];
wt_descr_t *pDesc;
synth_float_t kmix;
synth_float_t x, dx, wave_tri[WT_WAVE_SIZE], wave_sqr[WT_WAVE_SIZE], wave_saw[WT_WAVE_SIZE];
// Create waves from 16-bit raw data
offset = 0;
for (i=0; i < 300; i++)
{
if (i > 245)
offset = 122;
for (j=0; j < 64; j++)
{
sample = ((INT16)pCom->wave_rawdata[128*i + 2*j + 0] << 8) + pCom->wave_rawdata[128*i + 2*j + 1];
wave[j] = sample;
}
// Possible assembly 1
wave[64] = 0;
for (j=0; j < 63; j++)
{
wave[65+j] = -wave[63-j];
}
// Possible assembly 2
// for (j=0; j < 64; j++)
// {
// wave[64+j] = -wave[63-j];
// }
for (j=0; j < WT_WAVE_SIZE; j++)
{
pCom->waves[offset+i][j] = (synth_float_t)wave[j]/8192;
}
#if 0
//#ifdef SYNTH_DEBUG
{
FILE *pFile = NULL;
char filename[128] = {0};
sprintf(filename, "C:\\Users\\jens\\JaySynth\\wave_%03d.pcm", offset+i);
pFile = fopen(filename, "wb");
if (pFile)
{
fwrite(wave, 2, WT_WAVE_SIZE, pFile);
fclose(pFile);
}
}
#endif
}
// Create classic waveforms
// Saw
x = 1;
dx = 2./WT_WAVE_SIZE;
for (i=0; i < WT_WAVE_SIZE; i++)
{
wave_saw[i] = x;
x -= dx;
}
// Sqr
x = 1;
for (i=0; i < WT_WAVE_SIZE/2; i++)
{
wave_sqr[i] = x;
}
for (i=i; i < WT_WAVE_SIZE; i++)
{
wave_sqr[i] = -x;
}
// Tri
x = 0;
dx = 4./WT_WAVE_SIZE;
for (i=0; i < WT_WAVE_SIZE/4; i++)
{
wave_tri[i] = x;
x += dx;
}
for (i=i; i < WT_WAVE_SIZE/2; i++)
{
wave_tri[i] = x;
x -= dx;
}
for (i=i; i < 3*WT_WAVE_SIZE/4; i++)
{
wave_tri[i] = x;
x -= dx;
}
for (i=i; i < WT_WAVE_SIZE; i++)
{
wave_tri[i] = x;
x += dx;
}
// Create wavetables from waves
// Allocate memory
for (i=0; i < WT_NUM_WAVETABLES; i++)
{
pCom->ppWavetables[i] = (synth_float_t**)malloc(WT_WAVETABLE_SIZE*sizeof(synth_float_t*));
for (j=0; j < WT_WAVETABLE_SIZE; j++)
{
pCom->ppWavetables[i][j] = (synth_float_t*)malloc(WT_WAVE_SIZE*sizeof(synth_float_t));
}
}
for (i=0; i < WT_NUM_WAVETABLES; i++)
{
pDesc = &_g_wt_descr[i];
// Create first wavetable entry
j = 0;
for (j=0; j < pDesc->num_entries; j++)
{
memcpy(pCom->ppWavetables[i][pDesc->pEntry[j].pos], pCom->waves[pDesc->pEntry[j].wave_id], WT_WAVE_SIZE*sizeof(synth_float_t));
last_pos = pDesc->pEntry[j].pos;
if ((j+1) == pDesc->num_entries)
continue;
distance = pDesc->pEntry[j+1].pos - last_pos;
for (k=1; k < distance; k++)
{
kmix = 1 - (synth_float_t)k/distance;
Add_VV(pCom->ppWavetables[i][last_pos+k], pCom->ppWavetables[i][last_pos], kmix, pCom->waves[pDesc->pEntry[j+1].wave_id], 1-kmix, WT_WAVE_SIZE);
}
}
memcpy(pCom->ppWavetables[i][61], wave_tri, WT_WAVE_SIZE*sizeof(synth_float_t));
memcpy(pCom->ppWavetables[i][62], wave_sqr, WT_WAVE_SIZE*sizeof(synth_float_t));
memcpy(pCom->ppWavetables[i][63], wave_saw, WT_WAVE_SIZE*sizeof(synth_float_t));
}
}
void WT_ModFree(wt_common_t *pCom)
{
int i, j;
for (i=0; i < WT_NUM_WAVETABLES; i++)
{
for (j=0; j < WT_WAVETABLE_SIZE; j++)
{
free(pCom->ppWavetables[i][j]);
}
free(pCom->ppWavetables[i]);
}
}
void WT_Init(wt_t *pObj, UINT32 id, wt_common_t *pCom, synth_float_t fs)
{
pObj->pCom = pCom;
pObj->id = id;
pObj->fs = fs;
pObj->fm = 1;
if (pObj->id == 0)
{
WT_ModInit(pCom);
}
WT_Prepare(pObj);
}
void WT_Free(wt_t *pObj)
{
if (pObj->id == 0)
{
WT_ModFree(pObj->pCom);
}
}
void WT_SetFS(wt_t *pObj, synth_float_t fs)
{
pObj->fs = fs;
pObj->startup = 1;
}
void WT_Reset(wt_t *pObj, synth_float_t phase)
{
pObj->x = fmod(phase, 1);
pObj->startup = 1;
}
void WT_Prepare(wt_t *pObj)
{
WT_Reset(pObj, (synth_float_t)rand()/RAND_MAX);
}
void WT_Param2Set(wt_t *pObj, UINT32 type, synth_float_t value)
{
switch(type)
{
case WT_PARAM2_WAVEFORM:
if (pObj->param[type] == (UINT32)value)
break;
pObj->param[type] = (UINT32)value;
pObj->startup = 1;
break;
case WT_PARAM2_WAVETABLE_ID:
if (pObj->param[type] == (UINT32)value)
break;
pObj->param[type] = value;
pObj->startup = 1;
break;
case WT_PARAM2_WAVETABLE_ENTRY:
pObj->param[type] = value;
break;
default:
break;
}
}
void WT_Start(wt_t *pObj)
{
pObj->startup = 1;
}
void WT_ProcessDataV(wt_t *pObj, synth_float_t *pPitch, synth_float_t *pCV_fm, synth_float_t *pCV_pwm, synth_float_t *pOut, UINT32 len)
{
UINT32 i, ni, wt_table, ni_next;
synth_float_t out, dx, nn, nf, kmix, w1, w2;
if (pObj->param[WT_PARAM2_WAVEFORM] == WT_WAVEFORM_REGULAR)
{
wt_table = (UINT32)pObj->param[WT_PARAM2_WAVETABLE_ID];
for (i=0; i< len; i++)
{
if (pObj->x >= 1 || pObj->startup)
{
pObj->x -= 1;
if (pObj->startup)
pObj->x = 0;
pObj->wt_index = (WT_WAVETABLE_SIZE-1)*max(0, min(1, pObj->param[WT_PARAM2_WAVETABLE_ENTRY] + pCV_pwm[i]));
pObj->wt_start = (UINT32)pObj->wt_index;
if (pCV_fm)
{
pObj->fm = (synth_float_t)pow((synth_float_t)2, pCV_fm[i]);
}
pObj->startup = 0;
}
ni = (UINT32)(pObj->x*(WT_WAVE_SIZE));
w1 = pObj->pCom->ppWavetables[wt_table][pObj->wt_start][ni];
w2 = pObj->pCom->ppWavetables[wt_table][min((WT_WAVETABLE_SIZE-1), pObj->wt_start+1)][ni];
kmix = pObj->wt_index - (UINT32)pObj->wt_index;
out = w1*(1-kmix) + w2*kmix;
dx = pObj->fm*pPitch[i]/pObj->fs;
pObj->x += dx;
*(pOut++) = out;
}
}
if (pObj->param[WT_PARAM2_WAVEFORM] == WT_WAVEFORM_INTERPOLATED)
{
wt_table = (UINT32)pObj->param[WT_PARAM2_WAVETABLE_ID];
for (i=0; i< len; i++)
{
if (pObj->x >= 1 || pObj->startup)
{
pObj->x -= 1;
if (pObj->startup)
pObj->x = 0;
pObj->wt_index = (WT_WAVETABLE_SIZE-1)*max(0, min(1, pObj->param[WT_PARAM2_WAVETABLE_ENTRY] + pCV_pwm[i]));
pObj->wt_start = (UINT32)pObj->wt_index;
if (pCV_fm)
{
pObj->fm = (synth_float_t)pow((synth_float_t)2, pCV_fm[i]);
}
pObj->startup = 0;
}
nn = pObj->x*(WT_WAVE_SIZE);
ni = (UINT32)nn;
nf = nn - ni;
ni_next = (ni + 1)&(WT_WAVE_SIZE-1);
w1 = (pObj->pCom->ppWavetables[wt_table][pObj->wt_start][ni_next] - pObj->pCom->ppWavetables[wt_table][pObj->wt_start][ni])*nf + pObj->pCom->ppWavetables[wt_table][pObj->wt_start][ni];
w2 = (pObj->pCom->ppWavetables[wt_table][min((WT_WAVETABLE_SIZE-1), pObj->wt_start+1)][ni_next] - pObj->pCom->ppWavetables[wt_table][min((WT_WAVETABLE_SIZE-1), pObj->wt_start+1)][ni])*nf + pObj->pCom->ppWavetables[wt_table][min((WT_WAVETABLE_SIZE-1), pObj->wt_start+1)][ni];
kmix = pObj->wt_index - (UINT32)pObj->wt_index;
out = w1*(1-kmix) + w2*kmix;
dx = pObj->fm*pPitch[i]/pObj->fs;
pObj->x += dx;
*(pOut++) = out;
}
}
}
+89
View File
@@ -0,0 +1,89 @@
// --------------------------------------------------------------
// --------------------------------------------------------------
#ifndef _WAVETABLE_H_
#define _WAVETABLE_H_
#include "synth_types.h"
#define WT_NUM_WAVES 422
#define WT_WAVE_SIZE 128
#define WT_NUM_WAVETABLES 40
#define WT_WAVETABLE_SIZE 64
// --------------------------------------------------------------
// Types
// --------------------------------------------------------------
enum
{
WT_WAVEFORM_REGULAR,
WT_WAVEFORM_INTERPOLATED,
WT_NUM_WAVEFORMS
};
enum
{
WT_PARAM2_WAVEFORM,
WT_PARAM2_WAVETABLE_ID,
WT_PARAM2_WAVETABLE_ENTRY,
WT_NUM_PARAMS
};
typedef struct _swt_descr_entry_t
{
UINT32 pos, wave_id;
} wt_descr_entry_t;
typedef struct _swt_descr_t
{
UINT32 num_entries;
wt_descr_entry_t pEntry[WT_WAVETABLE_SIZE];
} wt_descr_t;
typedef struct _swt_common_t
{
unsigned char wave_rawdata[38400];
synth_float_t waves[WT_NUM_WAVES][WT_WAVE_SIZE];
synth_float_t **ppWavetables[WT_NUM_WAVETABLES]; //[WT_WAVETABLE_SIZE][WT_WAVE_SIZE];
} wt_common_t;
typedef struct _swt_t
{
UINT32 id;
wt_common_t *pCom;
synth_float_t fm, x, dx, wt_index;
UINT32 startup, wt_start;
synth_float_t param[WT_NUM_PARAMS];
synth_float_t fs;
} wt_t;
// --------------------------------------------------------------
#if defined(__cplusplus)
extern "C" {
#endif
// --------------------------------------------------------------
// Exported functions
// --------------------------------------------------------------
void WT_ModInit(wt_common_t *pCom);
void WT_ModFree(wt_common_t *pCom);
void WT_Init(wt_t *pObj, UINT32 id, wt_common_t *pCom, synth_float_t fs);
void WT_Free(wt_t *pObj);
void WT_SetFS(wt_t *pObj, synth_float_t fs);
void WT_Reset(wt_t *pObj, synth_float_t phase);
void WT_Param2Set(wt_t *pObj, UINT32 type, synth_float_t value);
void WT_Prepare(wt_t *pObj);
void WT_Start(wt_t *pObj);
void WT_ProcessDataV(wt_t *pObj, synth_float_t *pPitch, synth_float_t *pCV_fm, synth_float_t *pCV_pwm, synth_float_t *pOut, UINT32 len);
#if defined(__cplusplus)
}
#endif
// --------------------------------------------------------------
#endif // _WAVETABLE_H_
+267
View File
@@ -0,0 +1,267 @@
----------------------------------------------------
Changes:
----------------------------------------------------
V 0.5.6, 01.07.2013
- Resonance = 1.0 is normal
- No reset of resonance to 1.0 after change of filter type
- Bugfix: Midi-Controller changes were only applied to synthesizer if GUI is open
- Bugfix Texteingabe war fehlerhaft
- removed highest note priority voice allocation for monophonic mode.
Now each new note plays and retriggers envelope
- added Retrigger for monophonic mode
- Polyphony von GUI aus einstellbar. Maximum ist 256 voices
- VCO-Humanize funktion verbessert. Bessere Streuung der Voice-Verstimmungen.
- Mastertune ist jetzt relativ in Semitones statt absolute in Hertz.
Ältere Patches werden beim Laden korrekt auf Semitones umgerechnet.
----------------------------------------------------
V 0.5.5, 23.01.2013
- Added tooltip with version, date and name of developer.
----------------------------------------------------
V 0.5.4, 01.01.2013
- Bugfix: Rückkopplung beseitigt in Cubase.
- Bugfix: Symmetry bei einigen LFO-Wellenformen ohne Effekt
- Multicore-Audiorendering implementiert.
Die Last wird auf alle verfügbaren CPU-Kerne aufgeteilt => mehr Performance.
- Comboboxen (Waveforms, Mod-Sources, Filtertypes, etc.) unterstützen keine MidiControllerzuweisen mehr.
----------------------------------------------------
V 0.5.3, 08.10.2012
- LFO:
- Symmetry-Regler hinzugefügt.
- ComboBoxen für Sync und Mode durch ToggleButtons ersetzt.
- VCO:
- Phasen der Oszillatoren werden bei Programmstart mit Zufallswerten initialisiert.
----------------------------------------------------
V 0.5.2, 07.10.2012
- BLEP-Synthese:
- Anzahl der Harmonischen von 1800 auf 900 verringert => weniger Speicherverbrauch.
- LUT-Größe von 4096 auf 3072 verringert => weniger Speicherverbrauch.
- VCO:
- AM, FM und PWM sind jetzt durch zwei Quellen modulierbar
- Neuer Mode: Freerunning oder Restart der VCOs bei note-Trigger:
Bei Restart wird die VCO-Phase auf 0 gesetzt => Punchy-Sound - der Sound der vorherigen JaySynth-Versionen.
Bei free-Running bleibt VCO-Phase auf letzten Wert => Sound entspricht eher dem analogen Vorbild.
- Waldorf MicroWave Wellenformen und WaveTables hinzugefügt. WaveTable-Scan über PWM.
Original MicroWave Wellenformen müssen als Datei ("waves.bin", 16bit, Big-Endian) im Plugin-Verzeichnis vorliegen, damit Feature freigeschaltet wird.
- Impuls-Wellenform hinzugefügt. Erzeugt einen einzigen Impuls bei Tastenanschlag. Geeignet um VCF mit Selbstozillation anzuregen.
- 3-Fach Oversampling für Sinus-Wellenform eingeführt für bessere FM-Modulation
- VCF:
- Hilfe von LookUp-Table für schnellere Koeffizientenberechnung => mehr Performance
- Cutoff ist jetzt durch zwei Quellen modulierbar
- Velocity-Sense und Key-Follow Slider entfernt
- Resonance-Maximum auf 100 erhöht => Vorsicht!
- Resonance ist jetzt durch zwei Quellen modulierbar => hier auch Vorsicht!
- VCA:
- Velocity-Sense und Key-Follow Slider entfernt
- LFO:
- Delay und Attack hinzugefügt
- Neue Wellenformen hinzugefügt:
- Dreieck (Tri)
- Rechteck (Square)
- Zeitlich umgekehrter Sinus (1-Sine)
- Zeitlich umgekehrter Cosinus (1-Cosine)
- Zeitlich umgekehrter Saw (1-Saw)
- Zeitlich umgekehrter Rechteck (1-Square)
- Zeitlich umgekehrter Dreieck (1-Tri)
- Voice-Management:
- Max. Polyphonie auf 128 Stimmen erhöht
- Monophon-mode hinzugefügt
- Unisono-Mode:
- Jetzt auch polyphon spielbar => Nutzung der brachliegenden Stimmenressourcen, noch dichterer Sound.
- Grobe Lautstärkeanpassung, abhängig von Anzahl der Unisono-Stimmen.
- Envelopes:
- Stimmenklau verursacht weniger Knackser.
- ENV-3 und ENV-4 hinzugefügt
- Velocity-Sense und Key-Follow für die meisten Slider hinzugefügt.
- Menü ereichbar durch Rechts-Klick auf Slider. Achtung: Menü für Midi-Controller ist jetzt durch Shift-Rechts-Klick auf Slider erreichbar.
- Master-Volume hat jetzt logarithmische Kennlinie.
- Limiter im Audiosignalweg vermeidet Lautsprecherschaden
- GUI:
- Alle Bedienelemente verkleinert
- Build: Verwendung von SSE2-Befehlen => mehr Performance
- Bugfix: Bank Load/Save: Speicher wurde nicht wieder freigegeben.
----------------------------------------------------
V 0.5.1, 22.08.2012
- Master Tune in VCA Sektion hinzugefügt. Tune erfolgt relativ zu 440Hz
- VCO: Detune ist jetzt in cents. Achtung: Die VCOs gespeicherter Patches klingen jetzt weniger verstimmt.
Workaround: Detune nach Bedarf anpassen und Patch abspeichern.
- Pitchbender: Die Eingabefelder 'Min' und 'Max' sind jetzt beim 'Transpose'-Regler angeordnet.
- Per-Voice individual Stereo-Panning: Alternierend gerade, ungerade Stimme.
Einstellbar 0 bis 100% mit 'Voice-Pan ' in VCA Sektion
- Humanize-Funktion: Nachbildung nicht-idealer Bauteile eines analogen Hardware-Synthesizers.
Die Stimmenmodule eines analogen Hardware-Synthesizers klingen aufgrund von Bauteiltoleranzen nicht identisch.
Im JaySynth werden pro Stimme folgende Parameter in ihrem Werte Bereich normalverteilt gestreut:
- Mastertune: Spread 0 bis 10%. Einstellbar mit 'VCO hum.'
- VCF-Cutoff: Spread 0 bis 100%. Einstellbar mit 'VCF hum.'
- VCF-Resonance: Spread 0 bis 100%. Einstellbar mit 'VCF hum.'
- VCF-Envelope A,D,R: Spread 0 bis 100%. Einstellbar mit 'Env. hum.'
- VCA-Envelope A,D,R: Spread 0 bis 100%. Einstellbar mit 'Env. hum.'
- Stimmenzuordnungs-Algorithmus auf Round-Robin-Verfahren umgestellt: Jede Stimme wird nacheinander verwendet.
- Unisonomodus mit Portamento und Verwendung aller Stimmen (einstellbar)
- Filterorder 2 und 4
- Ob aktuelle Midi-Controllerstellungen beim Umschalten des Patch auf die Controllerziele des nächsten Patchs angewendet
wird, ist nun im MidiPopup einstellbar.
- Bugfix: Änderung des Patchnamens im Host führt nicht zum Update auf dem Plugin-Bildschirm
- VCOs: FM-Mod: VCA-Envelope und VCF-Envelope als Quellen hinzugefügt. Bei VCO-2 kann auch noch VCO-1 angegeben werden.
- Werteanzeige der Parameter zeigen jetzt die korrekte Anzahl an Nachkommastellen
- Bugfix: Wird GUI geschlossen und wieder geöffnet wird editiertes Patch mit Programmspeicher überschrieben.
- VCO: Pitchbenderbereich auf +/- 48 Halbtöne erhöht
- VCO: Transposebereich auf +/- 48 Halbtöne erhöht
- VCO: FM-amount: Einheit geändert von Oktaven auf Halbtöne (+/- 48 Halbtöne)
----------------------------------------------------
V 0.4.4, 14.08.2012
- Bugfix: Bei unsymmetrischen Pitchbenderbereichen wurde in Neutralstellung die Tonhöhe falsch eingestellt.
----------------------------------------------------
V 0.4.3, 13.08.2012
- Pitchbenderbereich pro VCO jetzt von der Oberfläche einstellbar.
Einfachklick auf Textfeld links und rechts neben 'FM-Amount'.
----------------------------------------------------
V 0.4.2, 12.08.2012
- Bugfix: Rangeingabe im MidiPopup: Bei range Min = max => crash
- Bugfix: LFO-shape SH-1 ließ sich nicht anwählen
- MidiPopup window: changed text 'Enable' to 'Assigned'
- MidiPopup window: changed text 'Move slider' to 'Absolute'
Absolute-mode bewegt zwar die Regler, ändert aber das Patch nicht.
- Edit-Buffer für Midicontroller eingeführt.
- Textfelder für Patchnummer und Patchname hinzugefügt.
Durch Einfachklick auf Patchname-Textfeld kann Patchname geändert.
Durch Einfachklick auf Patchnummer-Textfeld kann Patch direkt angewählt werden.
Anzeige im Patchname-Textfeld, wenn ein Patch editiert wurde.
- +/- Tasten für bequemes Durchklicken der Patches.
- Synthesizer merkt sich jetzt alle MidiControllerwerte.
Beim Umschalten zwischen den Patches werden,
die zugewiesenen Modulationsziele korrekt initialisiert.
----------------------------------------------------
V 0.4.1, 10.08.2012
- LFO: Smoothing Range intern um Factor 20 verkleinert.
- ToolTips: Bugfix: Tooltips wurden doppelt angezeigt
- GUI: Zuweisungen für MidiController hinzugefügt.
Menü ist erreichbar durch Rechtsklick auf Parameter-Regler
- Maximale Anzahl der Patches von 128 auf 64 reduziert
----------------------------------------------------
V 0.3.2, 05.08.2012
- Bugfix: Durch Verwendung von globalen Variablen, haben sich mehrere
Instanzen des Plugins gegenseitig beeinflusst.
- Bugfix: Das Abspeichern von Bänken, also von mehreren Patches auf einmal,
ist nun korrekt implementiert.
----------------------------------------------------
V 0.3.1, 04.08.2012
Allgemein:
- Beim Abspeichern werden nun keine Reglerstellungen mehr abgespeichert,
sondern die wahren, interen Werte. Bei einer Änderung von
Wertebereichen oder wenn ein Parameter dazu kommt, können Patches aus
zukünftigen Versionen korrekt geladen werden.
GUI:
- Umstrukturiert wegen Platzmangel.
- Direkte Werteeingabe der Parameter durch Einfach-klick
auf die Anzeige über den Reglern.
- Tooltips hinzugefügt.
Synthese:
- Weniger Ressourcenverbrauch durch Umstellung von BLIT-Synthese
auf LUT-gestützte BLEP-Synthese.
Interpoliert wird mit Lagrange-Polynom 2. Grads.
VCOs:
- Volumeregler und Ein/Ausschalter (Klick auf LED) hinzugefügt.
- Wellenform Noise1 und Noise2 entfernt.
- Frequenzmodulation geht nun über +/- 4 Oktaven.
- Square heisst jetzt Pulse.
- Sinus und Triangle-Wellenformen hinzugefügt.
- Für Pulse-Wellenform: Pulsweitenregler und PW-Modulation hinzugegefügt.
VCF:
- Filtersweep-charakteristik geändert. Filter macht jetzt 6.8 Oktaven
(20Hz bis 18 kHz) über den gesamten Bereich der Controlvoltage.
- VCF-Envelope-Generator: Bedingt durch Filtercharakteristik
werden intern die Zeiten für Decay und Release mit zwei multipliziert,
um dem subjektiven Hörempfinden gerecht zu werden.
- Envelope-Amount, Velocity-Amount und Key-Follow
können jetzt negativ sein.
- Resonance angepasst.
Resonance = 1 entpricht normaler Filtercharakteristik.
VCA:
- Tremolo kann nicht mehr negativ sein.
- Rauschquelle mit Ein/Aus-Schalter (Klick auf LED)
und Volumeregler hinzugefügt.
Es kann zwischen Uniform (ehemals Noise-1) und Gauss (ehemals Noise-2) ausgewählt werden.
Uniform entspricht gleichförmig verteiltem Rauschen.
Gauss entspricht Gauss-verteiltem Rauschen (was nicht Pink ist).
Pink-Rauschen muss noch hinzugefügt werden. Uniform-Rauschen wird in
späteren Versionen entfernt. Gauss wird dan als White-Noise bezeichnet.
ADSR-Envelope-Generator:
- Die Decay-Zeit wird nun definiert mit der Zeit um von 100% auf 0% zu
fallen. Der Sustain-level hat nun keinen Einfluss auf die
Decay-Steilheit. Die Decay-Steilheit bleibt nun konstant, unabhängig
vom Sustain-Level. Ein Sustain-Level größer 0 wird nun,
abweichend von der eigestellten Decay-Zeit, früher erreicht werden
als ein Sustain-Level von 0.
----------------------------------------------------
V 0.2.2, 22.07.2012
- LFO: Bugfix. 'Restart' klang unnatürlich bei S&H
----------------------------------------------------
V 0.2.1, 22.07.2012
- LFO: Zweite S&H Wellenform (S&H 2) hinzugefügt. Diese wird von
Gauss'schen Rauschen abgeleitet. Kommt dem analogen Vorbild näher. Wellenform S&H 1 ist die alte Wellenform.
- LFO: Neuer LFO-Parameter "smooth". Hatte Umgestaltung der GUI zur Folge. Siehe Bild im Anhang.
- VCO: Bugfix. Fehler führte zum Abbruch des Klangs.
- VCF: Filter-Typen Highpass und Bandpass hinzugefügt.
- VCF: Maximum Resonance auf 10 erhöht.
----------------------------------------------------
V 0.1.1, 21.07.2012
- jetzt mit ansprechender GUI
- Vier LFOs mit den Wellenformen Sine, Saw und Sample and Hold. Square und Tri sind noch nicht bereit
- VCOs haben Wellenformen Saw, Square und Noise. Tri ist noch disabled
- Key follow für VCF
- Tremolo und Stereo panning im VCA
----------------------------------------------------
+85
View File
@@ -0,0 +1,85 @@
---------------------------------
22.07.2012
- VOICE individual panning - (done 18.08.2012)
- LFO sync per midi (AudioPlayHead)
- Filter LP, HP, BP - (done 22.07.2012)
- Pitchwheel - (done 13.08.2012)
- Unisono mode - (done 18.08.2012)
- Portamento - (done 18.08.2012)
- Audio signal input anstatt VCOs
---------------------------------
29.07.2012
- Volume regler für VCOs (Done, 01.08.2012)
- Ein/Aus für VCOs (Done, 01.08.2012)
- Extra Noise OSC mit EIN/Aus und Volumeregler (Done, 01.08.2012)
- Reglerwerte mit Tastatur direkt eingeben (Done, 04.08.2012)
- Hardsync
- Speicheroptimierung: BLEP-LUT-size abhänging von M. BLEP-LUT-size abfallend mit steigender Frequenz.
---------------------------------
01.08.2012
- CCTRLs für alle Parameter (done 10.8.12)
04.08.2012
- Synthbandwidth muss Frequenz sein, statt omega.
---------------------------------
05.08.2012
- VCO gegenseitige FM und AM (done 22.8.12)
---------------------------------
10.08.2012
- Parametersmoothing für MidiCC
- Edit-Buffer für MidiCC-Assignments (done 11.8.12)
- Pitch-wheel Bereich einstellen - (done 13.08.2012)
- Bug: MidiCC: RangeMax == RangeMin => Absturz (done 10.8.12)
- Bug: LFO_SHAPE: SH-1 nicht anwählbar, es erschein TRI (done 10.8.12)
- MidiCC-Popup: "Move Slider = 1" => "Absolute" (done 10.8.12)
"Move Slider = 0" => "Relative"
---------------------------------
11.08.2012
- bei SetProgramm müssen alle zugewisenen RelativControllZiele
initialisiert werden (done 12.8.12)
---------------------------------
14.08.2012
- Parametertoleranzen pro Voice (Humanize-Funktion) - (done 18.08.2012)
---------------------------------
17.08.2012
- Bug: Wird GUI geschlossen und wieder geöffnet wird editiertes Patch mit Programmspeicher überschrieben - (done 22.08.2012)
- Pitchbenderbereich +/- 48 Töne - (done 22.08.2012)
- Hohe Resonanzwerte führen zu Verzerrungen
- Testen: Wenn Midi-Controller nicht mehr zugewiesen ist, Control auf 0 setzen bzw. Regler auf Patchwert setzen.
- Ob aktuelle Midi-Controllerstellungen beim Umschalten des Patch auf die Controllerziele des nächsten Patchs angewendet
wird, soll im MidiPopup einstellbar sein. - (done 19.08.2012)
- Temperaturdrift (Mainboard-Temperatur)
- Änderung des Patchnamens im Host führt nicht zum Update auf dem Plugin-Bildschirm - (done 19.08.2012)
- Lautstärke-Anpassung, im Unisono-Mode - (done 25.08.2012)
- Delay für LFOs
23.08.2012
- paramScale: Klasse davon machen und JaySynth, JaySynthSound und JaySynthMidiCC beerben.
- Beim Laden von meheren Instanzen kommt es gelegentlich zum Crash, wenn vorher eine Bank geladen wurde. Schwer reproduzierbar.
- Unisono -Mode auch polyphon spielbar. Nutzung der brachliegenden Stimmenressourcen - (done 25.08.2012)
30.8:2012
- Modulation sources richtig mappen