Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e9a5784ed1 | ||
|
|
f72a89ed61 | ||
|
|
17b12fe3f1 | ||
|
|
255858cee8 | ||
|
|
15bcf87529 | ||
|
|
31a0c4c009 | ||
|
|
6e67193c3d | ||
|
|
cbdb18e6ba | ||
|
|
bc2020e612 | ||
|
|
8ce2db511b | ||
|
|
6be1b4a911 | ||
|
|
a8e6593eed | ||
|
|
c392104aec | ||
|
|
0de8c05f00 | ||
|
|
597c70bb53 | ||
|
|
c7c9366dbb | ||
|
|
2ab8c68c9b | ||
|
|
21411d2c56 | ||
|
|
4f7803a8b4 | ||
|
|
64c6745c76 | ||
|
|
fd522e1b99 | ||
|
|
7e11e3e72b | ||
|
|
ed737f526f | ||
|
|
83afc11612 | ||
|
|
8a81dd649e | ||
|
|
42e877c08d | ||
|
|
1e0760e49b | ||
|
|
db4fdf68ff | ||
|
|
314b57b1ed | ||
|
|
a3ad0e989e | ||
|
|
159fa60b08 | ||
|
|
e3fb2074f6 | ||
|
|
7fcbb9b509 | ||
|
|
3a19db6a86 | ||
|
|
d73f172fc1 | ||
|
|
f05e3be55f | ||
|
|
2ec3cc9543 | ||
|
|
0f70ea025c | ||
|
|
2ac71f33f1 | ||
|
|
73332a7292 | ||
|
|
4bf46df821 | ||
|
|
072280c603 | ||
|
|
4a4d67f5f1 | ||
|
|
12783fdfdb | ||
|
|
63e1daa706 | ||
|
|
bc8a2b5b20 | ||
|
|
26c3ee4cb6 | ||
|
|
c0e651bf68 | ||
|
|
d801ce21e8 | ||
|
|
025818a042 | ||
|
|
3bda521d62 | ||
|
|
ff6ba8a179 | ||
|
|
2afe0cfccc | ||
|
|
e666247a45 | ||
|
|
dab1ed956f | ||
|
|
0dd21799f9 | ||
|
|
bcfe5e4edd | ||
|
|
4d25a24e53 | ||
|
|
3e63bdd4ce | ||
|
|
465bc88e8f | ||
|
|
6e8b990391 | ||
|
|
6fc6b9f567 | ||
|
|
7ef6975cb3 |
+12
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -1,15 +1,19 @@
|
||||
include $(MAKE_HOME)/defaults.mk
|
||||
include make/defaults.mk
|
||||
|
||||
CONFIG ?= release
|
||||
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)
|
||||
VST2_SDK_PATH ?= $(realpath ./sdk/vst/vstsdk2.4)
|
||||
JUCE_LIBCODE_PATH ?= $(realpath ./JuceLibraryCode)
|
||||
SRC_PATH := $(realpath ./src)
|
||||
|
||||
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
|
||||
CFLAGS += -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
|
||||
|
||||
DEFINES += -D__cdecl=""
|
||||
DEFINES += -DJUCE_GCC=1 -DLINUX=1 -DJUCE_APP_VERSION=1.0.0 -DJUCE_APP_VERSION_HEX=0x10000
|
||||
DEFINES_debug += -DDEBUG=1 -D_DEBUG=1
|
||||
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 -DSYNTH_DEBUG
|
||||
DEFINES_release += -DNDEBUG
|
||||
|
||||
DEFINES += -DJucePlugin_Version=1.0.0
|
||||
DEFINES += -DJucePlugin_VersionCode=0x01000000
|
||||
DEFINES += -DJucePlugin_VersionString=\"1.0.0\"
|
||||
DEFINES += -DJucePlugin_Version=$(APP_VERSION)
|
||||
DEFINES += -DJucePlugin_VersionCode=$(APP_VERSION_HEX)
|
||||
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
|
||||
|
||||
|
||||
all: app
|
||||
app: objects link
|
||||
|
||||
@@ -40,16 +45,27 @@ app: objects link
|
||||
|
||||
objects: ${PACKAGES}
|
||||
|
||||
Synth:
|
||||
@$(MAKE) -C Source/synth
|
||||
synth:
|
||||
@$(MAKE) -C $(SRC_PATH)/synth
|
||||
|
||||
Source:
|
||||
@$(MAKE) -C $@
|
||||
plug:
|
||||
@$(MAKE) -C $(SRC_PATH)/plug
|
||||
|
||||
JuceLibraryCode:
|
||||
@$(MAKE) -C $@
|
||||
|
||||
Fir:
|
||||
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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
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
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
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
@@ -0,0 +1,3 @@
|
||||
Waldorf MicroWave Wellenformen und WaveTables hinzugef�gt. WaveTable-Scan �ber PWM.
|
||||
wave.bin: Original MicroWave Wellenformen m�ssen 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
Executable
BIN
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
@@ -0,0 +1,7 @@
|
||||
include $(MAKE_HOME)/defaults.mk
|
||||
|
||||
# Environment
|
||||
CC=clang
|
||||
CCC=clang++
|
||||
CXX=clang++
|
||||
|
||||
+53
@@ -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])
|
||||
+52
@@ -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])
|
||||
+56
@@ -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;
|
||||
+52
@@ -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;
|
||||
Executable
+18
@@ -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)));
|
||||
Executable
+23
@@ -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)));
|
||||
Executable
+34
@@ -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');
|
||||
|
||||
Executable
+44
@@ -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');
|
||||
|
||||
Executable
+47
@@ -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');
|
||||
|
||||
Executable
+47
@@ -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');
|
||||
|
||||
Executable
+21
@@ -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;
|
||||
Executable
+34
@@ -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')
|
||||
Executable
BIN
Binary file not shown.
Executable
+38
@@ -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;
|
||||
|
||||
|
||||
Executable
+38
@@ -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;
|
||||
|
||||
|
||||
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
+77
@@ -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;
|
||||
Executable
+75
@@ -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;
|
||||
Executable
+116
@@ -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
|
||||
Executable
+116
@@ -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
|
||||
Executable
+33
@@ -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;
|
||||
Executable
+33
@@ -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;
|
||||
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
+96
@@ -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
|
||||
Executable
+90
@@ -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
|
||||
Executable
+105
@@ -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
|
||||
Executable
+145
@@ -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
|
||||
Executable
+103
@@ -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');
|
||||
|
||||
Executable
+116
@@ -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
|
||||
Executable
+90
@@ -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');
|
||||
|
||||
Executable
+128
@@ -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
|
||||
Executable
+68
@@ -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');
|
||||
|
||||
Executable
+92
@@ -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');
|
||||
|
||||
Executable
+88
@@ -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');
|
||||
|
||||
Executable
+125
@@ -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
|
||||
Executable
+107
@@ -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
|
||||
Executable
+11
@@ -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,
|
||||
Executable
+11
@@ -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);
|
||||
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
+66
@@ -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
|
||||
Executable
+13
@@ -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)');
|
||||
|
||||
Executable
+28
@@ -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
|
||||
Executable
+28
@@ -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
|
||||
@@ -0,0 +1,3 @@
|
||||
build
|
||||
JUCE-3.1.1
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ DEFINES += -D${TARGET}
|
||||
|
||||
${OBJS}: $(BUILD_DIR)/%.o : ${PKG_ROOT}/%.cpp
|
||||
mkdir -p $(dir $@)
|
||||
g++ ${CXXFLAGS_${CONFIG}} ${DEFINES} ${INCLUDES} -o $@ -c $<
|
||||
$(CXX) ${CXXFLAGS_${CONFIG}} ${DEFINES} ${INCLUDES} -o $@ -c $<
|
||||
|
||||
${BUILD_DIR}/${BUILD_TARGET}: ${OBJS}
|
||||
ar -q $@ ${OBJS}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
vstsdk2.4
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
CONFIG ?= release
|
||||
PKG_VER := vst_sdk2_4_rev2
|
||||
PKG_VER := vstsdk2.4
|
||||
|
||||
include pkg.mk
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -23,7 +23,7 @@
|
||||
#define __JUCER_HEADER_BUTTONLED_BUTTONLED_B8510B75__
|
||||
|
||||
//[Headers] -- You can add your own extra header files here --
|
||||
#include "../JuceLibraryCode/JuceHeader.h"
|
||||
#include <JuceHeader.h>
|
||||
//[/Headers]
|
||||
|
||||
|
||||
@@ -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
|
||||
#define __JK_MIDICLOCK
|
||||
|
||||
#include "../JuceLibraryCode/JuceHeader.h"
|
||||
#include <JuceHeader.h>
|
||||
|
||||
//#include "Includes.h"
|
||||
|
||||
@@ -23,14 +23,14 @@ class JK_MidiClock
|
||||
public:
|
||||
JK_MidiClock();
|
||||
|
||||
void setPositionJumpThreshold(const double ms) {posChangeThreshold = ms / 1000.0;}
|
||||
double getPositionJumpThreshold() {return posChangeThreshold;}
|
||||
void setFollowSongPosition(const bool shouldFollow) {followSongPosition = shouldFollow;}
|
||||
bool getFollowSongPosition() {return followSongPosition;}
|
||||
void setOffset(const int offset) {ppqOffset = offset;}
|
||||
int getOffset() {return ppqOffset;}
|
||||
void setPositionJumpThreshold(const double ms) {m_posChangeThreshold = ms / 1000.0;}
|
||||
double getPositionJumpThreshold() {return m_posChangeThreshold;}
|
||||
void setFollowSongPosition(const bool shouldFollow) {m_followSongPosition = shouldFollow;}
|
||||
bool getFollowSongPosition() {return m_followSongPosition;}
|
||||
void setOffset(const int offset) {m_ppqOffset = offset;}
|
||||
int getOffset() {return m_ppqOffset;}
|
||||
|
||||
void generateMidiclock(AudioPlayHead::CurrentPositionInfo &lastPosInfo,
|
||||
void generateMidiclock(const AudioPlayHead::CurrentPositionInfo &lastPosInfo,
|
||||
MidiBuffer* midiBuffer,
|
||||
const int bufferSize,
|
||||
const double sampleRate);
|
||||
@@ -45,21 +45,21 @@ private:
|
||||
}
|
||||
|
||||
|
||||
bool wasPlaying;
|
||||
double syncPpqPosition;
|
||||
double posChangeThreshold;
|
||||
double ppqToStartSyncAt;
|
||||
bool followSongPosition;
|
||||
uint8 syncFlag;
|
||||
int ppqOffset;
|
||||
|
||||
bool m_wasPlaying;
|
||||
double m_syncPpqPosition;
|
||||
double m_posChangeThreshold;
|
||||
double m_ppqToStartSyncAt;
|
||||
bool m_followSongPosition;
|
||||
uint8 m_syncFlag;
|
||||
int m_ppqOffset;
|
||||
int m_sample_remain;
|
||||
static const int cycleEnd_ = 1;
|
||||
static const int startSlave_ = 2;
|
||||
|
||||
ScopedPointer <MidiMessage> clockMessage;
|
||||
ScopedPointer <MidiMessage> continueMessage;
|
||||
ScopedPointer <MidiMessage> stopMessage;
|
||||
ScopedPointer <MidiMessage> songPositionMessage;
|
||||
ScopedPointer <MidiMessage> m_clockMessage;
|
||||
ScopedPointer <MidiMessage> m_continueMessage;
|
||||
ScopedPointer <MidiMessage> m_stopMessage;
|
||||
ScopedPointer <MidiMessage> m_songPositionMessage;
|
||||
|
||||
void sendSongPositionPointerMessage(const double ppqPosition, const int posInBuffer, MidiBuffer* buffer);
|
||||
|
||||
@@ -67,6 +67,7 @@ private:
|
||||
const double sampleRate, const double ppqPerSample);
|
||||
|
||||
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);
|
||||
};
|
||||
@@ -9,7 +9,16 @@
|
||||
#include <math.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 "JaySynthVoice.h"
|
||||
#include "JaySynthMonophonicMGR.h"
|
||||
@@ -887,22 +896,16 @@ void JaySynth::handlePitchWheel (const int midiChannel, const int wheelValue)
|
||||
|
||||
}
|
||||
|
||||
void JaySynth::handleController (const int midiChannel,
|
||||
const int controllerNumber,
|
||||
const int controllerValue)
|
||||
void JaySynth::handleController (const midiCC_info_t &midiCC_info)
|
||||
{
|
||||
midiCC_info.channel = midiChannel;
|
||||
midiCC_info.ID = controllerNumber;
|
||||
midiCC_info.value = (synth_float_t)controllerValue/127;
|
||||
last_midiCC_info[midiCC_info.ID] = midiCC_info;
|
||||
listeners.call (&JaySynthListener::synthChanged, SYNTH_CHANGED_MIDICC, (midiCC_info_t*)&midiCC_info);
|
||||
|
||||
last_midiCC_info[controllerNumber] = midiCC_info;
|
||||
listeners.call (&JaySynthListener::synthChanged, SYNTH_CHANGED_MIDICC, &midiCC_info);
|
||||
|
||||
switch (controllerNumber)
|
||||
switch (midiCC_info.ID)
|
||||
{
|
||||
case 0x40: handleSustainPedal (midiChannel, controllerValue >= 64); break;
|
||||
case 0x42: handleSostenutoPedal (midiChannel, controllerValue >= 64); break;
|
||||
case 0x43: handleSoftPedal (midiChannel, controllerValue >= 64); break;
|
||||
case 0x40: handleSustainPedal (midiCC_info.channel, midiCC_info.value_raw >= 64); break;
|
||||
case 0x42: handleSostenutoPedal (midiCC_info.channel, midiCC_info.value_raw >= 64); break;
|
||||
case 0x43: handleSoftPedal (midiCC_info.channel, midiCC_info.value_raw >= 64); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
@@ -912,8 +915,8 @@ void JaySynth::handleController (const int midiChannel,
|
||||
{
|
||||
JaySynthVoice* const voice = voices.getUnchecked (i);
|
||||
|
||||
if (midiChannel <= 0 || voice->isPlayingChannel (midiChannel))
|
||||
voice->controllerMoved (controllerNumber, controllerValue);
|
||||
if (midiCC_info.channel <= 0 || voice->isPlayingChannel (midiCC_info.channel))
|
||||
voice->controllerMoved (midiCC_info.ID, midiCC_info.value_raw);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1087,9 +1090,30 @@ void JaySynth::handleMidiEvent (const MidiMessage& m)
|
||||
}
|
||||
if (m.isController())
|
||||
{
|
||||
handleController (m.getChannel(),
|
||||
m.getControllerNumber(),
|
||||
m.getControllerValue());
|
||||
midiCC_info_t midiCC_info;
|
||||
midiCC_info.channel = m.getChannel();
|
||||
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())
|
||||
{
|
||||
@@ -1128,8 +1152,10 @@ void JaySynth::handleMidiEvent (const MidiMessage& m)
|
||||
if (m.isSongPositionPointer())
|
||||
{
|
||||
SynthDebug("SongPositionPointer\n");
|
||||
m_clock_cnt_bar = (6 * m.getSongPositionPointerMidiBeat()) % m_numMidiClocksPerBar;
|
||||
SynthDebug("getSongPositionPointerMidiBeat(): %u -> %u clocks\n", m.getSongPositionPointerMidiBeat(), m_clock_cnt_bar);
|
||||
double bar_16 = 1 + ((double)m.getSongPositionPointerMidiBeat()/4);
|
||||
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())
|
||||
{
|
||||
@@ -1162,10 +1188,17 @@ void JaySynth::handleMidiEvent (const MidiMessage& m)
|
||||
|
||||
info.bpm = (uint32_t)(bpm + 0.5);
|
||||
info.type = 1;
|
||||
|
||||
if (m_clock_cnt_bar == 0)
|
||||
{
|
||||
info.type = 2;
|
||||
SynthDebug("1111111111111111111111111");
|
||||
}
|
||||
else
|
||||
{
|
||||
SynthDebug("-------------------------");
|
||||
}
|
||||
|
||||
listeners.call (&JaySynthListener::synthChanged, SYNTH_CHANGED_MIDICLOCK, &info);
|
||||
}
|
||||
}
|
||||
@@ -9,11 +9,14 @@
|
||||
#ifndef _JAYSYNTH_H_
|
||||
#define _JAYSYNTH_H_
|
||||
|
||||
#include "../JuceLibraryCode/JuceHeader.h"
|
||||
#include "synth/synth_defs.h"
|
||||
#include "synth/param_scale.h"
|
||||
#include <synth/synth_defs.h>
|
||||
#include <synth/param_scale.h>
|
||||
|
||||
#include <JuceHeader.h>
|
||||
#include "JaySynthVoice.h"
|
||||
#include "JaySynthMonophonicMGR.h"
|
||||
#include "JaySynthMidiCC.h"
|
||||
#include "MidiNrpn.h"
|
||||
|
||||
#define GET_NUM_VOICES max_num_voices
|
||||
|
||||
@@ -44,7 +47,83 @@ private:
|
||||
class JaySynth : public Synthesiser
|
||||
{
|
||||
public:
|
||||
JaySynth(int num_voices, String pathToWaves);
|
||||
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();
|
||||
void setSampleRate (synth_float_t sampleRate);
|
||||
void setBufsize (int bufsize);
|
||||
@@ -57,7 +136,8 @@ public:
|
||||
synth_float_t getVolume(void);
|
||||
int lastPitchWheelValue, lastmidiChannel;
|
||||
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 updateParameter(int paramID);
|
||||
void humanizeModeChanged(void);
|
||||
@@ -145,72 +225,6 @@ public:
|
||||
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:
|
||||
@@ -261,6 +275,7 @@ private:
|
||||
bool m_isMidiClockStarted;
|
||||
|
||||
void updateMidiTiming(const MidiMessage& m);
|
||||
MidiNrpn mMidiNrpn;
|
||||
};
|
||||
|
||||
|
||||
+32
-30
@@ -726,24 +726,6 @@ JaySynthAudioProcessorEditor::JaySynthAudioProcessorEditor (JaySynthAudioProcess
|
||||
m_comboBox_vcf_type->addItem (TRANS("BPF"), 3);
|
||||
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"));
|
||||
m_slider_lfo0_smooth->setTooltip (TRANS("LFO 1 smooth [%]"));
|
||||
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->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"));
|
||||
m_slider_lfo2_smooth->setTooltip (TRANS("LFO 3 smooth [%]"));
|
||||
m_slider_lfo2_smooth->setRange (0, 1, 0);
|
||||
@@ -2497,10 +2497,10 @@ JaySynthAudioProcessorEditor::~JaySynthAudioProcessorEditor()
|
||||
m_label_synth_name = nullptr;
|
||||
m_label_synth_version = nullptr;
|
||||
m_comboBox_vcf_type = nullptr;
|
||||
m_slider_lfo1_smooth = nullptr;
|
||||
m_label_lfo1_smooth = nullptr;
|
||||
m_slider_lfo0_smooth = nullptr;
|
||||
m_label_lfo0_smooth = nullptr;
|
||||
m_slider_lfo1_smooth = nullptr;
|
||||
m_label_lfo1_smooth = nullptr;
|
||||
m_slider_lfo2_smooth = nullptr;
|
||||
m_label_lfo2_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_version->setBounds (978, 662, 132, 24);
|
||||
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_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_label_lfo2_smooth->setBounds (384, 384, 52, 20);
|
||||
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())
|
||||
{
|
||||
// Comboboxes don't support midicontroller assignments
|
||||
if (componentThatWasClicked->getComponentID().contains(String("PARAM_COMBOBOX")))
|
||||
{
|
||||
return;
|
||||
}
|
||||
MidiCC_PopUp_show(componentThatWasClicked);
|
||||
}
|
||||
}
|
||||
@@ -5164,10 +5160,6 @@ void JaySynthAudioProcessorEditor::MidiCC_PopUp_event(int event)
|
||||
switch (event)
|
||||
{
|
||||
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);
|
||||
break;
|
||||
|
||||
@@ -5366,6 +5358,16 @@ void JaySynthAudioProcessorEditor::paramUpdate(int paramID, bool doHostUpdate)
|
||||
if (pButton)
|
||||
{
|
||||
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__
|
||||
|
||||
//[Headers] -- You can add your own extra header files here --
|
||||
#include "../JuceLibraryCode/JuceHeader.h"
|
||||
#include <JuceHeader.h>
|
||||
#include "PluginProcessor.h"
|
||||
#include "ButtonLED.h"
|
||||
#include "MidiCC_PopUp.h"
|
||||
@@ -177,10 +177,10 @@ private:
|
||||
ScopedPointer<Label> m_label_synth_name;
|
||||
ScopedPointer<Label> m_label_synth_version;
|
||||
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<Label> m_label_lfo0_smooth;
|
||||
ScopedPointer<Slider> m_slider_lfo1_smooth;
|
||||
ScopedPointer<Label> m_label_lfo1_smooth;
|
||||
ScopedPointer<Slider> m_slider_lfo2_smooth;
|
||||
ScopedPointer<Label> m_label_lfo2_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"
|
||||
|
||||
//==============================================================================
|
||||
@@ -54,11 +55,21 @@ JaySynthMidiCC::JaySynthMidiCC()
|
||||
/*pmax*/pConstraints->pmax,
|
||||
/*pinterval*/pConstraints->pinterval);
|
||||
|
||||
midiCC_containers[i].doChangeParameter = false;
|
||||
midiCC_containers[i].controllerID = 0;
|
||||
midiCC_containers[i].controllerID = 128 + i;
|
||||
midiCC_containers[i].isAssigned = false;
|
||||
midiCC_containers[i].doChangeParameter = 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
|
||||
paramInfoInit(&midiCC_containers[i].curve_vel, i, pConstraints->pName);
|
||||
paramInfoSet(&midiCC_containers[i].curve_vel,
|
||||
@@ -173,26 +184,13 @@ int JaySynthMidiCC::findParamID_byName(String name)
|
||||
return (int)paramNamedValueSet.getWithDefault (toParameterNameXML(name), var(-1));
|
||||
}
|
||||
|
||||
void JaySynthMidiCC::exportXML(String name)
|
||||
{
|
||||
File file(name);
|
||||
XmlElement xml ("JSYNTH_MIDICC_TABLE_FILE");
|
||||
|
||||
exportXML(&xml);
|
||||
|
||||
file.create();
|
||||
xml.writeToFile (/*const File &destinationFile*/file, /*const String &dtdToUse*/"JSYNTH_MIDICC_TABLE_FILE" /*, const String &encodingType="UTF-8", int lineWrapLength=60*/);
|
||||
}
|
||||
|
||||
void JaySynthMidiCC::exportXML(XmlElement *pXML_doc) const
|
||||
void JaySynthMidiCC::export_midi_cc(XmlElement *pXML) const
|
||||
{
|
||||
int paramID;
|
||||
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
|
||||
pXML_root = pXML_doc->createNewChildElement (String("JSYNTH_MIDICONTROLLER_TABLE"));
|
||||
pXML = pXML_root->createNewChildElement (String("TARGETS"));
|
||||
for (paramID=0; paramID < SYNTH_NUM_PARAMS; paramID++)
|
||||
{
|
||||
pMidiContainer = &midiCC_containers[paramID];
|
||||
@@ -202,29 +200,34 @@ void JaySynthMidiCC::exportXML(XmlElement *pXML_doc) const
|
||||
pXML_PARAM->setAttribute ("IS_ABSOLUTE", pMidiContainer->doChangeParameter);
|
||||
pXML_PARAM->setAttribute ("DO_APPLY_ON_PATCH_INIT", pMidiContainer->doApplyOnPatchInit);
|
||||
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_KEYFOLLOW_ASSIGNED", pMidiContainer->isKeyAssigned);
|
||||
pXML_PARAM->setAttribute ("VELKEY_COMBINE_OP", pMidiContainer->velKeyCombineOP);
|
||||
|
||||
pXML_PARAM_INFO = pXML_PARAM->createNewChildElement (String("RELATIVE"));
|
||||
// pXML_PARAM_INFO->setAttribute ("BASE", String(pMidiContainer->control.base, 10));
|
||||
// pXML_PARAM_INFO->setAttribute ("KEXP", String(pMidiContainer->control.kexp, 10));
|
||||
// pXML_PARAM_INFO->setAttribute ("SCENTER", String(pMidiContainer->control.scenter, 10));
|
||||
pXML_PARAM_INFO->setAttribute ("PMIN", String(pMidiContainer->control.pmin, 10));
|
||||
pXML_PARAM_INFO->setAttribute ("PMAX", String(pMidiContainer->control.pmax, 10));
|
||||
// pXML_PARAM_INFO->setAttribute ("PINTERVAL", String(pMidiContainer->control.pinterval, 10));
|
||||
|
||||
pXML_PARAM_INFO = pXML_PARAM->createNewChildElement (String("ABSOLUTE"));
|
||||
// pXML_PARAM_INFO->setAttribute ("BASE", String(pMidiContainer->param.base, 10));
|
||||
// pXML_PARAM_INFO->setAttribute ("KEXP", String(pMidiContainer->param.kexp, 10));
|
||||
// pXML_PARAM_INFO->setAttribute ("SCENTER", String(pMidiContainer->param.scenter, 10));
|
||||
pXML_PARAM_INFO->setAttribute ("PMIN", String(pMidiContainer->param.pmin, 10));
|
||||
pXML_PARAM_INFO->setAttribute ("PMAX", String(pMidiContainer->param.pmax, 10));
|
||||
// pXML_PARAM_INFO->setAttribute ("PINTERVAL", String(pMidiContainer->param.pinterval, 10));
|
||||
|
||||
pXML_PARAM_INFO = pXML_PARAM->createNewChildElement (String("VELOCITY_CURVE"));
|
||||
// pXML_PARAM_INFO->setAttribute ("BASE", String(pMidiContainer->curve_vel.base, 10));
|
||||
pXML_PARAM_INFO->setAttribute ("KEXP", String(pMidiContainer->curve_vel.kexp, 10));
|
||||
pXML_PARAM_INFO->setAttribute ("SCENTER", String(pMidiContainer->curve_vel.scenter, 10));
|
||||
pXML_PARAM_INFO->setAttribute ("PMIN", String(pMidiContainer->curve_vel.pmin, 10));
|
||||
@@ -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 = pXML_PARAM->createNewChildElement (String("KEYFOLLOW_CURVE"));
|
||||
// pXML_PARAM_INFO->setAttribute ("BASE", String(pMidiContainer->curve_key.base, 10));
|
||||
pXML_PARAM_INFO->setAttribute ("KEXP", String(pMidiContainer->curve_key.kexp, 10));
|
||||
pXML_PARAM_INFO->setAttribute ("SCENTER", String(pMidiContainer->curve_key.scenter, 10));
|
||||
pXML_PARAM_INFO->setAttribute ("PMIN", String(pMidiContainer->curve_key.pmin, 10));
|
||||
pXML_PARAM_INFO->setAttribute ("PMAX", String(pMidiContainer->curve_key.pmax, 10));
|
||||
pXML_PARAM_INFO->setAttribute ("PINTERVAL", String(pMidiContainer->curve_key.pinterval, 10));
|
||||
}
|
||||
|
||||
/*
|
||||
{
|
||||
int i, controllerID, numDst;
|
||||
XmlElement *pXML_dst, *pXML_MIDICC;
|
||||
|
||||
// todo: romove that in future versions
|
||||
pXML = pXML_root->createNewChildElement (String("CONTROLLERS"));
|
||||
// Store MIDI controller assignments
|
||||
for (controllerID=0; controllerID < NUM_MIDI_CONTROLLERS; controllerID++)
|
||||
{
|
||||
pXML_MIDICC = pXML->createNewChildElement (String("MIDICC_") + String(controllerID));
|
||||
pXML_MIDICC->setAttribute ("ID", controllerID);
|
||||
|
||||
pXML_dst = pXML_MIDICC->createNewChildElement (String("TARGETS"));
|
||||
numDst = getNumDestinations(controllerID);
|
||||
for (i=0; i < numDst; i++)
|
||||
{
|
||||
pMidiContainer = getDestination(controllerID, i);
|
||||
pXML_dst->setAttribute (String("PARAM") + String(pMidiContainer->constraints.id), pMidiContainer->constraints.pName);
|
||||
}
|
||||
}
|
||||
}
|
||||
// todo: romove that in future versions
|
||||
*/
|
||||
}
|
||||
|
||||
int JaySynthMidiCC::importXML(String name)
|
||||
{
|
||||
File file(name);
|
||||
XmlDocument xml(file);
|
||||
|
||||
ScopedPointer<XmlElement> pXML_root (xml.getDocumentElement());
|
||||
|
||||
return importXML(pXML_root);
|
||||
}
|
||||
|
||||
int JaySynthMidiCC::importXML(XmlElement const *pXML_doc)
|
||||
int JaySynthMidiCC::import_midi_velkey(XmlElement const *pXML)
|
||||
{
|
||||
int i, paramID;
|
||||
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++)
|
||||
removeDestinations(i);
|
||||
|
||||
pXML_root = pXML_doc->getChildByName ("JSYNTH_MIDICONTROLLER_TABLE");
|
||||
// make sure that it's actually our type of XML object..
|
||||
if (pXML_root)
|
||||
if (pXML)
|
||||
{
|
||||
pXML = pXML_root->getFirstChildElement();
|
||||
while(pXML)
|
||||
pXML_PARAM = pXML->getFirstChildElement();
|
||||
while(pXML_PARAM)
|
||||
{
|
||||
paramID = findParamID_byName(pXML_PARAM->getStringAttribute("NAME"));
|
||||
if (paramID < 0)
|
||||
{
|
||||
pXML_PARAM = pXML_PARAM->getNextElement();
|
||||
continue;
|
||||
}
|
||||
|
||||
pMidiContainer = &midiCC_containers[paramID];
|
||||
pMidiContainer->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();
|
||||
while(pXML_PARAM)
|
||||
@@ -313,83 +388,42 @@ int JaySynthMidiCC::importXML(XmlElement const *pXML_doc)
|
||||
pXML_PARAM_INFO = pXML_PARAM->getChildByName(String("RELATIVE"));
|
||||
if (pXML_PARAM_INFO)
|
||||
{
|
||||
// pMidiContainer->control.base = pXML_PARAM_INFO->getDoubleAttribute("BASE", pMidiContainer->constraints.base);
|
||||
// pMidiContainer->control.kexp = pXML_PARAM_INFO->getDoubleAttribute("KEXP", pMidiContainer->constraints.kexp);
|
||||
// pMidiContainer->control.scenter = pXML_PARAM_INFO->getDoubleAttribute("SCENTER", pMidiContainer->constraints.scenter);
|
||||
pMidiContainer->control.pmin = pXML_PARAM_INFO->getDoubleAttribute("PMIN", pMidiContainer->constraints.pmin);
|
||||
pMidiContainer->control.pmax = pXML_PARAM_INFO->getDoubleAttribute("PMAX", pMidiContainer->constraints.pmax);
|
||||
// pMidiContainer->control.pinterval = pXML_PARAM_INFO->getDoubleAttribute("PINTERVAL", pMidiContainer->constraints.pinterval);
|
||||
}
|
||||
|
||||
pXML_PARAM_INFO = pXML_PARAM->getChildByName(String("ABSOLUTE"));
|
||||
if (pXML_PARAM_INFO)
|
||||
{
|
||||
// pMidiContainer->param.base = pXML_PARAM_INFO->getDoubleAttribute("BASE", pMidiContainer->constraints.base);
|
||||
// pMidiContainer->param.kexp = pXML_PARAM_INFO->getDoubleAttribute("KEXP", pMidiContainer->constraints.kexp);
|
||||
// pMidiContainer->param.scenter = pXML_PARAM_INFO->getDoubleAttribute("SCENTER", pMidiContainer->constraints.scenter);
|
||||
pMidiContainer->param.pmin = pXML_PARAM_INFO->getDoubleAttribute("PMIN", pMidiContainer->constraints.pmin);
|
||||
pMidiContainer->param.pmax = pXML_PARAM_INFO->getDoubleAttribute("PMAX", pMidiContainer->constraints.pmax);
|
||||
// pMidiContainer->param.pinterval = pXML_PARAM_INFO->getDoubleAttribute("PINTERVAL", pMidiContainer->constraints.pinterval);
|
||||
}
|
||||
|
||||
pXML_PARAM_INFO = pXML_PARAM->getChildByName(String("VELOCITY_CURVE"));
|
||||
if (pXML_PARAM_INFO)
|
||||
{
|
||||
// pMidiContainer->curve_vel.base = pXML_PARAM_INFO->getDoubleAttribute("BASE", exp(1.0));
|
||||
pMidiContainer->curve_vel.kexp = pXML_PARAM_INFO->getDoubleAttribute("KEXP", 0);
|
||||
pMidiContainer->curve_vel.scenter = pXML_PARAM_INFO->getDoubleAttribute("SCENTER", 0.5);
|
||||
pMidiContainer->curve_vel.pmin = pXML_PARAM_INFO->getDoubleAttribute("PMIN", 0);
|
||||
pMidiContainer->curve_vel.pmax = pXML_PARAM_INFO->getDoubleAttribute("PMAX", 1);
|
||||
// pMidiContainer->curve_vel.pinterval = pXML_PARAM_INFO->getDoubleAttribute("PINTERVAL", 0);
|
||||
}
|
||||
|
||||
pXML_PARAM_INFO = pXML_PARAM->getChildByName(String("KEYFOLLOW_CURVE"));
|
||||
if (pXML_PARAM_INFO)
|
||||
{
|
||||
// pMidiContainer->curve_key.base = pXML_PARAM_INFO->getDoubleAttribute("BASE", exp(1.0));
|
||||
pMidiContainer->curve_key.kexp = pXML_PARAM_INFO->getDoubleAttribute("KEXP", 0);
|
||||
pMidiContainer->curve_key.scenter = pXML_PARAM_INFO->getDoubleAttribute("SCENTER", 0.5);
|
||||
pMidiContainer->curve_key.pmin = pXML_PARAM_INFO->getDoubleAttribute("PMIN", 0);
|
||||
pMidiContainer->curve_key.pmax = pXML_PARAM_INFO->getDoubleAttribute("PMAX", 1);
|
||||
// pMidiContainer->curve_key.pinterval = pXML_PARAM_INFO->getDoubleAttribute("PINTERVAL", 0);
|
||||
}
|
||||
|
||||
if (pXML_PARAM->getIntAttribute("IS_ASSIGNED", 0))
|
||||
add(pMidiContainer, pXML_PARAM->getIntAttribute("CONTROLLER_ID", 0));
|
||||
else
|
||||
remove(pMidiContainer, pXML_PARAM->getIntAttribute("CONTROLLER_ID", 0));
|
||||
|
||||
pXML_PARAM = pXML_PARAM->getNextElement();
|
||||
}
|
||||
|
||||
// todo: romove that in future versions
|
||||
{
|
||||
int controllerID;
|
||||
XmlElement *pXML_MIDICC, *pXML_DST;
|
||||
|
||||
pXML = pXML->getNextElement();
|
||||
while(pXML)
|
||||
{
|
||||
pXML_MIDICC = pXML->getFirstChildElement();
|
||||
while(pXML_MIDICC)
|
||||
{
|
||||
controllerID = pXML_MIDICC->getIntAttribute("ID");
|
||||
pXML_DST = pXML_MIDICC->getFirstChildElement();
|
||||
if (pXML_DST)
|
||||
{
|
||||
for (i=0; i < pXML_DST->getNumAttributes(); i++)
|
||||
{
|
||||
paramID = findParamID_byName(pXML_DST->getAttributeValue(i));
|
||||
if (paramID < 0)
|
||||
break;
|
||||
pMidiContainer = &midiCC_containers[paramID];
|
||||
add(pMidiContainer, controllerID);
|
||||
}
|
||||
}
|
||||
pXML_MIDICC = pXML_MIDICC->getNextElement();
|
||||
}
|
||||
pXML = pXML->getNextElement();
|
||||
}
|
||||
}
|
||||
// todo: romove that in future versions
|
||||
}
|
||||
}
|
||||
isModified = false;
|
||||
@@ -11,8 +11,17 @@
|
||||
#ifndef _JAYSYNTH_MIDICC_
|
||||
#define _JAYSYNTH_MIDICC_
|
||||
|
||||
#include "../JuceLibraryCode/JuceHeader.h"
|
||||
#include "synth/synth_defs.h"
|
||||
#include <JuceHeader.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
|
||||
@@ -46,10 +55,11 @@ public:
|
||||
bool isMidiCCmodified(void) const;
|
||||
String toParameterNameXML (String const &name) const;
|
||||
int findParamID_byName(String name);
|
||||
void exportXML(String name);
|
||||
void exportXML(XmlElement *pXML_doc) const;
|
||||
int importXML(String name);
|
||||
int importXML(XmlElement const *pXML_doc);
|
||||
void export_midi_cc(XmlElement *pXML_doc) const;
|
||||
int import_midi_cc(XmlElement const *pXML_doc);
|
||||
void export_midi_velkey(XmlElement *pXML_doc) const;
|
||||
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 remove(midiCC_container_t *pObj, int controllerID);
|
||||
struct midiCC_container_t* getAtParamID(int paramID);
|
||||
@@ -11,7 +11,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "synth/synth_defs.h"
|
||||
#include <synth/synth_defs.h>
|
||||
#include "JaySynthMonophonicMGR.h"
|
||||
|
||||
/** A JaySynth voice that just plays incredible sounds.. */
|
||||
@@ -9,9 +9,6 @@
|
||||
#ifndef _JAYSYNTHMONOPHONICMGR_H_
|
||||
#define _JAYSYNTHMONOPHONICMGR_H_
|
||||
|
||||
//#include "../JuceLibraryCode/JuceHeader.h"
|
||||
#include "synth/synth_defs.h"
|
||||
|
||||
class JaySynthMonophonicMGR
|
||||
{
|
||||
public:
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "synth/synth_defs.h"
|
||||
#include <synth/synth_defs.h>
|
||||
#include "JaySynthSound.h"
|
||||
|
||||
JaySynthSound::JaySynthSound()
|
||||
@@ -9,8 +9,17 @@
|
||||
#ifndef _JAYSYNTHSOUND_H_
|
||||
#define _JAYSYNTHSOUND_H_
|
||||
|
||||
#include "../JuceLibraryCode/JuceHeader.h"
|
||||
#include "synth/synth_defs.h"
|
||||
#include <JuceHeader.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"
|
||||
|
||||
//==============================================================================
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user