63 Commits
Author SHA1 Message Date
jens e9a5784ed1 refactored pacth import/export 2026-05-10 16:10:51 +02:00
jens f72a89ed61 no setCurrentProgram on getCurrentSatte 2026-05-10 13:55:47 +02:00
jens 17b12fe3f1 fix midi controller dialog 2026-05-10 13:37:38 +02:00
jens 255858cee8 - combo boxes have midi controller dialog
- reduce update of parameter sliders during Midi Controller Dialog
2026-05-10 13:08:35 +02:00
jens 15bcf87529 improved assignment of midi controllers 2026-05-10 12:11:34 +02:00
jens 31a0c4c009 fixed NRPN 2026-05-10 10:53:26 +02:00
jens 6e67193c3d - robusten and refactored NRPN
- increased number of midicontrollers from 128 to 1024
2026-05-10 10:36:24 +02:00
jens cbdb18e6ba handleController for CC and NPRN 2026-05-09 22:11:40 +02:00
jens bc2020e612 NRPN: normalized by max value 2026-05-09 22:04:21 +02:00
jens 8ce2db511b added Midi NRPN 2026-05-09 20:37:17 +02:00
jens 6be1b4a911 updated .gitignore 2026-05-09 08:37:16 +02:00
jens a8e6593eed used -pre suffix for version 2026-05-09 08:34:24 +02:00
jens c392104aec - refactored kml import/export
- added ability to import patch file with midicc defined without patch parameter
- fixed notes cut off by calling getStateInformation()
- disabled limiter
- increased version to v1.1.0-pre
2026-05-09 08:34:01 +02:00
jens 0de8c05f00 fixed behavior whenn unison and humanize is set over midi 2026-05-09 08:30:12 +02:00
jens 597c70bb53 fixed eval_blep 2026-05-09 08:29:00 +02:00
jens c7c9366dbb - refactored
- remove DC
2025-08-22 14:49:50 +02:00
jens 2ab8c68c9b m-files fixed wavwrite 2025-08-22 13:39:23 +02:00
jens 21411d2c56 m-files compile clean 2025-08-21 21:09:48 +02:00
jens 4f7803a8b4 added doc 2025-08-21 07:52:16 +02:00
jens 64c6745c76 added matlab 2025-08-21 07:27:52 +02:00
jens fd522e1b99 no SYNTH_DEBUG for release build 2025-08-18 21:55:31 +02:00
jens 7e11e3e72b fixed midi sync led 2025-08-18 21:42:19 +02:00
jens ed737f526f updated .gitignore 2025-08-18 18:35:13 +02:00
jens 83afc11612 - added run and install target 2025-08-18 18:32:08 +02:00
jens 8a81dd649e added web URL for later reference 2025-08-18 18:31:26 +02:00
jens 42e877c08d fixed includes 2025-08-18 18:30:55 +02:00
jens 1e0760e49b fixed includes 2025-08-18 18:29:25 +02:00
jens db4fdf68ff fixed MidiClock now working with ardour 2025-08-18 18:22:55 +02:00
jens 314b57b1ed fixing MidiClock (Zwischenstand #3) 2025-08-18 09:37:39 +02:00
jens a3ad0e989e fixing MidiClock (Zwischenstand #2) 2025-08-16 15:10:26 +02:00
jens 159fa60b08 fixing MidiClock (Zwischenstand) 2025-08-16 14:16:13 +02:00
jens e3fb2074f6 DSP: changed from float to double 2025-08-08 17:44:01 +02:00
jens 7fcbb9b509 Fixed code problems 2025-08-08 16:36:22 +02:00
jens 3a19db6a86 Fixed code problems 2025-08-08 16:36:09 +02:00
jens d73f172fc1 added bear target 2025-08-08 16:35:29 +02:00
jens f05e3be55f Fixed code problems 2025-08-08 16:35:04 +02:00
jens 2ec3cc9543 added run target 2025-08-08 13:54:33 +02:00
jens 0f70ea025c change submodule/make 2025-08-08 13:54:08 +02:00
jens 2ac71f33f1 added new waves 2025-08-06 22:08:46 +02:00
jens 73332a7292 refactored wavetable constants 2025-08-06 22:08:13 +02:00
jens 4bf46df821 - added 12bit wace for Microwave
- refactored
2025-08-06 21:15:12 +02:00
jens 072280c603 refactored waves 2025-08-06 07:51:29 +02:00
jens 4a4d67f5f1 - wavetable using Waldorf Microwave "wave.bin" (16bit) is broken
- wavetable uses "wave2.bin" (8bit) Waveforms
-
2025-08-05 19:36:59 +02:00
jens 12783fdfdb removed unused include 2025-08-03 20:51:34 +02:00
jens 63e1daa706 export waves to uild folder 2025-08-03 20:42:07 +02:00
jens bc8a2b5b20 cleaned up 2025-08-03 20:35:59 +02:00
jens 26c3ee4cb6 - fixed problems
- updated .gitignore
2025-08-03 17:04:57 +02:00
jens c0e651bf68 - refactored 2025-08-03 10:57:01 +02:00
jens d801ce21e8 added patch 2025-08-02 14:36:02 +02:00
jens 025818a042 [sdk/vstsdk2.4]
- refactored
- created patch
2025-08-02 14:34:53 +02:00
jens 3bda521d62 - fixed master volume
- added osc jitter to blep waveform saw, square and tri
2025-08-02 12:04:40 +02:00
jens ff6ba8a179 permit to override default make environment 2025-08-02 10:24:41 +02:00
jens 2afe0cfccc change submodule/make 2025-08-02 10:23:53 +02:00
jens e666247a45 change submodule/fir 2025-08-02 10:22:04 +02:00
jens dab1ed956f juce: use 2025-08-02 10:17:55 +02:00
jens 0dd21799f9 [VCO/Blit/Sawtooth]
- added slight random frequency deviation for more vivid sound
2025-07-31 18:15:08 +02:00
jens bcfe5e4edd fixed 2025-07-31 18:14:23 +02:00
jens 4d25a24e53 disabled limiter 2025-07-31 18:13:16 +02:00
jens 3e63bdd4ce added sounds 2025-07-31 18:01:49 +02:00
jens 465bc88e8f removed linefeed 2025-07-31 16:41:24 +02:00
jens 6e8b990391 -fixed includes 2025-07-31 16:39:38 +02:00
jens 6fc6b9f567 - added submodules 2025-07-29 20:43:25 +02:00
jens 7ef6975cb3 - adde exra sounds 2024-03-04 08:40:52 +01:00
154 changed files with 159112 additions and 678 deletions
+12
View File
@@ -0,0 +1,12 @@
build
.cache
c_cpp_properties.json
compile_commands.json
venv
.codechecker
.vscode
matlab/osc/blip/saw.wav
matlab/osc/blip/sqr.wav
matlab/osc/blip/tri.wav
octave-workspace
+6
View File
@@ -0,0 +1,6 @@
[submodule "submodule/make"]
path = submodule/make
url = http://192.168.22.90:3001/jayfield/make.git
[submodule "submodule/fir"]
path = submodule/fir
url = http://192.168.22.90:3001/jayfield/fir.git
+31 -15
View File
@@ -1,15 +1,19 @@
include $(MAKE_HOME)/defaults.mk include make/defaults.mk
CONFIG ?= release CONFIG ?= release
TARGET ?= JaySynth.so TARGET ?= JaySynth.so
LIBSRC_PATH ?= $(realpath ../../libsrc) APP_VERSION := 1.1.0-pre
APP_VERSION_HEX := 0x010001
LIBSRC_PATH ?= $(realpath ./submodule)
JUCE_PATH := $(realpath ./sdk/juce/JUCE-3.1.1) JUCE_PATH := $(realpath ./sdk/juce/JUCE-3.1.1)
VST2_SDK_PATH ?= $(realpath ./sdk/vst/vstsdk2.4) VST2_SDK_PATH ?= $(realpath ./sdk/vst/vstsdk2.4)
JUCE_LIBCODE_PATH ?= $(realpath ./JuceLibraryCode)
SRC_PATH := $(realpath ./src)
NAME =: JaySynth NAME =: JaySynth
DEFINES := -Dradio_float_t=float -Dfir_float_t=float -Dsynth_float_t=float DEFINES := -Dradio_float_t=double -Dfir_float_t=double -Dsynth_float_t=double
DEFINES += -DHAVE_LROUND DEFINES += -DHAVE_LROUND
CFLAGS += -fPIC CFLAGS += -fPIC
CXXFLAGS += -fPIC CXXFLAGS += -fPIC
@@ -19,20 +23,21 @@ LIBS := -lstdc++ -lm -lGL -lX11 -lXext -lXinerama -lasound -ldl -lfreetype -lpth
LDFLAGS += $(TARGET_ARCH) $(LIBDIR) -L/usr/X11R6/lib/ -shared LDFLAGS += $(TARGET_ARCH) $(LIBDIR) -L/usr/X11R6/lib/ -shared
DEFINES += -D__cdecl="" DEFINES += -D__cdecl=""
DEFINES += -DJUCE_GCC=1 -DLINUX=1 -DJUCE_APP_VERSION=1.0.0 -DJUCE_APP_VERSION_HEX=0x10000 DEFINES += -DJUCE_GCC=1 -DLINUX=1 -DJUCE_APP_VERSION=$(APP_VERSION) -DJUCE_APP_VERSION_HEX=$(APP_VERSION_HEX)
DEFINES_debug += -DDEBUG=1 -D_DEBUG=1 DEFINES_debug += -DDEBUG=1 -D_DEBUG=1 -DSYNTH_DEBUG
DEFINES_release += -DNDEBUG DEFINES_release += -DNDEBUG
DEFINES += -DJucePlugin_Version=1.0.0 DEFINES += -DJucePlugin_Version=$(APP_VERSION)
DEFINES += -DJucePlugin_VersionCode=0x01000000 DEFINES += -DJucePlugin_VersionCode=$(APP_VERSION_HEX)
DEFINES += -DJucePlugin_VersionString=\"1.0.0\" DEFINES += -DJucePlugin_VersionString=\"$(APP_VERSION)\"
INCLUDES += -I $(JUCE_PATH) -I $(JUCE_PATH)/modules -I $(VST2_SDK_PATH) -I $(LIBSRC_PATH) INCLUDES += -I $(JUCE_PATH) -I $(JUCE_PATH)/modules -I $(VST2_SDK_PATH) -I $(LIBSRC_PATH) -I $(JUCE_LIBCODE_PATH) -I $(SRC_PATH)
PACKAGES := JuceLibraryCode Source Synth Fir PACKAGES := JuceLibraryCode plug synth fir
export export
all: app all: app
app: objects link app: objects link
@@ -40,16 +45,27 @@ app: objects link
objects: ${PACKAGES} objects: ${PACKAGES}
Synth: synth:
@$(MAKE) -C Source/synth @$(MAKE) -C $(SRC_PATH)/synth
Source: plug:
@$(MAKE) -C $@ @$(MAKE) -C $(SRC_PATH)/plug
JuceLibraryCode: JuceLibraryCode:
@$(MAKE) -C $@ @$(MAKE) -C $@
Fir: fir:
@$(MAKE) -C $(LIBSRC_PATH)/fir @$(MAKE) -C $(LIBSRC_PATH)/fir
bear:
make distclean
bear --output compile_commands.json -- $(MAKE)
run: install
carla ~/jaysynth+tal.carxp
install: app
cp extras/waves/waves_microwave_v2.0_8bit ~/.vst/jaysynth/waves.bin
cp build/linux/$(CONFIG)/JaySynth.so ~/.vst/jaysynth/JaySynth.so
include $(MAKE_HOME)/link.mk include $(MAKE_HOME)/link.mk
-189
View File
@@ -1,189 +0,0 @@
/*
//#######################################################################################
//Class to insert Midiclock messages into a given MidiBuffer, suitable for block
//based audio callbacks. The class can act on position jumps e.g. "Loops" by sending a
//positioning message.
//NOTE: No ballistik came in to play so I wouldn't recommend using it to drive a mechanical
//tape deck!!!
//
//solar3d-software, April- 10- 2012
//#######################################################################################
*/
#include "JK_MidiClock.h"
JK_MidiClock::JK_MidiClock()
:wasPlaying(false),
syncPpqPosition(-999.0),
posChangeThreshold(0.001),
ppqToStartSyncAt(0.0),
followSongPosition(true),
syncFlag(0),
ppqOffset(0)
{
//Prepare Midi messages to avoid blocking the caller of generateMidiclock()!
continueMessage = new MidiMessage(MidiMessage::midiContinue());
stopMessage = new MidiMessage(MidiMessage::midiStop());
clockMessage = new MidiMessage(MidiMessage::midiClock());
songPositionMessage = new MidiMessage(MidiMessage::songPositionPointer(0));
}
//=================================================================================================
void JK_MidiClock::generateMidiclock(AudioPlayHead::CurrentPositionInfo &lastPosInfo,
MidiBuffer* midiBuffer, const int bufferSize, const double sampleRate)
{
//###################################Some explanation about musical tempo #################
//A Time Signature, is two numbers, one on top of the other. The numerator describes the #
//number of Beats in a Bar, while the denominator describes of what note value a Beat is. #
//So 4/4 would be four quarter-notes per Bar, while 4/2 would be four half-notes per Bar, #
//4/8 would be four eighth-notes per Bar, and 2/4 would be two quarter-notes per Bar. #
//#########################################################################################
if (midiBuffer != nullptr)
{
//PPQ value of one sample
const double ppqPerSample = (lastPosInfo.bpm / 60.0) / sampleRate;
//PPQ offset to compensate Midi interface latency
double hostPpqPosition = lastPosInfo.ppqPosition + ppqOffset * ppqPerSample;;
if (lastPosInfo.isPlaying || lastPosInfo.isRecording)
{
if (! wasPlaying)
{
//set the point where to start the slave
ppqToStartSyncAt = getNearestSixteenthInPPQ(hostPpqPosition);
//Special case: Master is set to always start playback from the previous start position...
if (positionJumped(syncPpqPosition, hostPpqPosition, sampleRate, ppqPerSample))
{
//Cue Midiclock slave to the nearest sixteenth note to new start position
//because the one calculated in stop mode isn't valid anymore.
sendSongPositionPointerMessage(ppqToStartSyncAt, 0, midiBuffer);
}
}
else
{
//Position jump (loop or manually position change while playing)
if (positionJumped(syncPpqPosition, hostPpqPosition, sampleRate, ppqPerSample))
{
//set the point where to start the slave
ppqToStartSyncAt = getNearestSixteenthInPPQ(hostPpqPosition);
//User has changed position manually while playing
if (syncFlag == 0)
{
midiBuffer->addEvent(*stopMessage, 0);
sendSongPositionPointerMessage(hostPpqPosition, 0, midiBuffer);
syncFlag = startSlave_;
}
else
{
if (followSongPosition)
{
sendSongPositionPointerMessage(hostPpqPosition, 0, midiBuffer);
syncFlag = startSlave_;
}
else
syncFlag = 0;
}
}
}
for (int posInBuffer = 0; posInBuffer < bufferSize; ++posInBuffer)
{
syncPpqPosition = hostPpqPosition + (posInBuffer * ppqPerSample);
const int clockDistanceInSamples = roundToInt((60.0 * sampleRate) / (lastPosInfo.bpm * 24.0));
const int64 hostSamplePos = roundToInt64((hostPpqPosition * (60.0 / lastPosInfo.bpm)) * sampleRate);
const int64 syncSamplePos = hostSamplePos + posInBuffer;
//Some hosts like Cubase come up with a wacky ppqPosition
//that could break the timing! Best is to "wait"
//here for the right ppqPosition to jump on.
if (syncPpqPosition >= ppqToStartSyncAt)
{
if ((syncFlag & startSlave_) == startSlave_)
{
midiBuffer->addEvent(*continueMessage, posInBuffer);
syncFlag &= cycleEnd_;
}
//Cycle mode on
if (lastPosInfo.isLooping && lastPosInfo.ppqLoopStart != lastPosInfo.ppqLoopEnd)
{
const double ppqToCycleEnd = fabs(lastPosInfo.ppqLoopEnd - syncPpqPosition);
const int64 samplesToCycleEnd = roundToInt64(ppqToCycleEnd * (60.0 / lastPosInfo.bpm) * sampleRate);
if ((syncFlag & cycleEnd_) == 0)
{
if (samplesToCycleEnd <= clockDistanceInSamples) //For fine tuning tweak here
{
//We have reached the cycle- end position
//and must stop the Midiclock slave here
if (followSongPosition)
midiBuffer->addEvent(*stopMessage, posInBuffer);
syncFlag |= cycleEnd_;
}
}
}
}
//For best timing we should never interupt Midiclock messages!
//Seems that some slaves constantly adjusting their internal clock
//to Midiclock even if they are in stop mode.
if (syncSamplePos % clockDistanceInSamples == 0)
midiBuffer->addEvent(*clockMessage, posInBuffer);
}
wasPlaying = true;
}
else
{
//Send positioning message if the user has stopped or if he changed the playhead position
//manually in stop mode! This will also initially cue slave after loading plugin instance.
if (wasPlaying || positionJumped(syncPpqPosition, hostPpqPosition, sampleRate, ppqPerSample))
{
midiBuffer->addEvent(*stopMessage, 0);
sendSongPositionPointerMessage(hostPpqPosition, 0, midiBuffer);
}
syncPpqPosition = hostPpqPosition;
syncFlag = startSlave_;
wasPlaying = false;
}
}
}
//=================================================================================================
bool JK_MidiClock::positionJumped(const double lastPosInPPQ, const double currentPosInPPQ,
const double sampleRate, const double ppqPerSample)
{
//This returns true if the user has changed the playhead position manually or if
//a jump has occured! The comperator's default threshold is lastPosInPPQ +- 10ms.
if (currentPosInPPQ < lastPosInPPQ - ((posChangeThreshold * sampleRate) * ppqPerSample) ||
currentPosInPPQ > lastPosInPPQ + ((posChangeThreshold * sampleRate) * ppqPerSample))
return true;
return false;
}
//=================================================================================================
void JK_MidiClock::sendSongPositionPointerMessage(const double ppqPosition, const int posInBuffer, MidiBuffer* buffer)
{
//This will cue the slave to the NEAREST
//16th note to the given ppqPosition.
int intBeat = int(ceil(ppqPosition * 4));
uint8* pSongPositionTime((uint8*)(songPositionMessage->getRawData()));
*(pSongPositionTime + 1) = (uint8)(intBeat & 0x7f);
*(pSongPositionTime + 2) = (uint8)((intBeat & 0x3f80)>>7);
buffer->addEvent(*songPositionMessage, posInBuffer);
}
-11
View File
@@ -1,11 +0,0 @@
include $(MAKE_HOME)/defaults.mk
LIBSRC_PATH ?= $(realpath ../../../libsrc)
JUCE_PATH ?= $(realpath ../sdk/juce/JUCE-3.1.1)
VST2_SDK_PATH ?= $(realpath ../sdk/vst/vstsdk2.4)
include config.mk
INCLUDES += -I $(LIBSRC_PATH) -I $(JUCE_PATH) -I $(VST2_SDK_PATH)
include $(MAKE_HOME)/compile.mk
-10
View File
@@ -1,10 +0,0 @@
include $(MAKE_HOME)/defaults.mk
LIBSRC_PATH ?= $(realpath ../../../../libsrc)
VST2_SDK_PATH ?= $(realpath ../../sdk/vst/vstsdk2.4)
include config.mk
INCLUDES ?= -I $(LIBSRC_PATH) -I $(VST2_SDK_PATH)
include $(MAKE_HOME)/compile.mk
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+3
View File
@@ -0,0 +1,3 @@
Waldorf MicroWave Wellenformen und WaveTables hinzugefgt. WaveTable-Scan ber PWM.
wave.bin: Original MicroWave Wellenformen mssen als Datei ("waves.bin", 16bit, Big-Endian) im Plugin-Verzeichnis vorliegen, damit Feature freigeschaltet wird.
wave2.bin: Original PPG EVU Wellenformen 8bit
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+7
View File
@@ -0,0 +1,7 @@
include $(MAKE_HOME)/defaults.mk
# Environment
CC=clang
CCC=clang++
CXX=clang++
Vendored Executable
+53
View File
@@ -0,0 +1,53 @@
function eval_adsr(Ta, Td, Vs, Tr, ks)
% eval_adsr(0.1, 0.2, 0.2, 0.2)
fs = 1000;
a_a = -log(1-ks)/(Ta*fs);
a_d = 5/(Td*fs);
a_r = 5/(Tr*fs);
state = 0;
s = 0;
tol = 1E-4;
n = 1;
p = 0;
k = 1/ks;
while (1),
if state == 0 % Attack
s = a_a + (1-a_a)*s;
y(n) = k*s;
if s >= (ks-tol)
state = 1;
s = 1-ks;
end;
end;
if state == 1 % Decay
s = (1-a_d)*s;
y(n) = s/(1-ks);
if s <= (Vs+tol)
state = 2;
p = 0;
end;
end;
if state == 2 % sustain
y(n) = Vs;
if p >= 1*fs
state = 3;
s = Vs;
end;
p = p + 1;
end;
if state == 3 % Release
s = (1-a_r)*s;
y(n) = s;
if s <= (tol)
break;
end;
end;
n = n + 1;
end;
plot((0:n-1)/fs, y); grid;
set(gca,'xtick',[0:0.1:(n-1)/fs])
Vendored Executable
+52
View File
@@ -0,0 +1,52 @@
function eval_adsr(Ta, Td, Vs, Tr, ks)
% eval_adsr(0.1, 0.2, 0.2, 0.2)
fs = 1000;
a_a = -log(1-ks)/(Ta*fs);
a_d = 5/(Td*fs);
a_r = 5/(Tr*fs);
state = 0;
s = 0;
tol = 1E-4;
n = 1;
p = 0;
k = 1/ks;
while (1),
if state == 0 % Attack
s = a_a + (1-a_a)*s;
y(n) = s/ks;
if s >= (ks-tol)
state = 1;
end;
end;
if state == 1 % Decay
s = (1-a_d)*s;
y(n) = s/(ks);
if s <= (Vs*ks+tol)
state = 2;
p = 0;
end;
end;
if state == 2 % sustain
y(n) = Vs;
if p >= 1*fs
state = 3;
s = Vs;
end;
p = p + 1;
end;
if state == 3 % Release
s = (1-a_r)*s;
y(n) = s;
if s <= (tol)
break;
end;
end;
n = n + 1;
end;
plot((0:n-1)/fs, y); grid;
set(gca,'xtick',[0:0.1:(n-1)/fs])
Vendored Executable
+56
View File
@@ -0,0 +1,56 @@
function eval_adsr(Ta, Td, Vs, Tr)
% eval_adsr(0.1, 0.2, 0.2, 0.2)
fs = 10000;
aa = 1/(Ta*fs)
ba = (1-aa)
a_d = 5/(Td*fs)
a_r = 5/(Tr*fs)
state = 0;
s = 0;
tol = 1E-4;
ke = 1-exp(-1)
n = 0;
p = 0;
k = 1/ke;
kk = 0;
s
while (1),
if state == 0
s = aa + ba*s;
if s >= (ke-tol)
state = 1;
k = (1-Vs)/ke;
kk = Vs;
end;
end;
if state == 1
s = (1-a_d)*s;
if s <= (tol)
state = 2;
s = 1;
k = Vs;
kk = 0;
p = 0;
end;
end;
if state == 2
if p >= 0.1*fs
state = 3;
end;
p = p + 1;
end;
if state == 3
s = (1-a_r)*s;
if s <= (tol)
break;
end;
end;
n = n + 1;
y(n) = k*s + kk;
end;
plot((0:n-1)/fs, 0.8-y); grid;
Vendored Executable
+52
View File
@@ -0,0 +1,52 @@
function eval_adsr(Ta, Td, Vs, Tr)
% eval_adsr(0.1, 0.2, 0.2, 0.2)
fs = 1000;
a_a = 1/(Ta*fs);
a_d = -1/(Td*fs/log(Vs))
a_d = 5/(Td*fs)
a_r = 5/(Tr*fs)
state = 0;
s = 0;
tol = 1E-4;
target = 1;
n = 0;
p = 0;
k = 1/0.63;
while (1),
if state == 0 % Attack
s = a_a + (1-a_a)*s;
if s >= (0.63-tol)
state = 1
target = Vs;
end;
end;
if state == 1 % Decay
s = (1-a_d)*s;
if s <= (0.63*Vs+tol)
state = 2
target = 0;
p = 0;
end;
end;
if state == 2 % sustain
s = Vs/k;
if p >= 1*fs
state = 3
end;
p = p + 1;
end;
if state == 3 % Release
s = (1-a_r)*s;
if s <= (target+tol)
break;
end;
end;
n = n + 1;
y(n) = k*s;
end;
plot((0:n-1)/fs, y); grid;
+18
View File
@@ -0,0 +1,18 @@
function eval_vcf_lut()
N = 1000;
fs = 48000;
fmin = 18;
fmax = 18000;
sweepbase = 10;
filterParam = struct('sweepbase', 10, 'omega_min', 2*fmin/fs, 'omega_max', 2*fmax/fs, 'num_octaves', log(fmax/fmin)/log(sweepbase));
filterParam
cv = (0:N-1)/N;
plot (c
function cv = omega2cv(filterParam, omega)
cv = log(omega/filterParam.omega_min)/(filterParam.num_octaves * log(filterParam.sweepbase));
cv = min(1, max(0, cv));
function omega = cv2omega(filterParam, cv)
omega = filterParam.omega_min*filterParam.sweepbase ^ (filterParam.num_octaves*min(1, max(0, cv)));
+23
View File
@@ -0,0 +1,23 @@
function eval_vcf_lut()
N = 1000;
fs = 48000;
fmin = 18;
fmax = 18000;
sweepbase = 10;
filterParam = struct('sweepbase', 10, 'omega_min', fmin/fs, 'omega_max', fmax/fs, 'num_octaves', log(fmax/fmin)/log(sweepbase));
filterParam
cv = (0:N-1)/N;
subplot(2, 1, 1)
plot (cv, fs*cv2omega(filterParam, cv)); grid; legend('F'); xlabel('cv');
subplot(2, 1, 2)
plot (cv, cos(2*pi*cv2omega(filterParam, cv)), cv, sin(2*pi*cv2omega(filterParam, cv))); grid; legend('kc', 'ks'); xlabel('cv');
function cv = omega2cv(filterParam, omega)
cv = log(omega/filterParam.omega_min)/(filterParam.num_octaves * log(filterParam.sweepbase));
cv = min(1, max(0, cv));
function omega = cv2omega(filterParam, cv)
omega = filterParam.omega_min*filterParam.sweepbase .^ (filterParam.num_octaves*min(1, max(0, cv)));
+34
View File
@@ -0,0 +1,34 @@
function eval_lfo()
L = 10000;
fs = 44100;
fstart = 40;
fend = 400;
df = (fend-fstart)/L;
ip = 0 % phase of the first output sample in radians
w = freq*pi / samplerate
b1 = 2.0 * cos(w)
% Init
y1=sin(ip-w)
y2=sin(ip-2*w)
% Loop
for n=1:L,
y0 = b1*y1 - y2
y2 = y1
y1 = y0
close all
figure;
plot(1:L, vsaw, 1:L, vblit); grid;
wavwrite(0.5*vtri, fs, 'tri.wav');
wavwrite(0.5*vsqr, fs, 'sqr.wav');
wavwrite(0.5*vsaw, fs, 'saw.wav');
wavwrite(0.5*vblit, fs, 'blit.wav');
+44
View File
@@ -0,0 +1,44 @@
function eval_lfo()
L = 10000;
fs = 44100;
fstart = 44;
fend = 400;
df = (fend-fstart)/L;
ip = 0 % phase of the first output sample in radians
% Init
% Loop
f = fstart;
fchg = 1;
y1=sin(ip-f*pi / fs);
y2=sin(ip-2*f*pi / fs);
for n=1:L,
if fchg == 1,
b1 = 2.0 * cos(f*pi / fs);
fchg = 1000;
end;
y0 = b1*y1 - y2;
y2 = y1;
y1 = y0;
fchg = fchg - 1;
lfo(n) = y0;
f = f + df;
close all
end;
figure;
plot(1:L, lfo); grid;
wavwrite(0.5*lfo, fs, 'lfo.wav');
+47
View File
@@ -0,0 +1,47 @@
function eval_lfo2()
L = 80000;
fs = 48000;
fstart = 10;
fend = 1000;
df = (fend-fstart)/L;
ip = 0.0 % phase of the first output sample in radians
% Init
% Loop
f = fstart;
fchg = 0;
ylast = 0;
a = 0.5;
b = 2.0 * sin(f*pi / fs);
y0 = a*cos(2*pi*ip);
y1 = a*sin(2*pi*ip);
for n=1:L,
y0 = y0 - b*y1;
y1 = y1 + b*y0;
fchg = (mod(n, 1000) == 0);
if fchg
b = 2.0 * sin(f*pi / fs);
end
ylast = y1;
lfo(n) = y0;
f = f + df;
close all
end;
figure;
plot(1:L, lfo); grid;
wavwrite(0.5*lfo, fs, 'lfo.wav');
+47
View File
@@ -0,0 +1,47 @@
function eval_lfo2()
L = 80000;
fs = 48000;
fstart = 10;
fend = 5000;
df = (fend-fstart)/L;
ip = 0.0 % phase of the first output sample in radians
% Init
% Loop
f = fstart;
fchg = 0;
ylast = 0;
a = 0.5;
b = 2.0 * sin(f*pi / fs);
y0 = a*cos(2*pi*ip);
y1 = a*sin(2*pi*ip);
for n=1:L,
y0 = y0 - b*y1;
y1 = y1 + b*y0;
fchg = (mod(n, 1000) == 0);
if fchg
b = 2.0 * sin(f*pi / fs);
end
ylast = y1;
lfo(n) = y0;
f = f + df;
close all
end;
figure;
plot(1:L, lfo); grid;
wavwrite(0.5*lfo, fs, 'lfo.wav');
+21
View File
@@ -0,0 +1,21 @@
function eval_smooth(Ta)
fs = 10000;
b = 1;
if (abs(Ta) > 0)
b = 1/(abs(Ta)*fs);
end;
a = 1 - b;
x = [ zeros(1, 1000) ones(1, 1000) zeros(1, 1000)];
y = 0;
for i=1:length(x)
if (Ta < 0)
y = b*x(i) + a*y;
yn(i) = y;
end;
plot(yn); grid;
+34
View File
@@ -0,0 +1,34 @@
function eval_smooth(Ta)
fs = 10000;
b = 1;
if (abs(Ta) > 0)
b = 1/(abs(Ta)*fs);
end;
a = 1 - b;
x = [ zeros(1, 1000) ones(1, 1000) zeros(1, 1000)];
N = length(x);
y = 0;
y1 = 0;
for i=1:length(x)
y1 = b*x(i) + a*y1;
% if (Ta > 0)
y1n(i) = y1;
% else
y2n(i) = 2*x(i) - y1;
% end
end;
subplot(3, 1, 1)
plot(1:N, x, 'r'); grid;
xlabel('Original LFO Wellenform (Square)')
subplot(3, 1, 2)
plot(1:N, y1n, 'r'); grid;
xlabel('Positive smoothed')
subplot(3, 1, 3)
plot(1:N, y2n, 'r'); grid;
xlabel('Negative smoothed')
BIN
View File
Binary file not shown.
+38
View File
@@ -0,0 +1,38 @@
function eval_limiter(name)
Tr = 1; % ms
Tf = 100; % ms
input_gain = 2;
output_gain = 0.5;
limit_thresh = 0.25;
[x, fs, nbits, opts] = wavread(name);
x = x.*input_gain;
N = fix(length(x)/);
a_r = 1000/(Tr*fs);
a_f = 1000/(Tf*fs);
y = 0;
for n=1:N
if (y < abs(x(n)))
y = y + a_r*(abs(x(n)) - y);
else
y = y + a_f*(abs(x(n)) - y);
end
env(n) = y;
end;
limiter_gain = limit_thresh./max(limit_thresh, env)';
x_limited = x(1:N).*limiter_gain.*output_gain;
wavwrite(x_limited,fs,'limiter_out.wav');
subplot(2, 1, 1)
plot(0:N-1, x(1:N), 0:N-1, env, 'r-'); grid;
subplot(2, 1, 2)
plot(0:N-1, x_limited, 0:N-1, limiter_gain, 'r-'); grid;
+38
View File
@@ -0,0 +1,38 @@
function eval_limiter(name)
Tr = 1; % ms
Tf = 100; % ms
input_gain = 2;
output_gain = 0.5;
limit_thresh = 0.25;
[x, fs, nbits, opts] = wavread(name);
x = x.*input_gain;
N = fix(length(x));
a_r = 1000/(Tr*fs);
a_f = 1000/(Tf*fs);
y = 0;
for n=1:N
if (y < abs(x(n)))
y = y + a_r*(abs(x(n)) - y);
else
y = y + a_f*(abs(x(n)) - y);
end
env(n) = y;
end;
limiter_gain = limit_thresh./max(limit_thresh, env)';
x_limited = x(1:N).*limiter_gain.*output_gain;
wavwrite(x_limited,fs,'limiter_out.wav');
subplot(2, 1, 1)
plot(0:N-1, x(1:N), 0:N-1, env, 'r-'); grid;
subplot(2, 1, 2)
plot(0:N-1, x_limited, 0:N-1, limiter_gain, 'r-'); grid;
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+77
View File
@@ -0,0 +1,77 @@
function eval_midi_sync(pe, fe)
N = 5000;
t = (0:N-1)/N;
x1 = mod(20*t, 1) >=0.5;
x2 = mod((20+fe)*t+pe, 1) >=0.5;
dx1 = 50/N
dx2 = (50+fe)/N
qi1 = 0;
qi2 = 0;
xi1 = 0;
xi2 = 0;
xx1 = 0;
xx2 = 0;
lead = 0;
lag = 0;
ddx = 0;
for i=1:N,
%[qi1, qi2, xi1, xi2] = pd(x1(i), x2(i), qi1, qi2, xi1, xi2);
[qi1, qi2, xi1, xi2] = pd(xx1 >=0.5, xx2 >=0.5, qi1, qi2, xi1, xi2);
err = (qi1-qi2);
lead = 0.*err;
lag = lag + 0.000001*err;
ddx = (lead+lag);
xx1 = mod(xx1 + dx1, 1);
xx2 = mod(xx2 + dx2 + ddx, 1);
q1(i) = qi1;
q2(i) = qi2;
end;
dx2 = dx2 + ddx
dx1 = dx1
subplot(3, 1, 1)
plot(t, x1, t, x2); grid; axis([0 1 -0.2 1.2])
subplot(3, 1, 2)
plot(t, q1); grid; axis([0 1 -0.2 1.2])
subplot(3, 1, 3)
plot(t, q2); grid; axis([0 1 -0.2 1.2])
function [Q1, Q2, xo1, xo2] = pd(x1, x2, qi1, qi2, xi1, xi2)
xo1 = xi1;
xo2 = xi2;
qo1 = qi1;
qo2 = qi2;
for i=1:length(x1)
% Q1
% Detect edge
if (x1(i) - xo1) > 0.5
qo1 = 1;
end;
xo1 = x1(i);
% Q2
% Detect edge
if (x2(i) - xo2) > 0.5
qo2 = 1;
end;
xo2 = x2(i);
% Asynchronous reset
if (qo1 * qo2) > 0.5
qo1 = 0;
qo2 = 0;
end;
Q1(i) = qo1;
Q2(i) = qo2;
end;
+75
View File
@@ -0,0 +1,75 @@
function eval_midi_sync(pe, fe)
N = 5000;
t = (0:N-1)/N;
dx1 = 40/N
dx2 = (40+fe)/N
qi1 = 0;
qi2 = 0;
xi1 = 0;
xi2 = 0;
xx1 = 0;
xx2 = pe;
lead = 0;
lag = 0;
ddx = 0;
for i=1:N,
[qi1, qi2, xi1, xi2] = pd(xx1 >=0.5, xx2 >=0.5, qi1, qi2, xi1, xi2);
err = (qi1-qi2);
lead = 0.002*err;
lag = lag + 0.000005*err;
ddx(i) = (lead+lag);
xx1 = mod(xx1 + dx1, 1);
xx2 = mod(xx2 + dx2 + ddx(i), 1);
q1(i) = qi1;
q2(i) = qi2;
x1(i) = xx1 >=0.5;
x2(i) = xx2 >=0.5;
end;
subplot(4, 1, 1)
plot(t, x1, t, x2); grid; axis([0 1 -0.2 1.2])
subplot(4, 1, 2)
plot(t, q1); grid; axis([0 1 -0.2 1.2])
subplot(4, 1, 3)
plot(t, q2); grid; axis([0 1 -0.2 1.2])
subplot(4, 1, 4)
plot(t, ddx); grid;
function [Q1, Q2, xo1, xo2] = pd(x1, x2, qi1, qi2, xi1, xi2)
xo1 = xi1;
xo2 = xi2;
qo1 = qi1;
qo2 = qi2;
for i=1:length(x1)
% Q1
% Detect edge
if (x1(i) - xo1) > 0.5
qo1 = 1;
end;
xo1 = x1(i);
% Q2
% Detect edge
if (x2(i) - xo2) > 0.5
qo2 = 1;
end;
xo2 = x2(i);
% Asynchronous reset
if (qo1 * qo2) > 0.5
qo1 = 0;
qo2 = 0;
end;
Q1(i) = qo1;
Q2(i) = qo2;
end;
+116
View File
@@ -0,0 +1,116 @@
function eval_minblep()
nsin = 4096;
nharm_max = 1800;
L = 48000/2;
fs = 48000;
fstart = 440;
fend = 440;
f2start = 200;
f2end = 600;
df = (fend-fstart)/L
df2 = (f2end-f2start)/L
saw = 0;
% Calc blep table
nharm = min(fix((fs/fstart/2.0)) + 1, nharm_max)
Hw = kaiser(nsin, 8);
xx = (0:nsin-1)/nsin - 0.5;
for mm=1:nharm
blitm(mm,:) = sin(xx*(mm-1)*pi)./sin(xx*pi).*Hw';
blitm(mm,(find(isnan(blitm(mm,:))))) = (mm-1);
end;
for mm=1:nharm
blepm(mm, :) = cumsum(blitm(mm, :))/nsin;
end;
w = [1; 2*ones(nsin/2-1,1); ones(1 - rem(nsin,2),1); zeros(nsin/2-1,1)]';
for mm=1:nharm
x_rc = real(ifft(log(abs(fft(blitm(mm, :))))));
y = real(ifft(exp(fft(w.*x_rc))));
minblepm(mm, :) = cumsum(y)/nsin;
end;
x = 0;
x2 = 0;
z = 0;
f = fstart;
f2 = f2start;
tri = 0;
NLG = 2;
h = lagrange(1, 0.35)
startup = 1;
blep = 1;
for n = 1:L,
if x >= 1 || startup,
x = 0;
p = fs/f;
dx = 1.0/p;
m = min(fix((p/2.0)) + 1, nharm_max);
blep_offset = 0;
blep_gain = 1;
z = ~z;
end;
if x2 >= 1 || startup,
x2 =0;
dx2 = f2/fs;
% blep_offset = -(1-x);
% blep_gain = x;
% x = 0;
% z = ~z;
end;
startup = 0;
nn = (x+0.0)*(nsin-1) + 1;
ni = fix(nn);
nf = nn - ni;
h = lagrange(NLG, nf);
blep = h(NLG+1)*minblepm(m, max(1, ni));
j = 1;
for i = NLG:-1:1
blep = blep + h(i)*minblepm(m, max(1, ni-j));
j = j + 1;
end;
saw = x - blep_gain*blep + blep_offset;
if (z == 0)
sqr = blep;
else
sqr = 1-blep;
end
tri = tri + 2*(sqr-0.5)*dx;
vsqr(n) = 0.5*(sqr-0.5);
vtri(n) = tri;
vsaw(n,1) = x;
vsaw(n,2) = saw+0.5;
vblep(n,1) = x;
vblep(n,2) = blep;
x = x + dx;
f = f + df;
x2 = x2 + dx2;
f2 = f2 + df2;
end;
close all
plot(1:nsin, blepm(fix(nharm/2), :), 1:nsin, minblepm(fix(nharm/2), :)); grid;
wavwrite(0.5*vtri, fs, 'tri.wav');
wavwrite(0.5*vsqr, fs, 'sqr.wav');
wavwrite(0.5*vsaw, fs, 'saw.wav');
wavwrite(0.5*vblep, fs, 'blep.wav');
function h = lagrange(N, delay)
%LAGRANGE h=lagrange(N,delay) returns order N FIR
% filter h which implements given delay
% (in samples). For best results,
% delay should be near N/2 +/- 1.
n = 0:N;
h = ones(1,N+1);
for k = 0:N
index = find(n ~= k);
h(index) = h(index) * (delay-k)./ (n(index)-k);
end
+116
View File
@@ -0,0 +1,116 @@
function eval_minblep()
nsin = 4096;
nharm_max = 1800;
L = 48000/2;
fs = 48000;
fstart = 440;
fend = 440;
df = (fend-fstart)/L
f2start = 200;
f2end = 600;
df2 = (f2end-f2start)/L
saw = 0;
% Calc blep table
nharm = min(fix((fs/fstart/2.0)) + 1, nharm_max)
Hw = kaiser(nsin, 8);
xx = (0:nsin-1)/nsin - 0.5;
for mm=1:nharm
blitm(mm,:) = sin(xx*(mm-1)*pi)./sin(xx*pi).*Hw';
blitm(mm,(find(isnan(blitm(mm,:))))) = (mm-1);
end;
for mm=1:nharm
blepm(mm, :) = cumsum(blitm(mm, :))/nsin;
end;
w = [1; 2*ones(nsin/2-1,1); ones(1 - rem(nsin,2),1); zeros(nsin/2-1,1)]';
for mm=1:nharm
x_rc = real(ifft(log(abs(fft(blitm(mm, :))))));
y = real(ifft(exp(fft(w.*x_rc))));
minblepm(mm, :) = cumsum(y)/nsin;
end;
x = 0;
x2 = 0;
z = 0;
f = fstart;
f2 = f2start;
tri = 0;
NLG = 2;
h = lagrange(1, 0.35)
startup = 1;
blep = 1;
for n = 1:L,
if x >= 1 || startup,
x = 0;
p = fs/f;
dx = 1.0/p;
m = min(fix((p/2.0)) + 1, nharm_max);
blep_offset = 0;
blep_gain = 1;
z = ~z;
end;
if x2 >= 1 || startup,
x2 =0;
dx2 = f2/fs;
% blep_offset = -(1-x);
% blep_gain = x;
% x = 0;
% z = ~z;
end;
startup = 0;
nn = (x+0.0)*(nsin-1) + 1;
ni = fix(nn);
nf = nn - ni;
h = lagrange(NLG, nf);
blep = h(NLG+1)*minblepm(m, max(1, ni));
j = 1;
for i = NLG:-1:1
blep = blep + h(i)*minblepm(m, max(1, ni-j));
j = j + 1;
end;
saw = x - blep_gain*blep + blep_offset;
if (z == 0)
sqr = blep;
else
sqr = 1-blep;
end
vsqr(n) = 0.5*(sqr-0.5);
tri = tri + 2*(sqr-0.5)*dx;
vtri(n) = tri;
vsaw(n,1) = x;
vsaw(n,2) = saw+0.5;
vblep(n,1) = x;
vblep(n,2) = blep;
x = x + dx;
f = f + df;
x2 = x2 + dx2;
f2 = f2 + df2;
end;
close all
plot(1:nsin, blepm(fix(nharm/2), :), 1:nsin, minblepm(fix(nharm/2), :)); grid;
wavwrite(0.5*vtri, fs, 'tri.wav');
wavwrite(0.5*vsqr, fs, 'sqr.wav');
wavwrite(0.5*vsaw, fs, 'saw.wav');
wavwrite(0.5*vblep, fs, 'blep.wav');
function h = lagrange(N, delay)
%LAGRANGE h=lagrange(N,delay) returns order N FIR
% filter h which implements given delay
% (in samples). For best results,
% delay should be near N/2 +/- 1.
n = 0:N;
h = ones(1,N+1);
for k = 0:N
index = find(n ~= k);
h(index) = h(index) * (delay-k)./ (n(index)-k);
end
+33
View File
@@ -0,0 +1,33 @@
function eval_minblep_pre()
f = 440;
N = 4000;
t = (-N/2:N/2-1)/N;
x = sin(t*f*pi)./sin(t*pi); .* kaiser(N, 8)';
x(find(isnan(x))) = f;
%x = x / f;
% Real cepstrum
x_rc = real(ifft(log(abs(fft(x)))));
w = [1; 2*ones(N/2-1,1); ones(1 - rem(N,2),1); zeros(N/2-1,1)]';
y = real(ifft(exp(fft(w.*x_rc))));
xi = cumsum(x)/N;
yi = cumsum(y)/N;
close all;
subplot(2, 1, 1)
plot(t, x/f, t, xi, 'r'); grid;
subplot(2, 1, 2)
plot(0:N-1, y/f, 0:N-1, yi, 'r'); grid;
figure;
plot(t, xi); grid;
figure;
plot(t, yi); grid;
figure;
plot(w); grid;
+33
View File
@@ -0,0 +1,33 @@
function eval_minblep_pre()
f = 440;
N = 4000;
t = (-N/2:N/2-1)/N;
x = sin(t*f*pi)./sin(t*pi);% .* kaiser(N, 8)';
x(find(isnan(x))) = f;
%x = x / f;
% Real cepstrum
x_rc = real(ifft(log(abs(fft(x)))));
w = [1; 2*ones(N/2-1,1); ones(1 - rem(N,2),1); zeros(N/2-1,1)]';
y = real(ifft(exp(fft(w.*x_rc))));
xi = cumsum(x)/N;
yi = cumsum(y)/N;
close all;
subplot(2, 1, 1)
plot(t, x/f, t, xi, 'r'); grid;
subplot(2, 1, 2)
plot(0:N-1, y/f, 0:N-1, yi, 'r'); grid;
figure;
plot(t, xi); grid;
figure;
plot(t, yi); grid;
figure;
plot(w); grid;
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+96
View File
@@ -0,0 +1,96 @@
function eval_blep()
nsin = 2048;
nharm_max = 1800;
L = 48000;
fs = 48000;
fstart = 110;
fend = 110;
df = (fend-fstart)/L
% Calc blep table
nharm = min(fix((fs/fstart/2.0)) + 1, nharm_max)
Hw = kaiser(nsin, 8);
xx = (0:nsin-1)/nsin - 0.5;
for mm=1:nharm,
bb(mm, :) = sin((mm-1)*xx*pi);
end;
aa = sin(xx*pi);
for mm=1:nharm
for nn=1:length(xx)
if (aa(nn) == 0)
blitm(mm,nn) = (mm-1);
else
blitm(mm,nn) = bb(mm, nn)/aa(nn).*Hw(nn);
end
end
end;
for mm=1:nharm
blepm(mm, :) = cumsum(blitm(mm, :))/nsin;
end;
%blep2 = blepm(nharm_max/2+1, :)'
%aa2 = aa(:)'
%bb2 = bb(nharm_max/2+1, :)'
x = 0.5;
z = 0;
f = fstart;
tri = 0;
for n = 1:L,
if x >= 0.5,
x = x - 1;
p = fs/f;
dx = 1.0/p;
m = min(fix((p/2.0)) + 1, nharm_max);
z = ~z;
end;
nn = (x+0.5)*(nsin-1) + 1;
ni = fix(nn);
nf = nn - ni;
h = lagrange(1, nf);
% blep = (blepm(m, min(ni+1, nsin)) - blepm(m, ni))*nf + blepm(m, ni);
[blep, Zi] = filter(h, 1, blepm(m
blep = h(1)*blepm(m, max(1, ni-1)) + h(2)*blepm(m, ni);
saw = x - blep;
if (z == 0)
sqr = blep;
else
sqr = 1-blep;
end
tri = tri + 2*(sqr-0.5)*dx;
vtri(n) = tri;
vsaw(n) = saw+0.5;
vsqr(n) = 0.5*(sqr-0.5);
vblep(n) = blep;
x = x + dx;
f = f + df;
end;
close all
plot(1:nsin, blepm(fix(nharm/2), :)); grid;
wavwrite(0.5*vtri, fs, 'tri.wav');
wavwrite(0.5*vsqr, fs, 'sqr.wav');
wavwrite(0.5*vsaw, fs, 'saw.wav');
wavwrite(0.5*vblep, fs, 'blep.wav');
function h = lagrange(N, delay)
%LAGRANGE h=lagrange(N,delay) returns order N FIR
% filter h which implements given delay
% (in samples). For best results,
% delay should be near N/2 +/- 1.
n = 0:N;
h = ones(1,N+1);
for k = 0:N
index = find(n ~= k);
h(index) = h(index) * (delay-k)./ (n(index)-k);
end
+90
View File
@@ -0,0 +1,90 @@
function eval_blep()
nsin = 4096;
nharm_max = 1800;
L = 48000/2;
fs = 48000;
fstart = 440;
fend = 440;
df = (fend-fstart)/L
% Calc blep table
nharm = min(fix((fs/fstart/2.0)) + 1, nharm_max)
Hw = kaiser(nsin, 8);
xx = (0:nsin-1)/nsin - 0.5;
for mm=1:nharm
blitm(mm,:) = sin(xx*(mm-1)*pi)./sin(xx*pi).*Hw';
blitm(mm,(find(isnan(blitm(mm,:))))) = (mm-1);
end;
for mm=1:nharm
blepm(mm, :) = cumsum(blitm(mm, :))/nsin;
end;
x = 0.0;
z = 0;
f = fstart;
tri = 0;
NLG = 2;
h = lagrange(1, 0.35)
startup = 1;
for n = 1:L,
if x >= 0.5 || startup;
x = x - 1;
p = fs/f;
dx = 1.0/p;
m = min(fix((p/2.0)) + 1, nharm_max);
z = ~z;
end;
startup = 0;
nn = (x+0.5)*(nsin-1) + 1;
ni = fix(nn);
nf = nn - ni;
h = lagrange(NLG, nf);
blep = h(NLG+1)*blepm(m, max(1, ni));
j = 1;
for i = NLG:-1:1
blep = blep + h(i)*blepm(m, max(1, ni-j));
j = j + 1;
end;
saw = x - blep;
if (z == 0)
sqr = blep;
else
sqr = 1-blep;
end
vsqr(n) = 0.5*(sqr-0.5);
tri = tri + 2*(sqr-0.5)*dx;
vtri(n) = tri;
vsaw(n,1) = x;
vsaw(n,2) = saw+0.5;
vblep(n,1) = x;
vblep(n,2) = blep;
x = x + dx;
f = f + df;
end;
close all
plot(1:nsin, blepm(fix(nharm/2), :)); grid;
wavwrite(0.5*vtri, fs, 'tri.wav');
wavwrite(0.5*vsqr, fs, 'sqr.wav');
wavwrite(0.5*vsaw, fs, 'saw.wav');
wavwrite(0.5*vblep, fs, 'blep.wav');
function h = lagrange(N, delay)
%LAGRANGE h=lagrange(N,delay) returns order N FIR
% filter h which implements given delay
% (in samples). For best results,
% delay should be near N/2 +/- 1.
n = 0:N;
h = ones(1,N+1);
for k = 0:N
index = find(n ~= k);
h(index) = h(index) * (delay-k)./ (n(index)-k);
end
+105
View File
@@ -0,0 +1,105 @@
function eval_blep_hs()
nsin = 1024;
nharm_max = 1800;
L = 48000;
fs = 48000;
fstart = 44;
fend = 44;
df = (fend-fstart)/L
% Calc blep table
nharm = min(fix((fs/fstart/2.0)) + 1, nharm_max)
Hw = kaiser(nsin, 8);
xx = (0:nsin-1)/nsin - 0.5;
for mm=1:nharm,
bb(mm, :) = sin((mm-1)*xx*pi);
end;
aa = sin(xx*pi);
for mm=1:nharm
for nn=1:length(xx)
if (aa(nn) == 0)
blitm(mm,nn) = (mm-1);
else
blitm(mm,nn) = bb(mm, nn)/aa(nn).*Hw(nn);
end
end
end;
for mm=1:nharm
blepm(mm, :) = cumsum(blitm(mm, :))/nsin;
end;
%blep2 = blepm(nharm_max/2+1, :)'
%aa2 = aa(:)'
%bb2 = bb(nharm_max/2+1, :)'
x = 0.5;
x2 = 0.5;
z = 0;
f = fstart;
tri = 0;
NLG = 2;
h = lagrange(1, 0.35)
for n = 1:L,
if x >= 0.5,
x = x - 1;
p = fs/f;
dx = 1.0/p;
m = min(fix((p/2.0)) + 1, nharm_max);
z = ~z;
end;
nn = (x+0.5)*(nsin-1) + 1;
ni = fix(nn);
nf = nn - ni;
h = lagrange(NLG, nf);
% blep = (blepm(m, min(ni+1, nsin)) - blepm(m, ni))*nf + blepm(m, ni);
% blep = h(1)*blepm(m, max(1, ni-3)) + h(2)*blepm(m, max(1, ni-2)) + h(3)*blepm(m, max(1, ni-1)) + h(4)*blepm(m, max(1, ni));
blep = h(NLG+1)*blepm(m, max(1, ni));
j = 1;
for i = NLG:-1:1
blep = blep + h(i)*blepm(m, max(1, ni-j));
j = j + 1;
end;
saw = x - blep;
if (z == 0)
sqr = blep;
else
sqr = 1-blep;
end
tri = tri + 2*(sqr-0.5)*dx;
vtri(n) = tri;
vsaw(n) = saw+0.5;
vsqr(n) = 0.5*(sqr-0.5);
vblep(n) = blep;
x = x + dx;
f = f + df;
end;
close all
plot(1:nsin, blepm(fix(nharm/2), :)); grid;
wavwrite(0.5*vtri, fs, 'tri.wav');
wavwrite(0.5*vsqr, fs, 'sqr.wav');
wavwrite(0.5*vsaw, fs, 'saw.wav');
wavwrite(0.5*vblep, fs, 'blep.wav');
function h = lagrange(N, delay)
%LAGRANGE h=lagrange(N,delay) returns order N FIR
% filter h which implements given delay
% (in samples). For best results,
% delay should be near N/2 +/- 1.
n = 0:N;
h = ones(1,N+1);
for k = 0:N
index = find(n ~= k);
h(index) = h(index) * (delay-k)./ (n(index)-k);
end
+145
View File
@@ -0,0 +1,145 @@
function eval_blep_hs()
nsin = 1024;
nharm_max = 256;
L = 4800;
fs = 48000;
fstart = 44;
fend = 44;
df = (fend-fstart)/L
% Calc blep table
nharm = min(fix((fs/fstart/2.0)) + 1, nharm_max)
Hw = kaiser(nsin, 8);
xx = (0:nsin-1)/nsin - 0.5;
for mm=1:nharm,
bb(mm, :) = sin((mm-1)*xx*pi);
end;
aa = sin(xx*pi);
for mm=1:nharm
for nn=1:length(xx)
if (aa(nn) == 0)
blitm(mm,nn) = (mm-1);
else
blitm(mm,nn) = bb(mm, nn)/aa(nn).*Hw(nn);
end
end
end;
for mm=1:nharm
blepm(mm, :) = cumsum(blitm(mm, :))/nsin;
end;
%blep2 = blepm(nharm_max/2+1, :)'
%aa2 = aa(:)'
%bb2 = bb(nharm_max/2+1, :)'
x = 0.0;
x2 = -0.5;
z = 0;
f = fstart;
f2 = 0.6*f;
dx2 = f2/fs;
tri = 0;
NLG = 2;
h = lagrange(1, 0.35)
sync = 0;
restart = 0;
startup = 1;
minblep_active = 0;
minblep_count = 0;
minblep_length = 200;
minblep = 1-(0:minblep_length-1)/minblep_length;
for n = 1:L,
sync = 0;
if startup,
x = 0.0;
startup = 0;
p = fs/f;
dx = 1.0/p;
m = min(fix((p/2.0)) + 1, nharm_max);
z = 0;
end;
if (x >= 0.5),
x = x - 1;
p = fs/f;
dx = 1.0/p;
m = min(fix((p/2.0)) + 1, nharm_max);
z = ~z;
end;
if (x2 >= 0.5),
x2 = x2 - 1;
sync = 1;
startup = 1;
minblep_count = minblep_length;
end;
nn = (x+0.5)*(nsin-1) + 1;
ni = fix(nn);
nf = nn - ni;
h = lagrange(NLG, nf);
blep = h(NLG+1)*blepm(m, max(1, ni));
j = 1;
for i = NLG:-1:1
blep = blep + h(i)*blepm(m, max(1, ni-j));
j = j + 1;
end;
if (minblep_count > 0)
saw = saw_last - minblep(minblep_count)/(1-2*saw_last+minblep_length*dx);
minblep_count = minblep_count - 1;
minblep_active = 1;
else
minblep_active = 0;
saw = x - blep;
saw_last = saw;
end
if (z == 0)
sqr = blep;
else
sqr = 1-blep;
end
tri = tri + 2*(sqr-0.5)*dx;
vtri(n) = tri;
vsaw(n) = 2*(saw+0.5);
vsqr(n) = 0.5*(sqr-0.5);
vblep(n) = blep;
vx(n) = x;
vsync(n) = sync;
vminblep_active(n) = minblep_active;
x2 = x2 + dx2;
x = x + dx;
f = f + df;
end;
close all
plot(1:nsin, blepm(fix(nharm/2), :)); grid;
figure;
subplot(3, 1, 1)
plot(1:L, vx, 1:L, vsync, 'r'); grid;
subplot(3, 1, 2)
plot(1:L, vblep); grid;
subplot(3, 1, 3)
plot(1:L, vsaw, 1:L, vminblep_active); grid;
wavwrite(0.5*vtri, fs, 'tri.wav');
wavwrite(0.5*vsqr, fs, 'sqr.wav');
wavwrite(0.5*vsaw, fs, 'saw.wav');
wavwrite(0.5*vblep, fs, 'blep.wav');
function h = lagrange(N, delay)
%LAGRANGE h=lagrange(N,delay) returns order N FIR
% filter h which implements given delay
% (in samples). For best results,
% delay should be near N/2 +/- 1.
n = 0:N;
h = ones(1,N+1);
for k = 0:N
index = find(n ~= k);
h(index) = h(index) * (delay-k)./ (n(index)-k);
end
+103
View File
@@ -0,0 +1,103 @@
function eval_blit()
sinc_use_lut = 1
L = 40000;
fs = 48000;
fstart = 110;
fend = 1100;
df = (fend-fstart)/L;
nhw = 4096;
Hw = kaiser(nhw, 8)';
if sinc_use_lut == 1
nharm = 512;
nsin = 4096;
xx = (0:nsin)/nsin - 0.5;
mmm=0;
for mm=1:nharm,
mmm=mmm+1;
bb(mm, :) = sin(mmm*xx*pi);
end;
aa = sin(xx*pi);
end;
sinc_m(mm, find(aa == 0)) = 1;
x = 0.5;
z = -1;
f = fstart;
sqr = 0.0;
c4 = 0;
a = 1;
b = 1;
for n = 1:L,
if x >= 0.5,
x = x - 1;
p = fs/f;
fraq = 1.0/p;
m = fix((p/2.0)) + 1;
saw = 0.0;
c3 = 0.0;
z = -z;
end;
if sinc_use_lut == 1
nn = (x+0.5)*nsin + 1;
ni = fix(nn);
nf = nn - ni;
bbi = (bb(m, ni+1) - bb(m, ni))*nf + bb(m, ni); % Fractional delay (linear interpolation)
aai = (aa(ni+1) - aa(ni))*nf + aa(ni); % Fractional delay (linear interpolation)
if (aai ~= 0)
blit = fraq* bbi / aai * Hw(fix((x+0.5)*nhw)+1);
else
blit = fraq;
end
else
b = sin(m*x*pi);
a = sin(x*pi);
if (a ~= 0)
blit = fraq * b/a * Hw(fix((x+0.5)*nhw)+1);
else
blit = fraq;
end
end
saw = saw + blit;
sqr = sqr + z*blit;
vsaw(n) = 2*(saw - c3);
vsqr(n) = 2*(sqr - 0.5);
vblit(n) = blit;
vc3(n) = b;
x = x + fraq;
c3 = c3 + fraq;
f = f + df;
c4 = c4 + fraq - blit;
vc4(n) = a;
end;
close all
figure;
plot(1:L, vsaw, 1:L, vc4, 1:L, vblit); grid;
figure;
plot(vc4); grid;
figure;
plot(vc3); grid;
if sinc_use_lut == 1
figure;
plot(sinc_m(nharm, :)); grid;
end;
wavwrite(0.5*vc4, fs, 'c4.wav');
wavwrite(0.5*vc3, fs, 'c3.wav');
wavwrite(0.5*vsqr, fs, 'sqr.wav');
wavwrite(0.5*vsaw, fs, 'saw.wav');
wavwrite(0.5*vblit, fs, 'blit.wav');
+116
View File
@@ -0,0 +1,116 @@
function eval_blit()
Nb = 33;
Nos = 1000;
fs = 48000;
f = 440;
fcut = 16000;
P = fs/f
Pi = floor(P)
Pf = fix(Nos*(fs/f - Pi))
x = (0:Nb*Nos-1) - (Nb*Nos-1)/2;
H = sinc(2*fcut/fs.*x/Nos).*Kaiser(Nos*Nb, 8)';
for ii=0:Nos-1,
for jj=0:Nb-1
Hs(ii+1,jj+1) = H(Nos-ii+Nos*jj);
end
end;
%Hs = init_steps(Nb, Nos);
k = 1./sum(Hs');
%k = ones(1, Nb);
y0 = 0;
y1 = 0;
y2 = .5;
ks = 0.002*f/55
ii = 0;
ff = 0;
nn = 1;
jj = Nb;
kk = 1;
for i = 1:32000,
if ii == 0
jj = 1;
kk = ff + 1;
ii = Pi;
ff = ff + Pf;
if ff > (Nos-1)
ff = ff - Nos;
ii = ii + 1;
end
end;
ii = ii - 1;
if jj <= Nb
y0 = y0 + k(kk)*Hs(kk,jj); % - ks*y0;
jj = jj + 1;
end;
y0 = y0 - ks*y0;
y1 = 1 - y0;
y2 = 0.001*y1 + 0.999*y2;
blit(nn) = y1-y2;
nn = nn + 1;
end;
wavwrite(0.7*blit, fs, 'blit.wav');
for ii = 1:Nos
step(ii,:) = k(ii).*filter(Hs(ii,:), 1, [ones(1,Nb)]);
end
close all
plot(1:length(blit), blit, '-o'); grid;
figure
plot(abs(fft(blit))); grid;
figure
plot(step', '-'); grid;
figure
plot(Hs(1,:)', '-+'); grid;
function steps = init_steps(step_width, phase_count)
low_pass = 0.999; % lower values filter more high frequency
high_pass = 0.990; % lower values filter more low frequency
%phase_count = 32; % number of phase offsets to sample band-limited step at
%step_width = 16; % number of samples in each final band-limited step
%steps [phase_count] [step_width]; // would use short for speed in a real program
% Generate master band-limited step by adding sine components of a square wave
master_size = step_width * phase_count;
% master [master_size]; // large; might want to malloc() instead
for i = 0:master_size-1
master(i+1) = 0.5;
end;
gain = 0.5 / 0.777; % adjust normal square wave's amplitude of ~0.777 to 0.5
sine_size = 256 * phase_count + 2;
max_harmonic = sine_size / 2 / phase_count;
for h = 1:2:max_harmonic
amplitude = gain / h;
to_angle = 3.14159265358979323846 * 2 / sine_size * h;
for i = 0:master_size-1
master(i+1) = master(i+1) + sin( (i - master_size / 2) * to_angle ) * amplitude;
end
gain = gain * low_pass;
end
% Sample master step at several phases
for phase = 0:phase_count-1
error = 1.0;
prev = 0.0;
for i = 0:step_width-1
cur = master (i * phase_count + (phase_count - 1 - phase)+1);
delta = cur - prev;
error = error - delta;
prev = cur;
steps (phase+1, i+1) = delta;
end
% each delta should total 1.0
steps (phase+1, step_width / 2) = steps (phase+1, step_width / 2) + error * 0.5;
steps (phase+1, step_width / 2 + 1) = steps (phase+1, step_width / 2 + 1) + error * 0.5;
end
+90
View File
@@ -0,0 +1,90 @@
function eval_blit()
sinc_use_lut = 1
L = 96000;
fs = 48000;
fstart = 220;
fend = 880;
df = (fend-fstart)/L
# for saw
rho = 1.0;
nhw = 4096;
Hw = kaiser(nhw, 8)';
max_m = fix((fs/fstart/2.0)) + 1
if sinc_use_lut == 1
nharm = max_m
nsin = 1024;
xx = (0:nsin)/nsin - 0.5;
mmm=0;
for mm=1:nharm,
mmm=mmm+1;
bb(mm, :) = sin(mmm*xx*pi);
end;
aa = sin(xx*pi);
end;
x = 0.5;
z = -1;
f = fstart;
sqr = 0.0;
saw = 0.0;
tri = 0.0;
a = 1;
b = 1;
for n = 1:L,
if x >= 0.5,
x = x - 1;
p = fs/f;
fraq = 1.0/p;
m = fix((p/2.0)) + 1;
z = -z;
end;
if sinc_use_lut == 1
nn = (x+0.5)*nsin + 1;
ni = fix(nn);
nf = nn - ni;
b = (bb(m, ni+1) - bb(m, ni))*nf + bb(m, ni); % Fractional delay (linear interpolation)
a = (aa(ni+1) - aa(ni))*nf + aa(ni); % Fractional delay (linear interpolation)
else
b = sin(m*x*pi);
a = sin(x*pi);
end
if (a ~= 0)
blit = fraq * b/a * Hw(fix((x+0.5)*nhw)+1);
else
blit = fraq;
end
saw = rho*saw + (fraq - blit);
sqr = sqr + z*blit;
tri = tri + 2*(sqr-0.5)*fraq;
vtri(n) = tri;
vsaw(n) = saw;
vsqr(n) = 2*(sqr - 0.5);
vblit(n) = blit;
x = x + fraq;
f = f + df;
end;
close all
figure;
plot(1:L, vsaw, 1:L, vblit); grid;
N_UNDC = fs/100;
a, b = undcc(N_UNDC);
wavwrite(0.5*filter(b, a, vtri), fs, 'tri.wav');
wavwrite(0.5*filter(b, a, vsqr), fs, 'sqr.wav');
wavwrite(0.5*filter(b, a, vsaw), fs, 'saw.wav');
wavwrite(0.5*vblit, fs, 'blit.wav');
+128
View File
@@ -0,0 +1,128 @@
function eval_blit2()
L = 64000;
Nb = 65;
Nos = 8;
fs = 48000;
fstart = 440;
fend = 1760;
df = (fend-fstart)/L
fcut = 16000;
x = (0:Nb*Nos-1) - (Nb*Nos-1)/2;
H = sinc(2*fcut/fs.*x/Nos).*kaiser(Nos*Nb, 8)';
for ii=0:Nos-1,
for jj=0:Nb-1
Hs(ii+1,jj+1) = H(Nos-ii+Nos*jj);
end
end;
%Hs = init_steps(Nb, Nos);
f = fstart;
k = 1./sum(Hs')
%k = ones(1, Nb);
y0 = 0;
y1 = 0;
y2 = .5;
ks = 0.002*f/55
ii = 0;
ff = 0;
nn = 1;
jj = Nb;
kk = 1;
for i = 1:L,
P = fs/f;
Pi = floor(P);
Pf = fix(Nos*(fs/f - Pi));
if ii == 0
jj = 1;
kk = ff + 1;
ii = Pi;
ff = ff + Pf;
if ff > (Nos-1)
ff = ff - Nos;
ii = ii + 1;
end
end;
ii = ii - 1;
if jj <= Nb
y0 = k(kk)*Hs(kk,jj); % - ks*y0;
jj = jj + 1;
end;
y0 = y0 - ks*y0;
y1 = 1 - y0;
y2 = 0.001*y1 + 0.999*y2;
blit(nn) = y1-y2; % DC removal
nn = nn + 1;
f = f + df;
end;
wavwrite(0.7*blit, fs, 'blit.wav');
for ii = 1:Nos
step(ii,:) = k(ii).*filter(Hs(ii,:), 1, [ones(1,Nb)]);
end
DC = y2
close all
plot(H); grid;
figure
plot(1:length(blit), blit, '-o'); grid;
figure
plot(abs(fft(blit))); grid;
figure
plot(step', '-'); grid;
figure
plot(Hs(1,:)', '-+'); grid;
function steps = init_steps(step_width, phase_count)
low_pass = 0.999; % lower values filter more high frequency
high_pass = 0.990; % lower values filter more low frequency
%phase_count = 32; % number of phase offsets to sample band-limited step at
%step_width = 16; % number of samples in each final band-limited step
%steps [phase_count] [step_width]; // would use short for speed in a real program
% Generate master band-limited step by adding sine components of a square wave
master_size = step_width * phase_count;
% master [master_size]; // large; might want to malloc() instead
for i = 0:master_size-1
master(i+1) = 0.5;
end;
gain = 0.5 / 0.777; % adjust normal square wave's amplitude of ~0.777 to 0.5
sine_size = 256 * phase_count + 2;
max_harmonic = sine_size / 2 / phase_count;
for h = 1:2:max_harmonic
amplitude = gain / h;
to_angle = 3.14159265358979323846 * 2 / sine_size * h;
for i = 0:master_size-1
master(i+1) = master(i+1) + sin( (i - master_size / 2) * to_angle ) * amplitude;
end
gain = gain * low_pass;
end
% Sample master step at several phases
for phase = 0:phase_count-1
error = 1.0;
prev = 0.0;
for i = 0:step_width-1
cur = master (i * phase_count + (phase_count - 1 - phase)+1);
delta = cur - prev;
error = error - delta;
prev = cur;
steps (phase+1, i+1) = delta;
end
% each delta should total 1.0
steps (phase+1, step_width / 2) = steps (phase+1, step_width / 2) + error * 0.5;
steps (phase+1, step_width / 2 + 1) = steps (phase+1, step_width / 2 + 1) + error * 0.5;
end
+68
View File
@@ -0,0 +1,68 @@
function eval_blit3()
L = 64000;
Nb = 137;
Nphases = 256;
fs = 48000;
fstart = 110*4;
fend = 110*4;
df = (fend-fstart)/L;
fcut = 16000;
x = (0:Nb*Nphases-1) - (Nb*Nphases-1)/2;
H = sinc(2*fcut/fs.*x/Nphases);%.*kaiser(Nphases*Nb, 8)';
Hw = kaiser(Nb, 18)';
for ii=0:Nphases-1,
for jj=0:Nb-1
Hs(ii+1,jj+1) = H(Nphases-ii+Nphases*jj);
end
end;
f = fstart;
Pic = 1;
blit(1:L) = zeros(1, L);
blit_bp(1:L) = zeros(1, L);
pol = 1;
for n = Nb:L,
P = fs/f;
Pi = floor(P);
Pf = 1+fix(Nphases*(P - Pi));
if Pic >= Pi,
blit(n-Nb+1:n) = blit(n-Nb+1:n) + Hs(Pf,:).*Hw;
blit_bp(n-Nb+1:n) = blit_bp(n-Nb+1:n) + pol*Hs(Pf,:).*Hw;
Pic = 0;
pol = -pol;
end;
Pic = Pic + 1;
f = f + df;
end;
mean_blit = 0.0034;
mean_saw = 0.00;
saw(1:L) = zeros(1, L);
sqr(1:L) = zeros(1, L);
y_saw = 0;
y_sqr = 0;
for n = 2:L,
y_saw = y_saw + blit(n)-mean_blit;
y_sqr = y_sqr + blit_bp(n);
saw(n) = -y_saw -1;
sqr(n) = y_sqr;
end;
saw_nodc = filter([1 -1], [1 -0.995], saw);
sqr_nodc = filter([1 -1], [1 -0.995], sqr);
close all;
plot(saw); grid;
figure;
plot(saw_nodc); grid;
wavwrite(0.8*blit, fs, 'blit.wav');
wavwrite(0.7*saw_nodc, fs, 'saw.wav');
wavwrite(0.5*sqr_nodc, fs, 'sqr.wav');
+92
View File
@@ -0,0 +1,92 @@
function eval_blit()
sinc_use_lut = 0
L = 40000;
fs = 48000;
fstart = 110;
fend = 1550;
df = (fend-fstart)/L;
nhw = 4096;
Hw = kaiser(nhw, 8)';
ya = zeros(3,1);
yb = zeros(3,1);
x = 0.5;
z = -1;
f = fstart;
sqr = 0.0;
c4 = 0;
for n = 1:L,
if x >= 0.5,
x = x - 1;
p = fs/f;
fraq = 1.0/p;
m = fix((p/2.0)) + 1;
saw = 0.0;
c3 = 0.0;
z = -z;
ip = 0; % phase of the first output sample in radians
w = f*pi / fs
ba1 = 2.0 * cos(w)
bb1 = 2.0 * cos(w)
end;
if sinc_use_lut == 1
xi = fix((x+0.5)*nsin)+1
if aa(xi) ~= 0
blit = fraq*sinc_m(m, xi) * Hw(fix((x+0.5)*nhw)+1);;
else
blit = fraq;
end
else
b = fraq*sin(m*x*pi);
a = sin(x*pi);
if (a ~= 0)
blit = b/a * Hw(fix((x+0.5)*nhw)+1);
else
blit = fraq;
end
end
saw = saw + blit;
sqr = sqr + z*blit;
vsaw(n) = 2*(saw - c3);
vsqr(n) = 2*(sqr - 0.5);
vblit(n) = blit;
vc3(n) = c3;
x = x + fraq;
c3 = c3 + fraq;
f = f + df;
c4 = c4 + fraq - blit;
vc4(n) = c4;
end;
close all
figure;
plot(1:L, vsaw, 1:L, vc4, 1:L, vblit); grid;
figure;
plot(vblit); grid;
figure;
plot(vc3); grid;
if sinc_use_lut == 1
figure;
plot(sinc_m(nharm, :)); grid;
end;
wavwrite(0.5*vc4, fs, 'c4.wav');
wavwrite(0.5*vc3, fs, 'c3.wav');
wavwrite(0.5*vsqr, fs, 'sqr.wav');
wavwrite(0.5*vsaw, fs, 'saw.wav');
wavwrite(0.5*vblit, fs, 'blit.wav');
+88
View File
@@ -0,0 +1,88 @@
function eval_blit4()
L = 4000;
fs = 48000;
fstart = 110;
fend = 110;
df = (fend-fstart)/L;
nhw = 4096;
Hw = kaiser(nhw, 8)';
ya = zeros(3,1);
yb = zeros(3,1);
x = 0.5;
z = -1;
f = fstart;
sqr = 0.0;
c4 = 0;
for n = 1:L,
if x >= 0.5,
x = x - 1;
p = fs/f;
fraq = 1.0/p;
m = fix((p/2.0)) + 1
saw = 0.0;
c3 = 0.0;
z = -z;
ip = -pi/2; % phase of the first output sample in radians
w = f*pi / fs;
ba1 = 2.0 * cos(w);
bb1 = 2.0 * cos(m*w);
ya(2)=sin(ip-w);
ya(3)=sin(ip-2*w);
yb(2)=sin(ip-m*w);
yb(3)=sin(ip-2*m*w);
end;
ya(1) = ba1*ya(2) - ya(3);
ya(3) = ya(2);
ya(2) = ya(1);
yb(1) = bb1*yb(2) - yb(3);
yb(3) = yb(2);
yb(2) = yb(1);
b = fraq*yb(1);
a = ya(1);
if (a ~= 0)
blit = b/a * Hw(fix((x+0.5)*nhw)+1);
else
blit = fraq;
end
saw = saw + blit;
sqr = sqr + z*blit;
vsaw(n) = 2*(saw - c3);
vsqr(n) = 2*(sqr - 0.5);
vblit(n) = blit;
vc3(n) = b;
x = x + fraq;
c3 = c3 + fraq;
f = f + df;
c4 = c4 + fraq - blit;
vc4(n) = a;
end;
close all
figure;
plot(1:L, vsaw, 1:L, vc4, 1:L, vblit); grid;
figure;
plot(vc4); grid;
figure;
plot(vc3); grid;
wavwrite(0.5*vc4, fs, 'c4.wav');
wavwrite(0.5*vc3, fs, 'c3.wav');
wavwrite(0.5*vsqr, fs, 'sqr.wav');
wavwrite(0.5*vsaw, fs, 'saw.wav');
wavwrite(0.5*vblit, fs, 'blit.wav');
+125
View File
@@ -0,0 +1,125 @@
function eval_hardsync()
nsin = 4096;
nharm_max = 1800;
L = 48000/2;
fs = 48000;
fstart = 440;
fend = 440;
df = (fend-fstart)/L
f2start = 400;
f2end = 400;
df2 = (f2end-f2start)/L
% Calc blep table
nharm = min(fix((fs/min(fstart, f2start)/2.0)) + 1, nharm_max)
Hw = kaiser(nsin, 8);
xx = (0:nsin-1)/nsin - 0.5;
for mm=1:nharm
blitm(mm,:) = sin(xx*(mm-1)*pi)./sin(xx*pi).*Hw';
blitm(mm,(find(isnan(blitm(mm,:))))) = (mm-1);
end;
for mm=1:nharm
blepm(mm, :) = cumsum(blitm(mm, :))/nsin;
end;
x = 0.0;
x2 = 0.0;
z = 0;
f = fstart;
f2 = f2start;
tri = 0;
saw = 0;
NLG = 2;
h = lagrange(1, 0.35)
startup = 1;
for n = 1:L,
if x >= 1 || startup;
x = 0;
p = fs/f;
dx = 1.0/p;
m = min(fix((p/2.0)) + 1, nharm_max);
blep_offset = 0;
blep_gain = 1;
z = ~z;
end;
if x2 >= 1 || startup,
x2 =0;
p2 = fs/f2;
dx2 = 1.0/p2;
m2 = min(fix((p2/2.0)) + 1, nharm_max);
% blep_offset = -(1-(x+0.5));
% blep_gain = x+0.5;
% x = 0;
% z = ~z;
end;
startup = 0;
% BLEP 1
nn = (x+0.0)*(nsin-1) + 1;
ni = fix(nn);
nf = nn - ni;
h = lagrange(NLG, nf);
blep = h(NLG+1)*blepm(m, max(1, ni));
j = 1;
for i = NLG:-1:1
blep = blep + h(i)*blepm(m, max(1, ni-j));
j = j + 1;
end;
% BLEP 2
nn = (x2+0.0)*(nsin-1) + 1;
ni = fix(nn);
nf = nn - ni;
h = lagrange(NLG, nf);
blep2 = h(NLG+1)*blepm(m2, max(1, ni));
j = 1;
for i = NLG:-1:1
blep2 = blep2 + h(i)*blepm(m2, max(1, ni-j));
j = j + 1;
end;
saw = x - blep;
if (z == 0)
sqr = blep;
else
sqr = 1-blep;
end
vsqr(n) = 0.5*(sqr-0.5);
tri = tri + 2*(sqr-0.5)*dx;
vtri(n,1) = sqr;
vtri(n,2) = tri;
vsaw(n,1) = x;
vsaw(n,2) = tri;
vblep(n,1) = x;
vblep(n,2) = blep;
x = x + dx;
f = f + df;
x2 = x2 + dx2;
f2 = f2 + df2;
end;
close all
plot(1:nsin, blepm(fix(nharm/2), :)); grid;
wavwrite(0.5*vtri, fs, 'tri.wav');
wavwrite(0.5*vsqr, fs, 'sqr.wav');
wavwrite(0.5*vsaw, fs, 'saw.wav');
wavwrite(0.5*vblep, fs, 'blep.wav');
function h = lagrange(N, delay)
%LAGRANGE h=lagrange(N,delay) returns order N FIR
% filter h which implements given delay
% (in samples). For best results,
% delay should be near N/2 +/- 1.
n = 0:N;
h = ones(1,N+1);
for k = 0:N
index = find(n ~= k);
h(index) = h(index) * (delay-k)./ (n(index)-k);
end
+107
View File
@@ -0,0 +1,107 @@
function eval_hardsync()
nsin = 4096;
nharm_max = 1800;
L = 48000/2;
fs = 48000;
fstart = 440;
fend = 440;
df = (fend-fstart)/L
f2start = 200;
f2end = 600;
df2 = (f2end-f2start)/L
% Calc blep table
nharm = min(fix((fs/fstart/2.0)) + 1, nharm_max)
Hw = kaiser(nsin, 8);
xx = (0:nsin-1)/nsin - 0.5;
for mm=1:nharm
blitm(mm,:) = sin(xx*(mm-1)*pi)./sin(xx*pi).*Hw';
blitm(mm,(find(isnan(blitm(mm,:))))) = (mm-1);
end;
for mm=1:nharm
blepm(mm, :) = cumsum(blitm(mm, :))/nsin;
end;
x = 0.0;
x2 = 0.0;
z = 0;
f = fstart;
f2 = f2start;
tri = 0;
NLG = 2;
h = lagrange(1, 0.35)
startup = 1;
for n = 1:L,
if x >= 1 || startup;
x = x - 1;
p = fs/f;
dx = 1.0/p;
m = min(fix((p/2.0)) + 1, nharm_max);
z = ~z;
end;
if x2 >= 1 || startup,
x2 =0;
p2 = fs/f2;
dx2 = 1.0/p2;
m2 = min(fix((p2/2.0)) + 1, nharm_max);
% blep_offset = -(1-x);
% blep_gain = x;
% x = 0;
% z = ~z;
end;
startup = 0;
nn = (x+0.0)*(nsin-1) + 1;
ni = fix(nn);
nf = nn - ni;
h = lagrange(NLG, nf);
blep = h(NLG+1)*blepm(m, max(1, ni));
j = 1;
for i = NLG:-1:1
blep = blep + h(i)*blepm(m, max(1, ni-j));
j = j + 1;
end;
saw = x - blep;
if (z == 0)
sqr = blep;
else
sqr = 1-blep;
end
vsqr(n) = 0.5*(sqr-0.5);
tri = tri + 2*(sqr-0.5)*dx;
vtri(n) = tri;
vsaw(n,1) = x;
vsaw(n,2) = saw+0.5;
vblep(n,1) = x;
vblep(n,2) = blep;
x = x + dx;
f = f + df;
x2 = x2 + dx2;
f2 = f2 + df2;
end;
close all
plot(1:nsin, blepm(fix(nharm/2), :)); grid;
wavwrite(0.5*vtri, fs, 'tri.wav');
wavwrite(0.5*vsqr, fs, 'sqr.wav');
wavwrite(0.5*vsaw, fs, 'saw.wav');
wavwrite(0.5*vblep, fs, 'blep.wav');
function h = lagrange(N, delay)
%LAGRANGE h=lagrange(N,delay) returns order N FIR
% filter h which implements given delay
% (in samples). For best results,
% delay should be near N/2 +/- 1.
n = 0:N;
h = ones(1,N+1);
for k = 0:N
index = find(n ~= k);
h(index) = h(index) * (delay-k)./ (n(index)-k);
end
+11
View File
@@ -0,0 +1,11 @@
function eval_harmonics(name)
base = exp(1);
ke = 10;
[x, fs, nbits] = wavread(name);
y = (1 - base.^(-ke*fabs(x))) * sign(x);
wavrite(y, fs, nbits,
+11
View File
@@ -0,0 +1,11 @@
function eval_harmonics(name)
base = exp(1);
ke = 2;
[x, fs, nbits] = wavread(name);
y = (1 - base.^(-ke*abs(x))) .* sign(x);
yname = sprintf('out.wav', name);
wavwrite(y*0.8, fs, nbits, yname);
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+66
View File
@@ -0,0 +1,66 @@
function paramscale(base, kexp, scenter, pcenter, pmin, pmax)
N = 1000;
slider = (0:N)/N;
p = toParam(base, kexp, scenter, pcenter, pmin, pmax, slider);
s = toSlider(base, kexp, scenter, pcenter, pmin, pmax, p);
subplot (2, 1, 1)
plot (0:N, p); grid; xlabel('param');
subplot (2, 1, 2)
plot (0:N, s); grid; xlabel('slider');
function param = toParam(base, kexp, scenter, pcenter, pmin, pmax, slider)
% pcenter = pmax*scenter + pmin*(1-scenter)
for i=1:length(slider),
s = min(1, max(0, slider(i)));
if (s < scenter)
if (base == 1)
p = pcenter-(pcenter-pmin)*(scenter-s)/scenter;
% p = pcenter-(pcenter-pmin)*(scenter-s)/scenter;
else
p = pcenter-(pcenter-pmin)*(base^(kexp*(scenter-s)/scenter)-1)/(base^kexp-1);
% p = pcenter-(pcenter-pmin)*(pow(base,kexp*(scenter-s)/scenter)-1)/(pow(base,kexp)-1);
end
else
if (base == 1)
p = pcenter+(pmax-pcenter)*(-scenter+s)/(1-scenter);
% p = pcenter+(pmax-pcenter)*(-scenter+s)/(1-scenter);
else
p = pcenter+(pmax-pcenter)*(base^(kexp*(-scenter+s)/(1-scenter))-1)/(base^kexp-1);
% p = pcenter+(pmax-pcenter)*(pow(base,kexp*(-scenter+s)/(1-scenter))-1)/(pow(base,kexp)-1);
end;
end
param(i) = p;
end
function slider = toSlider(base, kexp, scenter, pcenter, pmin, pmax, param)
%pcenter = pmax*scenter + pmin*(1-scenter);
for i=1:length(param),
p = param(i);
if (p < pcenter)
if (base == 1)
s = (-pmin+p)*scenter/(pcenter-pmin);
% s = (-pmin+p)*scenter/(pcenter-pmin);
else
s = scenter*(log(base)*kexp-log(-(-pcenter*base^kexp+pmin+p*base^kexp-p)/(pcenter-pmin)))/log(base)/kexp;
% s = scenter*(log(base)*kexp-log(-(-pcenter*pow(base,kexp)+pmin+p*pow(base,kexp)-p)/(pcenter-pmin)))/log(base)/kexp;
end
else
if (base == 1)
s = (pcenter-scenter*pmax-p+scenter*p)/(-pmax+pcenter);
% s = (pcenter-scenter*pmax-p+scenter*p)/(-pmax+pcenter);
else
s = (kexp*log(base)*scenter+log(-(-pcenter*base^kexp+pmax+p*base^kexp-p)/(-pmax+pcenter))-log(-(-pcenter*base^kexp+pmax+p*base^kexp-p)/(-pmax+pcenter))*scenter)/log(base)/kexp;
% 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;
end
end
slider(i) = s;
end
+13
View File
@@ -0,0 +1,13 @@
function paramscale(base, kexp, scenter, pcenter, pmin, pmax)
N = 1000;
slider = (0:N)/N;
p = toParam(base, kexp, scenter, pcenter, pmin, pmax, slider);
s = toSlider(base, kexp, scenter, pcenter, pmin, pmax, p);
subplot (2, 1, 1)
plot (slider, p); grid; xlabel('toParam(s)');
subplot (2, 1, 2)
plot (slider, s); grid; xlabel('toSlider(p)');
+28
View File
@@ -0,0 +1,28 @@
function param = toParam(base, kexp, scenter, pcenter, pmin, pmax, slider)
if ((pcenter < pmin) || (pcenter > pmax))
pcenter = pmax*scenter + pmin*(1-scenter);
end
for i=1:length(slider),
s = min(1, max(0, slider(i)));
if (s < scenter)
if (base == 1)
p = pcenter-(pcenter-pmin)*(scenter-s)/scenter;
% p = pcenter-(pcenter-pmin)*(scenter-s)/scenter;
else
p = pcenter-(pcenter-pmin)*(base^(kexp*(scenter-s)/scenter)-1)/(base^kexp-1);
% p = pcenter-(pcenter-pmin)*(pow(base,kexp*(scenter-s)/scenter)-1)/(pow(base,kexp)-1);
end
else
if (base == 1)
p = pcenter+(pmax-pcenter)*(-scenter+s)/(1-scenter);
% p = pcenter+(pmax-pcenter)*(-scenter+s)/(1-scenter);
else
p = pcenter+(pmax-pcenter)*(base^(kexp*(-scenter+s)/(1-scenter))-1)/(base^kexp-1);
% p = pcenter+(pmax-pcenter)*(pow(base,kexp*(-scenter+s)/(1-scenter))-1)/(pow(base,kexp)-1);
end;
end
param(i) = p;
end
+28
View File
@@ -0,0 +1,28 @@
function slider = toSlider(base, kexp, scenter, pcenter, pmin, pmax, param)
if ((pcenter < pmin) || (pcenter > pmax))
pcenter = pmax*scenter + pmin*(1-scenter);
end
for i=1:length(param),
p = param(i);
if (p < pcenter)
if (base == 1)
s = (-pmin+p)*scenter/(pcenter-pmin);
% s = (-pmin+p)*scenter/(pcenter-pmin);
else
s = scenter*(log(base)*kexp-log(-(-pcenter*base^kexp+pmin+p*base^kexp-p)/(pcenter-pmin)))/log(base)/kexp;
% s = scenter*(log(base)*kexp-log(-(-pcenter*pow(base,kexp)+pmin+p*pow(base,kexp)-p)/(pcenter-pmin)))/log(base)/kexp;
end
else
if (base == 1)
s = (pcenter-scenter*pmax-p+scenter*p)/(-pmax+pcenter);
% s = (pcenter-scenter*pmax-p+scenter*p)/(-pmax+pcenter);
else
s = (kexp*log(base)*scenter+log(-(-pcenter*base^kexp+pmax+p*base^kexp-p)/(-pmax+pcenter))-log(-(-pcenter*base^kexp+pmax+p*base^kexp-p)/(-pmax+pcenter))*scenter)/log(base)/kexp;
% 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;
end
end
slider(i) = s;
end
+3
View File
@@ -0,0 +1,3 @@
build
JUCE-3.1.1
+1 -1
View File
@@ -23,7 +23,7 @@ DEFINES += -D${TARGET}
${OBJS}: $(BUILD_DIR)/%.o : ${PKG_ROOT}/%.cpp ${OBJS}: $(BUILD_DIR)/%.o : ${PKG_ROOT}/%.cpp
mkdir -p $(dir $@) mkdir -p $(dir $@)
g++ ${CXXFLAGS_${CONFIG}} ${DEFINES} ${INCLUDES} -o $@ -c $< $(CXX) ${CXXFLAGS_${CONFIG}} ${DEFINES} ${INCLUDES} -o $@ -c $<
${BUILD_DIR}/${BUILD_TARGET}: ${OBJS} ${BUILD_DIR}/${BUILD_TARGET}: ${OBJS}
ar -q $@ ${OBJS} ar -q $@ ${OBJS}
+2
View File
@@ -0,0 +1,2 @@
vstsdk2.4
+1 -1
View File
@@ -1,5 +1,5 @@
CONFIG ?= release CONFIG ?= release
PKG_VER := vst_sdk2_4_rev2 PKG_VER := vstsdk2.4
include pkg.mk include pkg.mk
+24
View File
@@ -0,0 +1,24 @@
diff -ruN temp/vstsdk2.4/public.sdk/source/vst2.x/audioeffect.cpp ./vstsdk2.4/public.sdk/source/vst2.x/audioeffect.cpp
--- temp/vstsdk2.4/public.sdk/source/vst2.x/audioeffect.cpp 2006-06-07 09:22:02.000000000 +0200
+++ ./vstsdk2.4/public.sdk/source/vst2.x/audioeffect.cpp 2025-08-02 10:01:34.082302630 +0200
@@ -7,7 +7,7 @@
// Created by : Steinberg Media Technologies
// Description : Class AudioEffect (VST 1.0)
//
-// © 2006, Steinberg Media Technologies, All Rights Reserved
+// � 2006, Steinberg Media Technologies, All Rights Reserved
//-------------------------------------------------------------------------------------------------------
#include "audioeffect.h"
@@ -507,9 +507,10 @@
{
VstInt32 digit = value / div;
value -= digit * div;
+ const char digit8 = (char)(digit & 0xFF) + '0';
if (state || digit > 0)
{
- char temp[2] = {'0' + (char)digit, '\0'};
+ char temp[2] = {digit8, '\0'};
vst_strncat (text, temp, maxLen);
state = true;
}
+1 -1
View File
@@ -23,7 +23,7 @@
#define __JUCER_HEADER_BUTTONLED_BUTTONLED_B8510B75__ #define __JUCER_HEADER_BUTTONLED_BUTTONLED_B8510B75__
//[Headers] -- You can add your own extra header files here -- //[Headers] -- You can add your own extra header files here --
#include "../JuceLibraryCode/JuceHeader.h" #include <JuceHeader.h>
//[/Headers] //[/Headers]
+241
View File
@@ -0,0 +1,241 @@
/*
//#######################################################################################
//Class to insert Midiclock messages into a given MidiBuffer, suitable for block
//based audio callbacks. The class can act on position jumps e.g. "Loops" by sending a
//positioning message.
//NOTE: No ballistik came in to play so I wouldn't recommend using it to drive a mechanical
//tape deck!!!
//
//solar3d-software, April- 10- 2012
//#######################################################################################
*/
#include "JK_MidiClock.h"
#include "juce_core/maths/juce_MathsFunctions.h"
#include <cmath>
#include <synth/synth_defs.h>
JK_MidiClock::JK_MidiClock()
:m_wasPlaying(false),
m_syncPpqPosition(-999.0),
m_posChangeThreshold(0.001),
m_ppqToStartSyncAt(0.0),
m_followSongPosition(true),
m_syncFlag(0),
m_ppqOffset(0)
{
//Prepare Midi messages to avoid blocking the caller of generateMidiclock()!
m_continueMessage = new MidiMessage(MidiMessage::midiContinue());
m_stopMessage = new MidiMessage(MidiMessage::midiStop());
m_clockMessage = new MidiMessage(MidiMessage::midiClock());
m_songPositionMessage = new MidiMessage(MidiMessage::songPositionPointer(0));
m_sample_remain = 0;
}
//=================================================================================================
void JK_MidiClock::generateMidiclock(const AudioPlayHead::CurrentPositionInfo &posInfo,
MidiBuffer* midiBuffer, const int bufferSize, const double sampleRate)
{
//###################################Some explanation about musical tempo #################
//A Time Signature, is two numbers, one on top of the other. The numerator describes the #
//number of Beats in a Bar, while the denominator describes of what note value a Beat is. #
//So 4/4 would be four quarter-notes per Bar, while 4/2 would be four half-notes per Bar, #
//4/8 would be four eighth-notes per Bar, and 2/4 would be two quarter-notes per Bar. #
//#########################################################################################
if (midiBuffer == nullptr)
{
return;
}
//PPQ value of one sample
const double ppqPerSample = (posInfo.bpm / 60.0) / sampleRate;
//PPQ offset to compensate Midi interface latency
double hostPpqPosition = posInfo.ppqPosition + m_ppqOffset * ppqPerSample;
const double clockDistanceInSamples_f = (60.0 * sampleRate) / (posInfo.bpm * 24.0);
const int clockDistanceInSamples = roundToInt(clockDistanceInSamples_f);
const double quant = (60.0 / posInfo.bpm) * sampleRate;
if (posInfo.isPlaying || posInfo.isRecording)
{
if (! m_wasPlaying)
{
//set the point where to start the slave
m_ppqToStartSyncAt = getNearestSixteenthInPPQ(hostPpqPosition);
SynthDebug("m_ppqToStartSyncAt %f", m_ppqToStartSyncAt);
//Special case: Master is set to always start playback from the previous start position...
if (positionJumped(m_syncPpqPosition, hostPpqPosition, sampleRate, ppqPerSample))
{
//Cue Midiclock slave to the nearest sixteenth note to new start position
//because the one calculated in stop mode isn't valid anymore.
sendSongPositionPointerMessage(m_ppqToStartSyncAt, 0, midiBuffer);
SynthDebug("m_ppqToStartSyncAt %f", m_ppqToStartSyncAt);
}
m_sample_remain = clockDistanceInSamples;
}
else
{
//Position jump (loop or manually position change while playing)
if (positionJumped(m_syncPpqPosition, hostPpqPosition, sampleRate, ppqPerSample))
{
SynthDebug("positionJumped");
//set the point where to start the slave
m_ppqToStartSyncAt = getNearestSixteenthInPPQ(hostPpqPosition);
//User has changed position manually while playing
if (m_syncFlag == 0)
{
SynthDebug("Sync=0");
midiBuffer->addEvent(*m_stopMessage, 0);
sendSongPositionPointerMessage(hostPpqPosition, 0, midiBuffer);
m_syncFlag = startSlave_;
}
else
{
SynthDebug("Sync=1");
if (m_followSongPosition)
{
sendSongPositionPointerMessage(hostPpqPosition, 0, midiBuffer);
m_syncFlag = startSlave_;
}
else
{
m_syncFlag = 0;
}
}
m_sample_remain = clockDistanceInSamples;
}
}
for (int posInBuffer = 0; posInBuffer < bufferSize; ++posInBuffer)
{
m_syncPpqPosition = hostPpqPosition + (posInBuffer * ppqPerSample);
//Some hosts like Cubase come up with a wacky ppqPosition
//that could break the timing! Best is to "wait"
//here for the right ppqPosition to jump on.
if (m_syncPpqPosition >= m_ppqToStartSyncAt)
{
if ((m_syncFlag & startSlave_) == startSlave_)
{
midiBuffer->addEvent(*m_continueMessage, posInBuffer);
m_syncFlag &= cycleEnd_;
}
//Cycle mode on
if (posInfo.isLooping && posInfo.ppqLoopStart != posInfo.ppqLoopEnd)
{
const double ppqToCycleEnd = fabs(posInfo.ppqLoopEnd - m_syncPpqPosition);
const int64 samplesToCycleEnd = roundToInt64(ppqToCycleEnd * (60.0 / posInfo.bpm) * sampleRate);
if ((m_syncFlag & cycleEnd_) == 0)
{
if (samplesToCycleEnd <= clockDistanceInSamples) //For fine tuning tweak here
{
//We have reached the cycle- end position
//and must stop the Midiclock slave here
if (m_followSongPosition)
midiBuffer->addEvent(*m_stopMessage, posInBuffer);
m_syncFlag |= cycleEnd_;
}
}
}
}
}
//For best timing we should never interupt Midiclock messages!
//Seems that some slaves constantly adjusting their internal clock
//to Midiclock even if they are in stop mode.
int buffer_remain = bufferSize;
int posInBuffer = 0;
int buffer_consume = 0;
while(buffer_remain)
{
if (m_sample_remain > buffer_remain)
{
m_sample_remain -= buffer_remain;
buffer_consume = buffer_remain;
}
else
{
buffer_consume = m_sample_remain;
m_sample_remain = 0;
}
buffer_remain -= buffer_consume;
posInBuffer += buffer_consume;
if (buffer_remain == 0)
{
break;
}
if (m_sample_remain == 0)
{
m_sample_remain = clockDistanceInSamples;
#if 0
SynthDebug("posInBuffer : %d", posInBuffer);
SynthDebug("clockDistanceInSamples_f (soll) : %f", clockDistanceInSamples_f);
SynthDebug("hostPpqPosition : %f", hostPpqPosition);
SynthDebug("hostPpqPosition (Q) : %f", getNearestInPPQ(hostPpqPosition, 96));
SynthDebug("hostSamplePos (Q) : %f", getNearestInPPQ(hostPpqPosition, 96) * quant);
#endif
midiBuffer->addEvent(*m_clockMessage, roundToInt(posInBuffer));
}
}
m_wasPlaying = true;
}
else
{
//Send positioning message if the user has stopped or if he changed the playhead position
//manually in stop mode! This will also initially cue slave after loading plugin instance.
if (m_wasPlaying || positionJumped(m_syncPpqPosition, hostPpqPosition, sampleRate, ppqPerSample))
{
midiBuffer->addEvent(*m_stopMessage, 0);
sendSongPositionPointerMessage(hostPpqPosition, 0, midiBuffer);
}
m_syncPpqPosition = hostPpqPosition;
m_syncFlag = startSlave_;
m_wasPlaying = false;
}
}
//=================================================================================================
bool JK_MidiClock::positionJumped(const double lastPosInPPQ, const double currentPosInPPQ,
const double sampleRate, const double ppqPerSample)
{
//This returns true if the user has changed the playhead position manually or if
//a jump has occured! The comperator's default threshold is lastPosInPPQ +- 10ms.
if (currentPosInPPQ < lastPosInPPQ - ((m_posChangeThreshold * sampleRate) * ppqPerSample) ||
currentPosInPPQ > lastPosInPPQ + ((m_posChangeThreshold * sampleRate) * ppqPerSample))
return true;
return false;
}
//=================================================================================================
void JK_MidiClock::sendSongPositionPointerMessage(const double ppqPosition, const int posInBuffer, MidiBuffer* buffer)
{
//This will cue the slave to the NEAREST
//16th note to the given ppqPosition.
int intBeat = int(ceil(ppqPosition * 4));
uint8* pSongPositionTime((uint8*)(m_songPositionMessage->getRawData()));
*(pSongPositionTime + 1) = (uint8)(intBeat & 0x7f);
*(pSongPositionTime + 2) = (uint8)((intBeat & 0x3f80)>>7);
buffer->addEvent(*m_songPositionMessage, posInBuffer);
}
@@ -14,7 +14,7 @@
#ifndef __JK_MIDICLOCK #ifndef __JK_MIDICLOCK
#define __JK_MIDICLOCK #define __JK_MIDICLOCK
#include "../JuceLibraryCode/JuceHeader.h" #include <JuceHeader.h>
//#include "Includes.h" //#include "Includes.h"
@@ -23,14 +23,14 @@ class JK_MidiClock
public: public:
JK_MidiClock(); JK_MidiClock();
void setPositionJumpThreshold(const double ms) {posChangeThreshold = ms / 1000.0;} void setPositionJumpThreshold(const double ms) {m_posChangeThreshold = ms / 1000.0;}
double getPositionJumpThreshold() {return posChangeThreshold;} double getPositionJumpThreshold() {return m_posChangeThreshold;}
void setFollowSongPosition(const bool shouldFollow) {followSongPosition = shouldFollow;} void setFollowSongPosition(const bool shouldFollow) {m_followSongPosition = shouldFollow;}
bool getFollowSongPosition() {return followSongPosition;} bool getFollowSongPosition() {return m_followSongPosition;}
void setOffset(const int offset) {ppqOffset = offset;} void setOffset(const int offset) {m_ppqOffset = offset;}
int getOffset() {return ppqOffset;} int getOffset() {return m_ppqOffset;}
void generateMidiclock(AudioPlayHead::CurrentPositionInfo &lastPosInfo, void generateMidiclock(const AudioPlayHead::CurrentPositionInfo &lastPosInfo,
MidiBuffer* midiBuffer, MidiBuffer* midiBuffer,
const int bufferSize, const int bufferSize,
const double sampleRate); const double sampleRate);
@@ -45,21 +45,21 @@ private:
} }
bool wasPlaying; bool m_wasPlaying;
double syncPpqPosition; double m_syncPpqPosition;
double posChangeThreshold; double m_posChangeThreshold;
double ppqToStartSyncAt; double m_ppqToStartSyncAt;
bool followSongPosition; bool m_followSongPosition;
uint8 syncFlag; uint8 m_syncFlag;
int ppqOffset; int m_ppqOffset;
int m_sample_remain;
static const int cycleEnd_ = 1; static const int cycleEnd_ = 1;
static const int startSlave_ = 2; static const int startSlave_ = 2;
ScopedPointer <MidiMessage> clockMessage; ScopedPointer <MidiMessage> m_clockMessage;
ScopedPointer <MidiMessage> continueMessage; ScopedPointer <MidiMessage> m_continueMessage;
ScopedPointer <MidiMessage> stopMessage; ScopedPointer <MidiMessage> m_stopMessage;
ScopedPointer <MidiMessage> songPositionMessage; ScopedPointer <MidiMessage> m_songPositionMessage;
void sendSongPositionPointerMessage(const double ppqPosition, const int posInBuffer, MidiBuffer* buffer); void sendSongPositionPointerMessage(const double ppqPosition, const int posInBuffer, MidiBuffer* buffer);
@@ -67,6 +67,7 @@ private:
const double sampleRate, const double ppqPerSample); const double sampleRate, const double ppqPerSample);
double getNearestSixteenthInPPQ(const double ppqPosition) {return ceil(ppqPosition * 4.0) / 4.0;} double getNearestSixteenthInPPQ(const double ppqPosition) {return ceil(ppqPosition * 4.0) / 4.0;}
double getNearestInPPQ(const double ppqPosition, double quantizer) {return ceil(ppqPosition * quantizer / 4) / (quantizer / 4);}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(JK_MidiClock); JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(JK_MidiClock);
}; };
+54 -21
View File
@@ -9,7 +9,16 @@
#include <math.h> #include <math.h>
#include <stdio.h> #include <stdio.h>
#include "synth/synth_defs.h" #include <synth/synth_defs.h>
#include <synth/voice.h>
#include <synth/vco.h>
#include <synth/noise.h>
#include <synth/smooth.h>
#include <synth/vcf.h>
#include <synth/lfo.h>
#include <synth/env.h>
#include <synth/param_scale.h>
#include "JaySynthSound.h" #include "JaySynthSound.h"
#include "JaySynthVoice.h" #include "JaySynthVoice.h"
#include "JaySynthMonophonicMGR.h" #include "JaySynthMonophonicMGR.h"
@@ -887,22 +896,16 @@ void JaySynth::handlePitchWheel (const int midiChannel, const int wheelValue)
} }
void JaySynth::handleController (const int midiChannel, void JaySynth::handleController (const midiCC_info_t &midiCC_info)
const int controllerNumber,
const int controllerValue)
{ {
midiCC_info.channel = midiChannel; last_midiCC_info[midiCC_info.ID] = midiCC_info;
midiCC_info.ID = controllerNumber; listeners.call (&JaySynthListener::synthChanged, SYNTH_CHANGED_MIDICC, (midiCC_info_t*)&midiCC_info);
midiCC_info.value = (synth_float_t)controllerValue/127;
last_midiCC_info[controllerNumber] = midiCC_info; switch (midiCC_info.ID)
listeners.call (&JaySynthListener::synthChanged, SYNTH_CHANGED_MIDICC, &midiCC_info);
switch (controllerNumber)
{ {
case 0x40: handleSustainPedal (midiChannel, controllerValue >= 64); break; case 0x40: handleSustainPedal (midiCC_info.channel, midiCC_info.value_raw >= 64); break;
case 0x42: handleSostenutoPedal (midiChannel, controllerValue >= 64); break; case 0x42: handleSostenutoPedal (midiCC_info.channel, midiCC_info.value_raw >= 64); break;
case 0x43: handleSoftPedal (midiChannel, controllerValue >= 64); break; case 0x43: handleSoftPedal (midiCC_info.channel, midiCC_info.value_raw >= 64); break;
default: break; default: break;
} }
@@ -912,8 +915,8 @@ void JaySynth::handleController (const int midiChannel,
{ {
JaySynthVoice* const voice = voices.getUnchecked (i); JaySynthVoice* const voice = voices.getUnchecked (i);
if (midiChannel <= 0 || voice->isPlayingChannel (midiChannel)) if (midiCC_info.channel <= 0 || voice->isPlayingChannel (midiCC_info.channel))
voice->controllerMoved (controllerNumber, controllerValue); voice->controllerMoved (midiCC_info.ID, midiCC_info.value_raw);
} }
} }
@@ -1087,9 +1090,30 @@ void JaySynth::handleMidiEvent (const MidiMessage& m)
} }
if (m.isController()) if (m.isController())
{ {
handleController (m.getChannel(), midiCC_info_t midiCC_info;
m.getControllerNumber(), midiCC_info.channel = m.getChannel();
m.getControllerValue()); midiCC_info.ID = m.getControllerNumber();
midiCC_info.type = MIDI_CONTROLLER_TYPE_CC;
midiCC_info.value_raw = m.getControllerValue();
midiCC_info.value = (synth_float_t)midiCC_info.value_raw/127;
SynthDebug("CC: controllerNumber=%d, controllerValue=%d", midiCC_info.ID, midiCC_info.value_raw);
bool isNrpnProcessing = mMidiNrpn.process(midiCC_info.ID, midiCC_info.value_raw);
if (mMidiNrpn.isValid())
{
midiCC_info.ID = mMidiNrpn.getId();
midiCC_info.type = MIDI_CONTROLLER_TYPE_NRPN;
midiCC_info.value_raw = mMidiNrpn.getValue();
midiCC_info.value = (synth_float_t)midiCC_info.value_raw/mMidiNrpn.getMaxValue();
SynthDebug("NRPN: controllerNumber=%d, controllerValue=%d", midiCC_info.ID, midiCC_info.value_raw);
}
if (!isNrpnProcessing)
{
handleController (midiCC_info);
}
} }
if (m.isMidiMachineControlMessage()) if (m.isMidiMachineControlMessage())
{ {
@@ -1128,8 +1152,10 @@ void JaySynth::handleMidiEvent (const MidiMessage& m)
if (m.isSongPositionPointer()) if (m.isSongPositionPointer())
{ {
SynthDebug("SongPositionPointer\n"); SynthDebug("SongPositionPointer\n");
m_clock_cnt_bar = (6 * m.getSongPositionPointerMidiBeat()) % m_numMidiClocksPerBar; double bar_16 = 1 + ((double)m.getSongPositionPointerMidiBeat()/4);
SynthDebug("getSongPositionPointerMidiBeat(): %u -> %u clocks\n", m.getSongPositionPointerMidiBeat(), m_clock_cnt_bar); double bar_4 = (bar_16 - (int)bar_16);
m_clock_cnt_bar = (int)(bar_4*4);
SynthDebug("getSongPositionPointerMidiBeat(): %f -> %u clocks", bar_4, m_clock_cnt_bar);
} }
if (m.isQuarterFrame()) if (m.isQuarterFrame())
{ {
@@ -1162,10 +1188,17 @@ void JaySynth::handleMidiEvent (const MidiMessage& m)
info.bpm = (uint32_t)(bpm + 0.5); info.bpm = (uint32_t)(bpm + 0.5);
info.type = 1; info.type = 1;
if (m_clock_cnt_bar == 0) if (m_clock_cnt_bar == 0)
{ {
info.type = 2; info.type = 2;
SynthDebug("1111111111111111111111111");
} }
else
{
SynthDebug("-------------------------");
}
listeners.call (&JaySynthListener::synthChanged, SYNTH_CHANGED_MIDICLOCK, &info); listeners.call (&JaySynthListener::synthChanged, SYNTH_CHANGED_MIDICLOCK, &info);
} }
} }
+85 -70
View File
@@ -9,11 +9,14 @@
#ifndef _JAYSYNTH_H_ #ifndef _JAYSYNTH_H_
#define _JAYSYNTH_H_ #define _JAYSYNTH_H_
#include "../JuceLibraryCode/JuceHeader.h" #include <synth/synth_defs.h>
#include "synth/synth_defs.h" #include <synth/param_scale.h>
#include "synth/param_scale.h"
#include <JuceHeader.h>
#include "JaySynthVoice.h" #include "JaySynthVoice.h"
#include "JaySynthMonophonicMGR.h" #include "JaySynthMonophonicMGR.h"
#include "JaySynthMidiCC.h"
#include "MidiNrpn.h"
#define GET_NUM_VOICES max_num_voices #define GET_NUM_VOICES max_num_voices
@@ -44,6 +47,82 @@ private:
class JaySynth : public Synthesiser class JaySynth : public Synthesiser
{ {
public: public:
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_MIDICLOCK,
SYNTH_CHANGED_SIZE
};
enum
{
MIDI_CONTROLLER_TYPE_CC = 0,
MIDI_CONTROLLER_TYPE_NRPN,
MIDI_CONTROLLER_TYPE_RPN,
MIDI_CONTROLLER_TYPE_SIZE
};
typedef struct _smidiCC_info_t
{
int type;
int channel;
int ID;
int value_raw;
synth_float_t value;
} midiCC_info_t;
typedef struct _smidi_note_info_t
{
int note;
synth_float_t velocity;
} midi_note_info_t;
typedef struct _smidi_quarter_clock_info_t
{
uint32_t type;
uint32_t bpm;
} midi_quarter_clock_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;
JaySynth(int num_voices, String pathToWaves); JaySynth(int num_voices, String pathToWaves);
~JaySynth(); ~JaySynth();
void setSampleRate (synth_float_t sampleRate); void setSampleRate (synth_float_t sampleRate);
@@ -57,7 +136,8 @@ public:
synth_float_t getVolume(void); synth_float_t getVolume(void);
int lastPitchWheelValue, lastmidiChannel; int lastPitchWheelValue, lastmidiChannel;
void handlePitchWheel (int midiChannel, int wheelValue); void handlePitchWheel (int midiChannel, int wheelValue);
void handleController (int midiChannel, int controllerNumber, int controllerValue); void handleController (int midiChannel, int controllerNumber, int controllerValue) {}
void handleController (const midiCC_info_t &midiCC_info);
void updateParameters(void); void updateParameters(void);
void updateParameter(int paramID); void updateParameter(int paramID);
void humanizeModeChanged(void); void humanizeModeChanged(void);
@@ -145,72 +225,6 @@ public:
listeners.add (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_MIDICLOCK,
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;
typedef struct _smidi_quarter_clock_info_t
{
uint32_t type;
uint32_t bpm;
} midi_quarter_clock_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: private:
@@ -261,6 +275,7 @@ private:
bool m_isMidiClockStarted; bool m_isMidiClockStarted;
void updateMidiTiming(const MidiMessage& m); void updateMidiTiming(const MidiMessage& m);
MidiNrpn mMidiNrpn;
}; };
@@ -726,24 +726,6 @@ JaySynthAudioProcessorEditor::JaySynthAudioProcessorEditor (JaySynthAudioProcess
m_comboBox_vcf_type->addItem (TRANS("BPF"), 3); m_comboBox_vcf_type->addItem (TRANS("BPF"), 3);
m_comboBox_vcf_type->addListener (this); m_comboBox_vcf_type->addListener (this);
addAndMakeVisible (m_slider_lfo1_smooth = new Slider ("LFO 2 smooth"));
m_slider_lfo1_smooth->setTooltip (TRANS("LFO 2 smooth [%]"));
m_slider_lfo1_smooth->setRange (0, 1, 0);
m_slider_lfo1_smooth->setSliderStyle (Slider::RotaryVerticalDrag);
m_slider_lfo1_smooth->setTextBoxStyle (Slider::NoTextBox, false, 80, 20);
m_slider_lfo1_smooth->setColour (Slider::rotarySliderFillColourId, Colour (0x7fffffff));
m_slider_lfo1_smooth->setColour (Slider::rotarySliderOutlineColourId, Colour (0x66ffffff));
m_slider_lfo1_smooth->addListener (this);
addAndMakeVisible (m_label_lfo1_smooth = new Label ("LFO 2 smooth",
TRANS("value")));
m_label_lfo1_smooth->setFont (Font (14.00f, Font::plain));
m_label_lfo1_smooth->setJustificationType (Justification::centred);
m_label_lfo1_smooth->setEditable (true, true, false);
m_label_lfo1_smooth->setColour (TextEditor::textColourId, Colours::black);
m_label_lfo1_smooth->setColour (TextEditor::backgroundColourId, Colour (0x00000000));
m_label_lfo1_smooth->addListener (this);
addAndMakeVisible (m_slider_lfo0_smooth = new Slider ("LFO 1 smooth")); addAndMakeVisible (m_slider_lfo0_smooth = new Slider ("LFO 1 smooth"));
m_slider_lfo0_smooth->setTooltip (TRANS("LFO 1 smooth [%]")); m_slider_lfo0_smooth->setTooltip (TRANS("LFO 1 smooth [%]"));
m_slider_lfo0_smooth->setRange (0, 1, 0); m_slider_lfo0_smooth->setRange (0, 1, 0);
@@ -762,6 +744,24 @@ JaySynthAudioProcessorEditor::JaySynthAudioProcessorEditor (JaySynthAudioProcess
m_label_lfo0_smooth->setColour (TextEditor::backgroundColourId, Colour (0x00000000)); m_label_lfo0_smooth->setColour (TextEditor::backgroundColourId, Colour (0x00000000));
m_label_lfo0_smooth->addListener (this); m_label_lfo0_smooth->addListener (this);
addAndMakeVisible (m_slider_lfo1_smooth = new Slider ("LFO 2 smooth"));
m_slider_lfo1_smooth->setTooltip (TRANS("LFO 2 smooth [%]"));
m_slider_lfo1_smooth->setRange (0, 1, 0);
m_slider_lfo1_smooth->setSliderStyle (Slider::RotaryVerticalDrag);
m_slider_lfo1_smooth->setTextBoxStyle (Slider::NoTextBox, false, 80, 20);
m_slider_lfo1_smooth->setColour (Slider::rotarySliderFillColourId, Colour (0x7fffffff));
m_slider_lfo1_smooth->setColour (Slider::rotarySliderOutlineColourId, Colour (0x66ffffff));
m_slider_lfo1_smooth->addListener (this);
addAndMakeVisible (m_label_lfo1_smooth = new Label ("LFO 2 smooth",
TRANS("value")));
m_label_lfo1_smooth->setFont (Font (14.00f, Font::plain));
m_label_lfo1_smooth->setJustificationType (Justification::centred);
m_label_lfo1_smooth->setEditable (true, true, false);
m_label_lfo1_smooth->setColour (TextEditor::textColourId, Colours::black);
m_label_lfo1_smooth->setColour (TextEditor::backgroundColourId, Colour (0x00000000));
m_label_lfo1_smooth->addListener (this);
addAndMakeVisible (m_slider_lfo2_smooth = new Slider ("LFO 3 smooth")); addAndMakeVisible (m_slider_lfo2_smooth = new Slider ("LFO 3 smooth"));
m_slider_lfo2_smooth->setTooltip (TRANS("LFO 3 smooth [%]")); m_slider_lfo2_smooth->setTooltip (TRANS("LFO 3 smooth [%]"));
m_slider_lfo2_smooth->setRange (0, 1, 0); m_slider_lfo2_smooth->setRange (0, 1, 0);
@@ -2497,10 +2497,10 @@ JaySynthAudioProcessorEditor::~JaySynthAudioProcessorEditor()
m_label_synth_name = nullptr; m_label_synth_name = nullptr;
m_label_synth_version = nullptr; m_label_synth_version = nullptr;
m_comboBox_vcf_type = nullptr; m_comboBox_vcf_type = nullptr;
m_slider_lfo1_smooth = nullptr;
m_label_lfo1_smooth = nullptr;
m_slider_lfo0_smooth = nullptr; m_slider_lfo0_smooth = nullptr;
m_label_lfo0_smooth = nullptr; m_label_lfo0_smooth = nullptr;
m_slider_lfo1_smooth = nullptr;
m_label_lfo1_smooth = nullptr;
m_slider_lfo2_smooth = nullptr; m_slider_lfo2_smooth = nullptr;
m_label_lfo2_smooth = nullptr; m_label_lfo2_smooth = nullptr;
m_slider_lfo3_smooth = nullptr; m_slider_lfo3_smooth = nullptr;
@@ -3535,10 +3535,10 @@ void JaySynthAudioProcessorEditor::resized()
m_label_synth_name->setBounds (12, 662, 92, 24); m_label_synth_name->setBounds (12, 662, 92, 24);
m_label_synth_version->setBounds (978, 662, 132, 24); m_label_synth_version->setBounds (978, 662, 132, 24);
m_comboBox_vcf_type->setBounds (880, 74, 68, 16); m_comboBox_vcf_type->setBounds (880, 74, 68, 16);
m_slider_lfo1_smooth->setBounds (506, 88, 36, 36);
m_label_lfo1_smooth->setBounds (498, 70, 52, 20);
m_slider_lfo0_smooth->setBounds (392, 224, 36, 36); m_slider_lfo0_smooth->setBounds (392, 224, 36, 36);
m_label_lfo0_smooth->setBounds (384, 206, 52, 20); m_label_lfo0_smooth->setBounds (384, 206, 52, 20);
m_slider_lfo1_smooth->setBounds (506, 88, 36, 36);
m_label_lfo1_smooth->setBounds (498, 70, 52, 20);
m_slider_lfo2_smooth->setBounds (392, 402, 36, 36); m_slider_lfo2_smooth->setBounds (392, 402, 36, 36);
m_label_lfo2_smooth->setBounds (384, 384, 52, 20); m_label_lfo2_smooth->setBounds (384, 384, 52, 20);
m_slider_lfo3_smooth->setBounds (506, 402, 36, 36); m_slider_lfo3_smooth->setBounds (506, 402, 36, 36);
@@ -5045,10 +5045,6 @@ void JaySynthAudioProcessorEditor::mouseDown (const MouseEvent &m)
if (m.mods.isRightButtonDown() && m.mods.isShiftDown()) if (m.mods.isRightButtonDown() && m.mods.isShiftDown())
{ {
// Comboboxes don't support midicontroller assignments // Comboboxes don't support midicontroller assignments
if (componentThatWasClicked->getComponentID().contains(String("PARAM_COMBOBOX")))
{
return;
}
MidiCC_PopUp_show(componentThatWasClicked); MidiCC_PopUp_show(componentThatWasClicked);
} }
} }
@@ -5164,10 +5160,6 @@ void JaySynthAudioProcessorEditor::MidiCC_PopUp_event(int event)
switch (event) switch (event)
{ {
case MidiCC_PopUp::POPUP_OK: case MidiCC_PopUp::POPUP_OK:
paramID = m_MidiCC_PopUp->getParamID();
getProcessor()->setParam(paramID, m_MidiCC_PopUp->getCurrentParamValue(), false, false);
getProcessor()->controlParam(paramID, m_MidiCC_PopUp->getCurrentControlValue());
m_label_patch_name->setText(getProcessor()->getCurrentProgramName(), juce::NotificationType::dontSendNotification);
deleteAndZero (m_MidiCC_PopUp); deleteAndZero (m_MidiCC_PopUp);
break; break;
@@ -5366,6 +5358,16 @@ void JaySynthAudioProcessorEditor::paramUpdate(int paramID, bool doHostUpdate)
if (pButton) if (pButton)
{ {
pButton->setToggleState(getProcessor()->getParameter(paramID) > 0.5, juce::NotificationType::dontSendNotification); pButton->setToggleState(getProcessor()->getParameter(paramID) > 0.5, juce::NotificationType::dontSendNotification);
if (pButton == m_button_humanize_enable)
{
getProcessor()->humanizeModeChanged();
}
else if (pButton == m_button_unisono_enable)
{
getProcessor()->unisonoModeChanged();
}
} }
} }
@@ -21,7 +21,7 @@
#define __JUCE_HEADER_AD3FF14AD0EF4DBE__ #define __JUCE_HEADER_AD3FF14AD0EF4DBE__
//[Headers] -- You can add your own extra header files here -- //[Headers] -- You can add your own extra header files here --
#include "../JuceLibraryCode/JuceHeader.h" #include <JuceHeader.h>
#include "PluginProcessor.h" #include "PluginProcessor.h"
#include "ButtonLED.h" #include "ButtonLED.h"
#include "MidiCC_PopUp.h" #include "MidiCC_PopUp.h"
@@ -177,10 +177,10 @@ private:
ScopedPointer<Label> m_label_synth_name; ScopedPointer<Label> m_label_synth_name;
ScopedPointer<Label> m_label_synth_version; ScopedPointer<Label> m_label_synth_version;
ScopedPointer<ComboBox> m_comboBox_vcf_type; ScopedPointer<ComboBox> m_comboBox_vcf_type;
ScopedPointer<Slider> m_slider_lfo1_smooth;
ScopedPointer<Label> m_label_lfo1_smooth;
ScopedPointer<Slider> m_slider_lfo0_smooth; ScopedPointer<Slider> m_slider_lfo0_smooth;
ScopedPointer<Label> m_label_lfo0_smooth; ScopedPointer<Label> m_label_lfo0_smooth;
ScopedPointer<Slider> m_slider_lfo1_smooth;
ScopedPointer<Label> m_label_lfo1_smooth;
ScopedPointer<Slider> m_slider_lfo2_smooth; ScopedPointer<Slider> m_slider_lfo2_smooth;
ScopedPointer<Label> m_label_lfo2_smooth; ScopedPointer<Label> m_label_lfo2_smooth;
ScopedPointer<Slider> m_slider_lfo3_smooth; ScopedPointer<Slider> m_slider_lfo3_smooth;
@@ -7,8 +7,9 @@
============================================================================== ==============================================================================
*/ */
#include "../JuceLibraryCode/JuceHeader.h" #include <synth/synth_defs.h>
#include "synth/synth_defs.h"
#include <JuceHeader.h>
#include "JaySynthMidiCC.h" #include "JaySynthMidiCC.h"
//============================================================================== //==============================================================================
@@ -54,11 +55,21 @@ JaySynthMidiCC::JaySynthMidiCC()
/*pmax*/pConstraints->pmax, /*pmax*/pConstraints->pmax,
/*pinterval*/pConstraints->pinterval); /*pinterval*/pConstraints->pinterval);
midiCC_containers[i].doChangeParameter = false; midiCC_containers[i].controllerID = 128 + i;
midiCC_containers[i].controllerID = 0;
midiCC_containers[i].isAssigned = false; midiCC_containers[i].isAssigned = false;
midiCC_containers[i].doChangeParameter = false;
midiCC_containers[i].doApplyOnPatchInit = false; midiCC_containers[i].doApplyOnPatchInit = false;
if (pConstraints->midiControllerId >= 0)
{
if (pConstraints->midiControllerId > 0)
{
midiCC_containers[i].controllerID = pConstraints->midiControllerId;
}
midiCC_containers[i].doChangeParameter = true;
midiCC_containers[i].isAssigned = true;
}
// Velocity // Velocity
paramInfoInit(&midiCC_containers[i].curve_vel, i, pConstraints->pName); paramInfoInit(&midiCC_containers[i].curve_vel, i, pConstraints->pName);
paramInfoSet(&midiCC_containers[i].curve_vel, paramInfoSet(&midiCC_containers[i].curve_vel,
@@ -173,26 +184,13 @@ int JaySynthMidiCC::findParamID_byName(String name)
return (int)paramNamedValueSet.getWithDefault (toParameterNameXML(name), var(-1)); return (int)paramNamedValueSet.getWithDefault (toParameterNameXML(name), var(-1));
} }
void JaySynthMidiCC::exportXML(String name) void JaySynthMidiCC::export_midi_cc(XmlElement *pXML) const
{
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) const
{ {
int paramID; int paramID;
midiCC_container_t const *pMidiContainer; midiCC_container_t const *pMidiContainer;
XmlElement *pXML, *pXML_root, *pXML_PARAM, *pXML_PARAM_INFO; XmlElement *pXML_PARAM, *pXML_PARAM_INFO;
// Store controller and slider infos // 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++) for (paramID=0; paramID < SYNTH_NUM_PARAMS; paramID++)
{ {
pMidiContainer = &midiCC_containers[paramID]; pMidiContainer = &midiCC_containers[paramID];
@@ -202,29 +200,34 @@ void JaySynthMidiCC::exportXML(XmlElement *pXML_doc) const
pXML_PARAM->setAttribute ("IS_ABSOLUTE", pMidiContainer->doChangeParameter); pXML_PARAM->setAttribute ("IS_ABSOLUTE", pMidiContainer->doChangeParameter);
pXML_PARAM->setAttribute ("DO_APPLY_ON_PATCH_INIT", pMidiContainer->doApplyOnPatchInit); pXML_PARAM->setAttribute ("DO_APPLY_ON_PATCH_INIT", pMidiContainer->doApplyOnPatchInit);
pXML_PARAM->setAttribute ("CONTROLLER_ID", pMidiContainer->controllerID); pXML_PARAM->setAttribute ("CONTROLLER_ID", pMidiContainer->controllerID);
}
}
void JaySynthMidiCC::export_midi_velkey(XmlElement *pXML) const
{
int paramID;
midiCC_container_t const *pMidiContainer;
XmlElement *pXML_PARAM, *pXML_PARAM_INFO;
// Store controller and slider infos
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_VELOCITY_ASSIGNED", pMidiContainer->isVelAssigned); pXML_PARAM->setAttribute ("IS_VELOCITY_ASSIGNED", pMidiContainer->isVelAssigned);
pXML_PARAM->setAttribute ("IS_KEYFOLLOW_ASSIGNED", pMidiContainer->isKeyAssigned); pXML_PARAM->setAttribute ("IS_KEYFOLLOW_ASSIGNED", pMidiContainer->isKeyAssigned);
pXML_PARAM->setAttribute ("VELKEY_COMBINE_OP", pMidiContainer->velKeyCombineOP); pXML_PARAM->setAttribute ("VELKEY_COMBINE_OP", pMidiContainer->velKeyCombineOP);
pXML_PARAM_INFO = pXML_PARAM->createNewChildElement (String("RELATIVE")); 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 ("PMIN", String(pMidiContainer->control.pmin, 10));
pXML_PARAM_INFO->setAttribute ("PMAX", String(pMidiContainer->control.pmax, 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 = 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 ("PMIN", String(pMidiContainer->param.pmin, 10));
pXML_PARAM_INFO->setAttribute ("PMAX", String(pMidiContainer->param.pmax, 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 = 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 ("KEXP", String(pMidiContainer->curve_vel.kexp, 10));
pXML_PARAM_INFO->setAttribute ("SCENTER", String(pMidiContainer->curve_vel.scenter, 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 ("PMIN", String(pMidiContainer->curve_vel.pmin, 10));
@@ -232,65 +235,137 @@ void JaySynthMidiCC::exportXML(XmlElement *pXML_doc) const
pXML_PARAM_INFO->setAttribute ("PINTERVAL", String(pMidiContainer->curve_vel.pinterval, 10)); pXML_PARAM_INFO->setAttribute ("PINTERVAL", String(pMidiContainer->curve_vel.pinterval, 10));
pXML_PARAM_INFO = pXML_PARAM->createNewChildElement (String("KEYFOLLOW_CURVE")); 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 ("KEXP", String(pMidiContainer->curve_key.kexp, 10));
pXML_PARAM_INFO->setAttribute ("SCENTER", String(pMidiContainer->curve_key.scenter, 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 ("PMIN", String(pMidiContainer->curve_key.pmin, 10));
pXML_PARAM_INFO->setAttribute ("PMAX", String(pMidiContainer->curve_key.pmax, 10)); pXML_PARAM_INFO->setAttribute ("PMAX", String(pMidiContainer->curve_key.pmax, 10));
pXML_PARAM_INFO->setAttribute ("PINTERVAL", String(pMidiContainer->curve_key.pinterval, 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) int JaySynthMidiCC::import_midi_velkey(XmlElement const *pXML)
{
File file(name);
XmlDocument xml(file);
ScopedPointer<XmlElement> pXML_root (xml.getDocumentElement());
return importXML(pXML_root);
}
int JaySynthMidiCC::importXML(XmlElement const *pXML_doc)
{ {
int i, paramID; int i, paramID;
midiCC_container_t *pMidiContainer; midiCC_container_t *pMidiContainer;
XmlElement *pXML, *pXML_root, *pXML_PARAM, *pXML_PARAM_INFO; XmlElement *pXML_PARAM, *pXML_PARAM_INFO;
for (i=0; i < NUM_MIDI_CONTROLLERS; i++) for (i=0; i < NUM_MIDI_CONTROLLERS; i++)
removeDestinations(i); removeDestinations(i);
pXML_root = pXML_doc->getChildByName ("JSYNTH_MIDICONTROLLER_TABLE");
// make sure that it's actually our type of XML object.. // make sure that it's actually our type of XML object..
if (pXML_root) if (pXML)
{ {
pXML = pXML_root->getFirstChildElement(); pXML_PARAM = pXML->getFirstChildElement();
while(pXML) while(pXML_PARAM)
{
paramID = findParamID_byName(pXML_PARAM->getStringAttribute("NAME"));
if (paramID < 0)
{
pXML_PARAM = pXML_PARAM->getNextElement();
continue;
}
pMidiContainer = &midiCC_containers[paramID];
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.pmin = pXML_PARAM_INFO->getDoubleAttribute("PMIN", pMidiContainer->constraints.pmin);
pMidiContainer->control.pmax = pXML_PARAM_INFO->getDoubleAttribute("PMAX", pMidiContainer->constraints.pmax);
}
pXML_PARAM_INFO = pXML_PARAM->getChildByName(String("ABSOLUTE"));
if (pXML_PARAM_INFO)
{
pMidiContainer->param.pmin = pXML_PARAM_INFO->getDoubleAttribute("PMIN", pMidiContainer->constraints.pmin);
pMidiContainer->param.pmax = pXML_PARAM_INFO->getDoubleAttribute("PMAX", pMidiContainer->constraints.pmax);
}
pXML_PARAM_INFO = pXML_PARAM->getChildByName(String("VELOCITY_CURVE"));
if (pXML_PARAM_INFO)
{
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);
}
pXML_PARAM_INFO = pXML_PARAM->getChildByName(String("KEYFOLLOW_CURVE"));
if (pXML_PARAM_INFO)
{
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);
}
if (pXML_PARAM->getIntAttribute("IS_ASSIGNED", 0))
add(pMidiContainer, pXML_PARAM->getIntAttribute("CONTROLLER_ID", 0));
else
remove(pMidiContainer, pXML_PARAM->getIntAttribute("CONTROLLER_ID", 0));
pXML_PARAM = pXML_PARAM->getNextElement();
}
}
isModified = false;
return 0;
}
int JaySynthMidiCC::import_midi_cc(XmlElement const *pXML)
{
int i, paramID;
midiCC_container_t *pMidiContainer;
XmlElement *pXML_PARAM, *pXML_PARAM_INFO;
for (i=0; i < NUM_MIDI_CONTROLLERS; i++)
removeDestinations(i);
// make sure that it's actually our type of XML object..
if (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;
if (pXML_PARAM->getIntAttribute("IS_ASSIGNED", 0))
add(pMidiContainer, pXML_PARAM->getIntAttribute("CONTROLLER_ID", 0));
else
remove(pMidiContainer, pXML_PARAM->getIntAttribute("CONTROLLER_ID", 0));
pXML_PARAM = pXML_PARAM->getNextElement();
}
}
isModified = false;
return 0;
}
int JaySynthMidiCC::import_midi_cc_legacy(XmlElement const *pXML_MidiCc)
{
int i, paramID;
midiCC_container_t *pMidiContainer;
XmlElement *pXML, *pXML_PARAM, *pXML_PARAM_INFO;
for (i=0; i < NUM_MIDI_CONTROLLERS; i++)
removeDestinations(i);
// make sure that it's actually our type of XML object..
if (pXML_MidiCc)
{
pXML = pXML_MidiCc->getFirstChildElement();
if(pXML)
{ {
pXML_PARAM = pXML->getFirstChildElement(); pXML_PARAM = pXML->getFirstChildElement();
while(pXML_PARAM) while(pXML_PARAM)
@@ -313,83 +388,42 @@ int JaySynthMidiCC::importXML(XmlElement const *pXML_doc)
pXML_PARAM_INFO = pXML_PARAM->getChildByName(String("RELATIVE")); pXML_PARAM_INFO = pXML_PARAM->getChildByName(String("RELATIVE"));
if (pXML_PARAM_INFO) 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.pmin = pXML_PARAM_INFO->getDoubleAttribute("PMIN", pMidiContainer->constraints.pmin);
pMidiContainer->control.pmax = pXML_PARAM_INFO->getDoubleAttribute("PMAX", pMidiContainer->constraints.pmax); 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")); pXML_PARAM_INFO = pXML_PARAM->getChildByName(String("ABSOLUTE"));
if (pXML_PARAM_INFO) 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.pmin = pXML_PARAM_INFO->getDoubleAttribute("PMIN", pMidiContainer->constraints.pmin);
pMidiContainer->param.pmax = pXML_PARAM_INFO->getDoubleAttribute("PMAX", pMidiContainer->constraints.pmax); 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")); pXML_PARAM_INFO = pXML_PARAM->getChildByName(String("VELOCITY_CURVE"));
if (pXML_PARAM_INFO) 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.kexp = pXML_PARAM_INFO->getDoubleAttribute("KEXP", 0);
pMidiContainer->curve_vel.scenter = pXML_PARAM_INFO->getDoubleAttribute("SCENTER", 0.5); pMidiContainer->curve_vel.scenter = pXML_PARAM_INFO->getDoubleAttribute("SCENTER", 0.5);
pMidiContainer->curve_vel.pmin = pXML_PARAM_INFO->getDoubleAttribute("PMIN", 0); pMidiContainer->curve_vel.pmin = pXML_PARAM_INFO->getDoubleAttribute("PMIN", 0);
pMidiContainer->curve_vel.pmax = pXML_PARAM_INFO->getDoubleAttribute("PMAX", 1); 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")); pXML_PARAM_INFO = pXML_PARAM->getChildByName(String("KEYFOLLOW_CURVE"));
if (pXML_PARAM_INFO) 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.kexp = pXML_PARAM_INFO->getDoubleAttribute("KEXP", 0);
pMidiContainer->curve_key.scenter = pXML_PARAM_INFO->getDoubleAttribute("SCENTER", 0.5); pMidiContainer->curve_key.scenter = pXML_PARAM_INFO->getDoubleAttribute("SCENTER", 0.5);
pMidiContainer->curve_key.pmin = pXML_PARAM_INFO->getDoubleAttribute("PMIN", 0); pMidiContainer->curve_key.pmin = pXML_PARAM_INFO->getDoubleAttribute("PMIN", 0);
pMidiContainer->curve_key.pmax = pXML_PARAM_INFO->getDoubleAttribute("PMAX", 1); 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)) if (pXML_PARAM->getIntAttribute("IS_ASSIGNED", 0))
add(pMidiContainer, pXML_PARAM->getIntAttribute("CONTROLLER_ID", 0)); add(pMidiContainer, pXML_PARAM->getIntAttribute("CONTROLLER_ID", 0));
else
remove(pMidiContainer, pXML_PARAM->getIntAttribute("CONTROLLER_ID", 0));
pXML_PARAM = pXML_PARAM->getNextElement(); 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; isModified = false;
@@ -11,8 +11,17 @@
#ifndef _JAYSYNTH_MIDICC_ #ifndef _JAYSYNTH_MIDICC_
#define _JAYSYNTH_MIDICC_ #define _JAYSYNTH_MIDICC_
#include "../JuceLibraryCode/JuceHeader.h" #include <JuceHeader.h>
#include "synth/synth_defs.h"
#include <synth/synth_defs.h>
#include <synth/voice.h>
#include <synth/vco.h>
#include <synth/noise.h>
#include <synth/smooth.h>
#include <synth/vcf.h>
#include <synth/lfo.h>
#include <synth/env.h>
#include <synth/param_scale.h>
//============================================================================== //==============================================================================
#define MIDICONTROLLER_TYPE_VELKEY 0x00000080 #define MIDICONTROLLER_TYPE_VELKEY 0x00000080
@@ -46,10 +55,11 @@ public:
bool isMidiCCmodified(void) const; bool isMidiCCmodified(void) const;
String toParameterNameXML (String const &name) const; String toParameterNameXML (String const &name) const;
int findParamID_byName(String name); int findParamID_byName(String name);
void exportXML(String name); void export_midi_cc(XmlElement *pXML_doc) const;
void exportXML(XmlElement *pXML_doc) const; int import_midi_cc(XmlElement const *pXML_doc);
int importXML(String name); void export_midi_velkey(XmlElement *pXML_doc) const;
int importXML(XmlElement const *pXML_doc); int import_midi_velkey(XmlElement const *pXML_doc);
int import_midi_cc_legacy(XmlElement const *pXML_doc);
void add(midiCC_container_t *pObj, int controllerID); void add(midiCC_container_t *pObj, int controllerID);
void remove(midiCC_container_t *pObj, int controllerID); void remove(midiCC_container_t *pObj, int controllerID);
struct midiCC_container_t* getAtParamID(int paramID); struct midiCC_container_t* getAtParamID(int paramID);
@@ -11,7 +11,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <math.h> #include <math.h>
#include "synth/synth_defs.h" #include <synth/synth_defs.h>
#include "JaySynthMonophonicMGR.h" #include "JaySynthMonophonicMGR.h"
/** A JaySynth voice that just plays incredible sounds.. */ /** A JaySynth voice that just plays incredible sounds.. */
@@ -9,9 +9,6 @@
#ifndef _JAYSYNTHMONOPHONICMGR_H_ #ifndef _JAYSYNTHMONOPHONICMGR_H_
#define _JAYSYNTHMONOPHONICMGR_H_ #define _JAYSYNTHMONOPHONICMGR_H_
//#include "../JuceLibraryCode/JuceHeader.h"
#include "synth/synth_defs.h"
class JaySynthMonophonicMGR class JaySynthMonophonicMGR
{ {
public: public:
@@ -8,7 +8,7 @@
#include <math.h> #include <math.h>
#include "synth/synth_defs.h" #include <synth/synth_defs.h>
#include "JaySynthSound.h" #include "JaySynthSound.h"
JaySynthSound::JaySynthSound() JaySynthSound::JaySynthSound()
@@ -9,8 +9,17 @@
#ifndef _JAYSYNTHSOUND_H_ #ifndef _JAYSYNTHSOUND_H_
#define _JAYSYNTHSOUND_H_ #define _JAYSYNTHSOUND_H_
#include "../JuceLibraryCode/JuceHeader.h" #include <JuceHeader.h>
#include "synth/synth_defs.h" #include <synth/synth_defs.h>
#include <synth/voice.h>
#include <synth/vco.h>
#include <synth/noise.h>
#include <synth/smooth.h>
#include <synth/vcf.h>
#include <synth/lfo.h>
#include <synth/env.h>
#include <synth/param_scale.h>
#include "JaySynthMidiCC.h" #include "JaySynthMidiCC.h"
//============================================================================== //==============================================================================

Some files were not shown because too many files have changed in this diff Show More