- initial import
git-svn-id: http://moon:8086/svn/software/trunk/projects/JaySynth@37 b431acfa-c32f-4a4a-93f1-934dc6c82436
This commit is contained in:
@@ -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& 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;
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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
@@ -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__
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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_
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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_
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
@@ -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_
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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_
|
||||
@@ -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
|
||||
@@ -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__
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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
@@ -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__
|
||||
@@ -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
|
||||
@@ -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 |
@@ -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;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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_
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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_
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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 Schrage’s 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;
|
||||
}
|
||||
@@ -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_
|
||||
@@ -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*)¶m_info[i];
|
||||
}
|
||||
@@ -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_
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
@@ -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_
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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_
|
||||
@@ -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 */
|
||||
}
|
||||
@@ -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_
|
||||
|
||||
@@ -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_
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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_
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_
|
||||
@@ -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++));
|
||||
}
|
||||
}
|
||||
@@ -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_
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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_
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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_
|
||||
Reference in New Issue
Block a user