mirror of
https://github.com/thestk/stk
synced 2026-01-12 04:21:52 +00:00
Compare commits
202 Commits
2.02
...
arielelkin
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
889328c3c1 | ||
|
|
62416d7e3f | ||
|
|
9627701d04 | ||
|
|
9966f06757 | ||
|
|
56bcdc32ed | ||
|
|
2ddc79e3bd | ||
|
|
96b1a72186 | ||
|
|
2a6ada02a7 | ||
|
|
488301223a | ||
|
|
08f71c8fa9 | ||
|
|
e03aa486dd | ||
|
|
5dd605ecfd | ||
|
|
77a5cfa4aa | ||
|
|
77bdb45575 | ||
|
|
ff52b9f0b0 | ||
|
|
fe0f5d7f96 | ||
|
|
e1aa259517 | ||
|
|
95fcd14213 | ||
|
|
a5bef56e76 | ||
|
|
fb50d69e08 | ||
|
|
126ff9d9e1 | ||
|
|
83b75ed339 | ||
|
|
f0f6668f25 | ||
|
|
a506acc708 | ||
|
|
3e42e3db3f | ||
|
|
852bdec0c9 | ||
|
|
9d8673a24e | ||
|
|
57344a11a9 | ||
|
|
00da5562cd | ||
|
|
b02298a9f4 | ||
|
|
d1b4dd485b | ||
|
|
6d5a779879 | ||
|
|
7ea8b10c6a | ||
|
|
0e69055579 | ||
|
|
c2833d356a | ||
|
|
0f16f683c9 | ||
|
|
f3b1f35a8c | ||
|
|
262fe5a2d1 | ||
|
|
5e79513e5a | ||
|
|
f13866e696 | ||
|
|
9533f2bc66 | ||
|
|
8c0ad97a25 | ||
|
|
87461b1471 | ||
|
|
58fc744ea4 | ||
|
|
35f66c806e | ||
|
|
0a7c541cdc | ||
|
|
0e55d2d2b1 | ||
|
|
c1c314e7d6 | ||
|
|
84d947c750 | ||
|
|
05560b102d | ||
|
|
759fc187bc | ||
|
|
46be0d56c3 | ||
|
|
032e76da70 | ||
|
|
aae7f609cf | ||
|
|
d959a1167d | ||
|
|
c9f8c017bc | ||
|
|
6094f40399 | ||
|
|
a2fb59f476 | ||
|
|
f905623d10 | ||
|
|
b196c58c75 | ||
|
|
20b9411a5a | ||
|
|
bc3cfa8fb5 | ||
|
|
d1acfb07ed | ||
|
|
b5f046871b | ||
|
|
1de1f1e63d | ||
|
|
4ce317a5a7 | ||
|
|
2e8a0cdd50 | ||
|
|
5f9f7f6f08 | ||
|
|
a2be4bc721 | ||
|
|
2437623d67 | ||
|
|
0063a57dcb | ||
|
|
cc568a58c1 | ||
|
|
1799064d6f | ||
|
|
540d45dbbd | ||
|
|
222f81c1c1 | ||
|
|
cbb2fea120 | ||
|
|
4e4e8053a5 | ||
|
|
dc2bfe01d0 | ||
|
|
ea52f1f1a8 | ||
|
|
1c5d42e64c | ||
|
|
f1c929a6c4 | ||
|
|
d6dba8859f | ||
|
|
069cc1c339 | ||
|
|
32574e97d6 | ||
|
|
a0638ad024 | ||
|
|
3ad1a59585 | ||
|
|
90c33cae06 | ||
|
|
1ce9b33ca3 | ||
|
|
3caee97842 | ||
|
|
887baf05f8 | ||
|
|
aec65bcb76 | ||
|
|
db6fc1f0df | ||
|
|
1a2509ead9 | ||
|
|
7388163b7c | ||
|
|
3d9bb4051b | ||
|
|
92ca28918f | ||
|
|
32a3b551d8 | ||
|
|
a9a654862f | ||
|
|
a239b58651 | ||
|
|
caf7d2f2eb | ||
|
|
3ee62e42d0 | ||
|
|
afa3069dea | ||
|
|
2c136e82ef | ||
|
|
17b45a1dad | ||
|
|
dbecf1f7f0 | ||
|
|
4c8e0dec43 | ||
|
|
914a76cae0 | ||
|
|
979c6877c9 | ||
|
|
fff3e0b887 | ||
|
|
a027a515af | ||
|
|
1f0cad64dd | ||
|
|
3d3ab8b86a | ||
|
|
e4146d6dae | ||
|
|
79cdf449b5 | ||
|
|
ce076784a4 | ||
|
|
0f6f1c4194 | ||
|
|
b2cefb3b53 | ||
|
|
1468ad7e12 | ||
|
|
eade52ff5c | ||
|
|
4e90d3ffd2 | ||
|
|
b2c4aa87bb | ||
|
|
85ca274a33 | ||
|
|
eccc38a093 | ||
|
|
3ebdbe6977 | ||
|
|
742cf6a202 | ||
|
|
b7cbce0ced | ||
|
|
b5e24dec52 | ||
|
|
8658acabee | ||
|
|
0e7077c0f3 | ||
|
|
e2f4193e1a | ||
|
|
f38bcceed7 | ||
|
|
9e2cad425a | ||
|
|
3e43d5e297 | ||
|
|
8055f1d040 | ||
|
|
5e145ff682 | ||
|
|
042dea6ff7 | ||
|
|
04ba9c694e | ||
|
|
40fe7dae1d | ||
|
|
cafad844ad | ||
|
|
5749dc1c55 | ||
|
|
8284487d4b | ||
|
|
193a8ebb2e | ||
|
|
84cf7c5344 | ||
|
|
11ff75339d | ||
|
|
96543e1b84 | ||
|
|
416c02c83c | ||
|
|
08af1a08b4 | ||
|
|
4c6e8aee76 | ||
|
|
b2fbc4f302 | ||
|
|
7aefe7caff | ||
|
|
00f822e00c | ||
|
|
c2ae82f200 | ||
|
|
72786d0b72 | ||
|
|
32f23f9538 | ||
|
|
b0e8953a6f | ||
|
|
586eeac02e | ||
|
|
1874c0efa9 | ||
|
|
9e6a25d046 | ||
|
|
8912a5c0af | ||
|
|
b017472cdf | ||
|
|
ed754183e3 | ||
|
|
add961c2f4 | ||
|
|
e619de2a65 | ||
|
|
5e68ce4eeb | ||
|
|
ae9e437ae8 | ||
|
|
4699f8ef59 | ||
|
|
80db57e79b | ||
|
|
4078d9309d | ||
|
|
18e210ea94 | ||
|
|
3369940892 | ||
|
|
c57c52c17e | ||
|
|
1bbd2c003a | ||
|
|
80561731fe | ||
|
|
4f0c39e7eb | ||
|
|
b089236578 | ||
|
|
deaabdd041 | ||
|
|
caeaa5778c | ||
|
|
c298839886 | ||
|
|
57e3fe7dae | ||
|
|
4c8691eb08 | ||
|
|
3d0db65b1c | ||
|
|
c8b7b67680 | ||
|
|
72095c0a3d | ||
|
|
e449ac3583 | ||
|
|
a117cd0bb1 | ||
|
|
fc877b87bf | ||
|
|
0aec39260a | ||
|
|
baca57040b | ||
|
|
b6a2202011 | ||
|
|
eccd8c9981 | ||
|
|
d199342e86 | ||
|
|
27d9b79dc7 | ||
|
|
2cbce2d8bd | ||
|
|
a6381b9d38 | ||
|
|
cf06b7598b | ||
|
|
586b0add5f | ||
|
|
6e0d1955a8 | ||
|
|
2f09fcd019 | ||
|
|
81475b04c5 | ||
|
|
3f126af4e5 | ||
|
|
4b6500d3de | ||
|
|
868787a5f9 |
188
.gitignore
vendored
Normal file
188
.gitignore
vendored
Normal file
@@ -0,0 +1,188 @@
|
||||
#####
|
||||
# OS X temporary files that should never be committed
|
||||
#
|
||||
# c.f. http://www.westwind.com/reference/os-x/invisibles.html
|
||||
|
||||
.DS_Store
|
||||
|
||||
# c.f. http://www.westwind.com/reference/os-x/invisibles.html
|
||||
|
||||
.Trashes
|
||||
|
||||
# c.f. http://www.westwind.com/reference/os-x/invisibles.html
|
||||
|
||||
*.swp
|
||||
|
||||
# *.lock - this is used and abused by many editors for many different things.
|
||||
# For the main ones I use (e.g. Eclipse), it should be excluded
|
||||
# from source-control, but YMMV
|
||||
|
||||
*.lock
|
||||
|
||||
#
|
||||
# profile - REMOVED temporarily (on double-checking, this seems incorrect; I can't find it in OS X docs?)
|
||||
#profile
|
||||
|
||||
|
||||
####
|
||||
# Xcode temporary files that should never be committed
|
||||
#
|
||||
# NB: NIB/XIB files still exist even on Storyboard projects, so we want this...
|
||||
|
||||
*~.nib
|
||||
|
||||
|
||||
####
|
||||
# Xcode build files -
|
||||
#
|
||||
# NB: slash on the end, so we only remove the FOLDER, not any files that were badly named "DerivedData"
|
||||
|
||||
DerivedData/
|
||||
|
||||
# NB: slash on the end, so we only remove the FOLDER, not any files that were badly named "build"
|
||||
|
||||
build/
|
||||
|
||||
|
||||
#####
|
||||
# Xcode private settings (window sizes, bookmarks, breakpoints, custom executables, smart groups)
|
||||
#
|
||||
# This is complicated:
|
||||
#
|
||||
# SOMETIMES you need to put this file in version control.
|
||||
# Apple designed it poorly - if you use "custom executables", they are
|
||||
# saved in this file.
|
||||
# 99% of projects do NOT use those, so they do NOT want to version control this file.
|
||||
# ..but if you're in the 1%, comment out the line "*.pbxuser"
|
||||
|
||||
# .pbxuser: http://lists.apple.com/archives/xcode-users/2004/Jan/msg00193.html
|
||||
|
||||
*.pbxuser
|
||||
|
||||
# .mode1v3: http://lists.apple.com/archives/xcode-users/2007/Oct/msg00465.html
|
||||
|
||||
*.mode1v3
|
||||
|
||||
# .mode2v3: http://lists.apple.com/archives/xcode-users/2007/Oct/msg00465.html
|
||||
|
||||
*.mode2v3
|
||||
|
||||
# .perspectivev3: http://stackoverflow.com/questions/5223297/xcode-projects-what-is-a-perspectivev3-file
|
||||
|
||||
*.perspectivev3
|
||||
|
||||
# NB: also, whitelist the default ones, some projects need to use these
|
||||
!default.pbxuser
|
||||
!default.mode1v3
|
||||
!default.mode2v3
|
||||
!default.perspectivev3
|
||||
|
||||
|
||||
####
|
||||
# Xcode 4 - semi-personal settings
|
||||
#
|
||||
#
|
||||
# OPTION 1: ---------------------------------
|
||||
# throw away ALL personal settings (including custom schemes!
|
||||
# - unless they are "shared")
|
||||
#
|
||||
# NB: this is exclusive with OPTION 2 below
|
||||
xcuserdata
|
||||
|
||||
# OPTION 2: ---------------------------------
|
||||
# get rid of ALL personal settings, but KEEP SOME OF THEM
|
||||
# - NB: you must manually uncomment the bits you want to keep
|
||||
#
|
||||
# NB: this *requires* git v1.8.2 or above; you may need to upgrade to latest OS X,
|
||||
# or manually install git over the top of the OS X version
|
||||
# NB: this is exclusive with OPTION 1 above
|
||||
#
|
||||
#xcuserdata/**/*
|
||||
|
||||
# (requires option 2 above): Personal Schemes
|
||||
#
|
||||
#!xcuserdata/**/xcschemes/*
|
||||
|
||||
####
|
||||
# XCode 4 workspaces - more detailed
|
||||
#
|
||||
# Workspaces are important! They are a core feature of Xcode - don't exclude them :)
|
||||
#
|
||||
# Workspace layout is quite spammy. For reference:
|
||||
#
|
||||
# /(root)/
|
||||
# /(project-name).xcodeproj/
|
||||
# project.pbxproj
|
||||
# /project.xcworkspace/
|
||||
# contents.xcworkspacedata
|
||||
# /xcuserdata/
|
||||
# /(your name)/xcuserdatad/
|
||||
# UserInterfaceState.xcuserstate
|
||||
# /xcsshareddata/
|
||||
# /xcschemes/
|
||||
# (shared scheme name).xcscheme
|
||||
# /xcuserdata/
|
||||
# /(your name)/xcuserdatad/
|
||||
# (private scheme).xcscheme
|
||||
# xcschememanagement.plist
|
||||
#
|
||||
#
|
||||
|
||||
####
|
||||
# Xcode 4 - Deprecated classes
|
||||
#
|
||||
# Allegedly, if you manually "deprecate" your classes, they get moved here.
|
||||
#
|
||||
# We're using source-control, so this is a "feature" that we do not want!
|
||||
|
||||
*.moved-aside
|
||||
|
||||
####
|
||||
# Files generated by automake
|
||||
|
||||
Makefile
|
||||
autom4te.cache
|
||||
config.log
|
||||
config.status
|
||||
configure
|
||||
projects/demo/Makefile
|
||||
projects/demo/stk-demo
|
||||
projects/demo/Release
|
||||
projects/demo/Debug
|
||||
projects/effects/Makefile
|
||||
projects/effects/effects
|
||||
projects/effects/Release
|
||||
projects/effects/Debug
|
||||
projects/eguitar/Makefile
|
||||
projects/eguitar/eguitar
|
||||
projects/eguitar/Release
|
||||
projects/eguitar/Debug
|
||||
projects/examples/Makefile
|
||||
projects/examples/audioprobe
|
||||
projects/examples/bethree
|
||||
projects/examples/controlbee
|
||||
projects/examples/crtsine
|
||||
projects/examples/duplex
|
||||
projects/examples/foursine
|
||||
projects/examples/grains
|
||||
projects/examples/inetIn
|
||||
projects/examples/inetOut
|
||||
projects/examples/libMakefile
|
||||
projects/examples/midiprobe
|
||||
projects/examples/play
|
||||
projects/examples/playsmf
|
||||
projects/examples/record
|
||||
projects/examples/rtsine
|
||||
projects/examples/sine
|
||||
projects/examples/sineosc
|
||||
projects/examples/threebees
|
||||
projects/examples/Release
|
||||
projects/examples/Debug
|
||||
projects/ragamatic/Makefile
|
||||
projects/ragamatic/ragamat
|
||||
projects/ragamatic/Release
|
||||
projects/ragamatic/Debug
|
||||
src/libstk.a
|
||||
src/Release
|
||||
src/Debug
|
||||
src/Makefile
|
||||
197
ADSR.cpp
197
ADSR.cpp
@@ -1,197 +0,0 @@
|
||||
/*******************************************/
|
||||
/* ADSR Subclass of the Envelope Class, */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* This is the traditional ADSR (Attack */
|
||||
/* Decay, Sustain, Release) ADSR. */
|
||||
/* It responds to simple KeyOn and KeyOff */
|
||||
/* messages, keeping track of it's state. */
|
||||
/* There are two tick (update value) */
|
||||
/* methods, one returns the value, and */
|
||||
/* other returns the state (0 = A, 1 = D, */
|
||||
/* 2 = S, 3 = R) */
|
||||
/*******************************************/
|
||||
|
||||
#include "ADSR.h"
|
||||
|
||||
ADSR :: ADSR() : Envelope()
|
||||
{
|
||||
target = (MY_FLOAT) 0.0;
|
||||
value = (MY_FLOAT) 0.0;
|
||||
attackRate = (MY_FLOAT) 0.001;
|
||||
decayRate = (MY_FLOAT) 0.001;
|
||||
sustainLevel = (MY_FLOAT) 0.5;
|
||||
releaseRate = (MY_FLOAT) 0.01;
|
||||
state = 0;
|
||||
}
|
||||
|
||||
ADSR :: ~ADSR()
|
||||
{
|
||||
/* Nothing to do here */
|
||||
}
|
||||
|
||||
void ADSR :: keyOn()
|
||||
{
|
||||
target = (MY_FLOAT) 1.0;
|
||||
rate = attackRate;
|
||||
state = 0;
|
||||
}
|
||||
|
||||
void ADSR :: keyOff()
|
||||
{
|
||||
target = (MY_FLOAT) 0.0;
|
||||
rate = releaseRate;
|
||||
state = 3;
|
||||
}
|
||||
|
||||
void ADSR :: setAttackRate(MY_FLOAT aRate)
|
||||
{
|
||||
if (aRate < 0.0) {
|
||||
printf("negative rates not allowed!!, correcting\n");
|
||||
attackRate = -aRate;
|
||||
}
|
||||
else attackRate = aRate;
|
||||
}
|
||||
|
||||
void ADSR :: setDecayRate(MY_FLOAT aRate)
|
||||
{
|
||||
if (aRate < 0.0) {
|
||||
printf("negative rates not allowed!!, correcting\n");
|
||||
decayRate = -aRate;
|
||||
}
|
||||
else decayRate = aRate;
|
||||
}
|
||||
|
||||
void ADSR :: setSustainLevel(MY_FLOAT aLevel)
|
||||
{
|
||||
if (aLevel < 0.0 ) {
|
||||
printf("Sustain level out of range!!, correcting\n");
|
||||
sustainLevel = (MY_FLOAT) 0.0;
|
||||
}
|
||||
else sustainLevel = aLevel;
|
||||
}
|
||||
|
||||
void ADSR :: setReleaseRate(MY_FLOAT aRate)
|
||||
{
|
||||
if (aRate < 0.0) {
|
||||
printf("negative rates not allowed!!, correcting\n");
|
||||
releaseRate = -aRate;
|
||||
}
|
||||
else releaseRate = aRate;
|
||||
}
|
||||
|
||||
void ADSR :: setAttackTime(MY_FLOAT aTime)
|
||||
{
|
||||
if (aTime < 0.0) {
|
||||
printf("negative times not allowed!!, correcting\n");
|
||||
attackRate = ONE_OVER_SRATE / -aTime;
|
||||
}
|
||||
else attackRate = ONE_OVER_SRATE / aTime;
|
||||
}
|
||||
|
||||
void ADSR :: setDecayTime(MY_FLOAT aTime)
|
||||
{
|
||||
if (aTime < 0.0) {
|
||||
printf("negative times not allowed!!, correcting\n");
|
||||
decayRate = ONE_OVER_SRATE / -aTime;
|
||||
}
|
||||
else decayRate = ONE_OVER_SRATE / aTime;
|
||||
}
|
||||
|
||||
void ADSR :: setReleaseTime(MY_FLOAT aTime)
|
||||
{
|
||||
if (aTime < 0.0) {
|
||||
printf("negative times not allowed!!, correcting\n");
|
||||
releaseRate = ONE_OVER_SRATE / -aTime;
|
||||
}
|
||||
else releaseRate = ONE_OVER_SRATE / aTime;
|
||||
}
|
||||
|
||||
void ADSR :: setAllTimes(MY_FLOAT attTime, MY_FLOAT decTime, MY_FLOAT susLevel, MY_FLOAT relTime)
|
||||
{
|
||||
this->setAttackTime(attTime);
|
||||
this->setDecayTime(decTime);
|
||||
this->setSustainLevel(susLevel);
|
||||
this->setReleaseTime(relTime);
|
||||
}
|
||||
|
||||
void ADSR :: setTarget(MY_FLOAT aTarget)
|
||||
{
|
||||
target = aTarget;
|
||||
if (value < target) {
|
||||
state = ATTACK;
|
||||
this->setSustainLevel(target);
|
||||
rate = attackRate;
|
||||
}
|
||||
if (value > target) {
|
||||
this->setSustainLevel(target);
|
||||
state = DECAY;
|
||||
rate = decayRate;
|
||||
}
|
||||
}
|
||||
|
||||
void ADSR :: setValue(MY_FLOAT aValue)
|
||||
{
|
||||
state = SUSTAIN;
|
||||
target = aValue;
|
||||
value = aValue;
|
||||
this->setSustainLevel(aValue);
|
||||
rate = (MY_FLOAT) 0.0;
|
||||
}
|
||||
|
||||
MY_FLOAT ADSR :: tick()
|
||||
{
|
||||
if (state==ATTACK) {
|
||||
value += rate;
|
||||
if (value >= target) {
|
||||
value = target;
|
||||
rate = decayRate;
|
||||
target = sustainLevel;
|
||||
state = DECAY;
|
||||
}
|
||||
}
|
||||
else if (state==DECAY) {
|
||||
value -= decayRate;
|
||||
if (value <= sustainLevel) {
|
||||
value = sustainLevel;
|
||||
rate = (MY_FLOAT) 0.0;
|
||||
state = SUSTAIN;
|
||||
}
|
||||
}
|
||||
else if (state==RELEASE) {
|
||||
value -= releaseRate;
|
||||
if (value <= 0.0) {
|
||||
value = (MY_FLOAT) 0.0;
|
||||
state = 4;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
int ADSR :: informTick()
|
||||
{
|
||||
this->tick();
|
||||
return state;
|
||||
}
|
||||
|
||||
MY_FLOAT ADSR :: lastOut()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
/************ Test Main ************************/
|
||||
/*
|
||||
void main()
|
||||
{
|
||||
long i;
|
||||
ADSR test;
|
||||
|
||||
test.setAttackRate(0.15);
|
||||
test.keyOn();
|
||||
while(test.informTick()==ATTACK) printf("%lf\n",test.tick());
|
||||
test.setDecayRate(0.1);
|
||||
while (test.informTick()==DECAY) printf("%lf\n",test.lastOut());
|
||||
test.setReleaseRate(0.05);
|
||||
test.keyOff();
|
||||
while(test.informTick()==RELEASE) printf("%lf\n",test.lastOut());
|
||||
}
|
||||
*/
|
||||
46
ADSR.h
46
ADSR.h
@@ -1,46 +0,0 @@
|
||||
/*******************************************/
|
||||
/* ADSR Subclass of the Envelope Class, */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* This is the traditional ADSR (Attack */
|
||||
/* Decay, Sustain, Release) envelope. */
|
||||
/* It responds to simple KeyOn and KeyOff */
|
||||
/* messages, keeping track of it's state. */
|
||||
/* There are two tick (update value) */
|
||||
/* methods, one returns the value, and */
|
||||
/* other returns the state (0 = A, 1 = D, */
|
||||
/* 2 = S, 3 = R) */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__ADSR_h)
|
||||
#define __ADSR_h
|
||||
|
||||
#include "Envelope.h"
|
||||
|
||||
class ADSR : public Envelope
|
||||
{
|
||||
protected:
|
||||
MY_FLOAT attackRate;
|
||||
MY_FLOAT decayRate;
|
||||
MY_FLOAT sustainLevel;
|
||||
MY_FLOAT releaseRate;
|
||||
public:
|
||||
ADSR();
|
||||
~ADSR();
|
||||
void keyOn();
|
||||
void keyOff();
|
||||
void setAttackRate(MY_FLOAT aRate);
|
||||
void setDecayRate(MY_FLOAT aRate);
|
||||
void setSustainLevel(MY_FLOAT aLevel);
|
||||
void setReleaseRate(MY_FLOAT aRate);
|
||||
void setAttackTime(MY_FLOAT aTime);
|
||||
void setDecayTime(MY_FLOAT aTime);
|
||||
void setReleaseTime(MY_FLOAT aTime);
|
||||
void setAllTimes(MY_FLOAT attTime, MY_FLOAT decTime, MY_FLOAT susLevel, MY_FLOAT relTime);
|
||||
void setTarget(MY_FLOAT aTarget);
|
||||
void setValue(MY_FLOAT aValue);
|
||||
MY_FLOAT tick();
|
||||
int informTick();
|
||||
MY_FLOAT lastOut();
|
||||
};
|
||||
|
||||
#endif
|
||||
76
AgogoBel.cpp
76
AgogoBel.cpp
@@ -1,76 +0,0 @@
|
||||
/*******************************************/
|
||||
/* AgogoBell SubClass of Modal4 Instrument*/
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* */
|
||||
/* Controls: CONTROL1 = stickHardness */
|
||||
/* CONTROL2 = strikePosition*/
|
||||
/* CONTROL3 = vibFreq */
|
||||
/* MOD_WHEEL= vibAmt */
|
||||
/*******************************************/
|
||||
|
||||
/* Modes measured from my Agogo Bell by FFT: */
|
||||
/* 360, 1470, 2401, 4600 */
|
||||
|
||||
#include "AgogoBel.h"
|
||||
#include "SKINI11.msg"
|
||||
|
||||
AgogoBel :: AgogoBel() : Modal4()
|
||||
{
|
||||
wave = new RawInterp("rawwaves/britestk.raw");
|
||||
wave->normalize();
|
||||
wave->setRate((MY_FLOAT) 7.0); /* hardstick */
|
||||
this->setRatioAndReson(0, (MY_FLOAT) 1.00,(MY_FLOAT) 0.999); /* Set our */
|
||||
this->setRatioAndReson(1, (MY_FLOAT) 4.08,(MY_FLOAT) 0.999); /* resonances */
|
||||
this->setRatioAndReson(2,(MY_FLOAT) 6.669,(MY_FLOAT) 0.999); /* here */
|
||||
this->setRatioAndReson(3,(MY_FLOAT) -3725.0, (MY_FLOAT)0.999); /* (One fixed) */
|
||||
this->setFiltGain(0,(MY_FLOAT) 0.06); /* And filter */
|
||||
this->setFiltGain(1,(MY_FLOAT) 0.05); /* gains too */
|
||||
this->setFiltGain(2,(MY_FLOAT) 0.03);
|
||||
this->setFiltGain(3,(MY_FLOAT) 0.02);
|
||||
directGain = (MY_FLOAT) 0.25;
|
||||
}
|
||||
|
||||
AgogoBel :: ~AgogoBel()
|
||||
{
|
||||
delete wave;
|
||||
}
|
||||
|
||||
void AgogoBel :: setStickHardness(MY_FLOAT hardness)
|
||||
{
|
||||
stickHardness = hardness; /* To an approximation, */
|
||||
wave->setRate((MY_FLOAT) 3.0 + ((MY_FLOAT) 8.0 * stickHardness)); /* hardness <-> center */
|
||||
masterGain = (MY_FLOAT) 1.0; /* freq and amplitude */
|
||||
}
|
||||
|
||||
void AgogoBel :: setStrikePosition(MY_FLOAT position)
|
||||
{
|
||||
MY_FLOAT temp,temp2;
|
||||
temp2 = position * PI;
|
||||
strikePosition = position; /* Hack only first */
|
||||
temp = (MY_FLOAT) sin(0.7 * temp2); /* three modes, */
|
||||
this->setFiltGain(0,(MY_FLOAT) 0.08 * temp); /* leave the other */
|
||||
temp = (MY_FLOAT) sin(0.1 + (5.0 * temp2)); /* fixed. Why? */
|
||||
this->setFiltGain(1,(MY_FLOAT) 0.07 * temp); /* So it doesn't */
|
||||
temp = (MY_FLOAT) sin(0.2 + (7.0 * temp2)); /* sound like a */
|
||||
this->setFiltGain(2,(MY_FLOAT) 0.04 * temp); /* sample! */
|
||||
}
|
||||
|
||||
void AgogoBel :: controlChange(int number, MY_FLOAT value)
|
||||
{
|
||||
#if defined(_debug_)
|
||||
printf("AgogoBel : ControlChange: Number=%i Value=%f\n",number,value);
|
||||
#endif
|
||||
if (number == __SK_StickHardness_)
|
||||
this->setStickHardness(value * NORM_7);
|
||||
else if (number == __SK_StrikePosition_)
|
||||
this->setStrikePosition(value * NORM_7);
|
||||
else if (number == __SK_ModFrequency_)
|
||||
vibr->setFreq((value * NORM_7 * (MY_FLOAT) 12.0));
|
||||
else if (number == __SK_ModWheel_)
|
||||
vibrGain = (value * NORM_7);
|
||||
else if (number == __SK_AfterTouch_Cont_)
|
||||
this->strike(value * NORM_7);
|
||||
else {
|
||||
printf("AgogoBel : Undefined Control Number!!\n");
|
||||
}
|
||||
}
|
||||
26
AgogoBel.h
26
AgogoBel.h
@@ -1,26 +0,0 @@
|
||||
/*******************************************/
|
||||
/* AgogoBell SubClass of Modal4 Instrument*/
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* */
|
||||
/* Controls: CONTROL1 = stickHardness */
|
||||
/* CONTROL2 = strikePosition */
|
||||
/* CONTROL3 = vibFreq */
|
||||
/* MOD_WHEEL= vibAmt */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__AgogoBel_h)
|
||||
#define __AgogoBel_h
|
||||
|
||||
#include "Modal4.h"
|
||||
|
||||
class AgogoBel : public Modal4
|
||||
{
|
||||
public:
|
||||
AgogoBel();
|
||||
~AgogoBel();
|
||||
void setStickHardness(MY_FLOAT hardness);
|
||||
void setStrikePosition(MY_FLOAT position);
|
||||
virtual void controlChange(int number, MY_FLOAT value);
|
||||
};
|
||||
|
||||
#endif
|
||||
71
BeeThree.cpp
71
BeeThree.cpp
@@ -1,71 +0,0 @@
|
||||
/******************************************/
|
||||
/* Hammond(OID) Organ Subclass */
|
||||
/* of Algorithm 8 (TX81Z) Subclass of */
|
||||
/* 4 Operator FM Synth */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/******************************************/
|
||||
|
||||
#include "BeeThree.h"
|
||||
|
||||
BeeThree :: BeeThree() : FM4Alg8()
|
||||
{
|
||||
this->loadWaves("rawwaves/sinewave.raw",
|
||||
"rawwaves/sinewave.raw",
|
||||
"rawwaves/sinewave.raw",
|
||||
"rawwaves/sinewave.raw");
|
||||
this->setRatio(0,(MY_FLOAT) 0.999);
|
||||
this->setRatio(1,(MY_FLOAT) 1.997);
|
||||
this->setRatio(2,(MY_FLOAT) 3.006);
|
||||
this->setRatio(3,(MY_FLOAT) 6.009);
|
||||
gains[0] = __FM4Op_gains[95];
|
||||
gains[1] = __FM4Op_gains[95];
|
||||
gains[2] = __FM4Op_gains[99];
|
||||
gains[3] = __FM4Op_gains[95];
|
||||
adsr[0]->setAllTimes((MY_FLOAT) 0.005,(MY_FLOAT) 0.003,(MY_FLOAT) 1.0,(MY_FLOAT) 0.01);
|
||||
adsr[1]->setAllTimes((MY_FLOAT) 0.005,(MY_FLOAT) 0.003,(MY_FLOAT) 1.0,(MY_FLOAT) 0.01);
|
||||
adsr[2]->setAllTimes((MY_FLOAT) 0.005,(MY_FLOAT) 0.003,(MY_FLOAT) 1.0,(MY_FLOAT) 0.01);
|
||||
adsr[3]->setAllTimes((MY_FLOAT) 0.005,(MY_FLOAT) 0.001,(MY_FLOAT) 0.4,(MY_FLOAT) 0.03);
|
||||
twozero->setGain((MY_FLOAT) 0.1);
|
||||
}
|
||||
|
||||
BeeThree :: ~BeeThree()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void BeeThree :: setFreq(MY_FLOAT frequency)
|
||||
{
|
||||
baseFreq = frequency;
|
||||
waves[0]->setFreq(baseFreq * ratios[0]);
|
||||
waves[1]->setFreq(baseFreq * ratios[1]);
|
||||
waves[2]->setFreq(baseFreq * ratios[2]);
|
||||
waves[3]->setFreq(baseFreq * ratios[3]);
|
||||
}
|
||||
|
||||
MY_FLOAT BeeThree :: tick()
|
||||
{
|
||||
MY_FLOAT temp;
|
||||
if (modDepth > 0.0) {
|
||||
temp = (MY_FLOAT) 1.0 + (modDepth * vibWave->tick() * (MY_FLOAT) 0.1);
|
||||
waves[0]->setFreq(baseFreq * ratios[0] * temp);
|
||||
waves[1]->setFreq(baseFreq * ratios[1] * temp);
|
||||
waves[2]->setFreq(baseFreq * ratios[2] * temp);
|
||||
waves[3]->setFreq(baseFreq * ratios[3] * temp);
|
||||
}
|
||||
lastOutput = FM4Alg8 :: tick();
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
void BeeThree :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
||||
{
|
||||
gains[0] = amp * __FM4Op_gains[95];
|
||||
gains[1] = amp * __FM4Op_gains[95];
|
||||
gains[2] = amp * __FM4Op_gains[99];
|
||||
gains[3] = amp * __FM4Op_gains[95];
|
||||
this->setFreq(freq);
|
||||
this->keyOn();
|
||||
#if defined(_debug_)
|
||||
printf("BeeThree : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
23
BeeThree.h
23
BeeThree.h
@@ -1,23 +0,0 @@
|
||||
/******************************************/
|
||||
/* HammondOid Organ Subclass */
|
||||
/* of Algorithm 8 (TX81Z) Subclass of */
|
||||
/* 4 Operator FM Synth */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__BeeThree_h)
|
||||
#define __BeeThree_h
|
||||
|
||||
#include "FM4Alg8.h"
|
||||
|
||||
class BeeThree : public FM4Alg8
|
||||
{
|
||||
public:
|
||||
BeeThree();
|
||||
~BeeThree();
|
||||
virtual void setFreq(MY_FLOAT frequency);
|
||||
MY_FLOAT tick();
|
||||
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
|
||||
};
|
||||
|
||||
#endif
|
||||
80
BiQuad.cpp
80
BiQuad.cpp
@@ -1,80 +0,0 @@
|
||||
/*******************************************/
|
||||
/* BiQuad (2-pole, 2-zero) Filter Class, */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* See books on filters to understand */
|
||||
/* more about how this works. Nothing */
|
||||
/* out of the ordinary in this version. */
|
||||
/*******************************************/
|
||||
|
||||
#include "BiQuad.h"
|
||||
|
||||
BiQuad :: BiQuad() : Filter()
|
||||
{
|
||||
inputs = (MY_FLOAT *) malloc(2 * MY_FLOAT_SIZE);
|
||||
zeroCoeffs[0] = (MY_FLOAT) 0.0;
|
||||
zeroCoeffs[1] = (MY_FLOAT) 0.0;
|
||||
poleCoeffs[0] = (MY_FLOAT) 0.0;
|
||||
poleCoeffs[1] = (MY_FLOAT) 0.0;
|
||||
gain = (MY_FLOAT) 1.0;
|
||||
this->clear();
|
||||
}
|
||||
|
||||
BiQuad :: ~BiQuad()
|
||||
{
|
||||
free(inputs);
|
||||
}
|
||||
|
||||
void BiQuad :: clear()
|
||||
{
|
||||
inputs[0] = (MY_FLOAT) 0.0;
|
||||
inputs[1] = (MY_FLOAT) 0.0;
|
||||
lastOutput = (MY_FLOAT) 0.0;
|
||||
}
|
||||
|
||||
void BiQuad :: setPoleCoeffs(MY_FLOAT *coeffs)
|
||||
{
|
||||
poleCoeffs[0] = coeffs[0];
|
||||
poleCoeffs[1] = coeffs[1];
|
||||
}
|
||||
|
||||
void BiQuad :: setZeroCoeffs(MY_FLOAT *coeffs)
|
||||
{
|
||||
zeroCoeffs[0] = coeffs[0];
|
||||
zeroCoeffs[1] = coeffs[1];
|
||||
}
|
||||
|
||||
void BiQuad :: setFreqAndReson(MY_FLOAT freq, MY_FLOAT reson)
|
||||
{
|
||||
poleCoeffs[1] = - (reson * reson);
|
||||
poleCoeffs[0] = (MY_FLOAT) 2.0 * reson * (MY_FLOAT) cos(TWO_PI * freq / SRATE);
|
||||
}
|
||||
|
||||
void BiQuad :: setEqualGainZeroes()
|
||||
{
|
||||
zeroCoeffs[1] = (MY_FLOAT) -1.0;
|
||||
zeroCoeffs[0] = (MY_FLOAT) 0.0;
|
||||
}
|
||||
|
||||
void BiQuad :: setGain(MY_FLOAT aValue)
|
||||
{
|
||||
gain = aValue;
|
||||
}
|
||||
|
||||
MY_FLOAT BiQuad :: tick(MY_FLOAT sample) /* Perform Filter Operation */
|
||||
{ /* Biquad is two pole, two zero filter */
|
||||
MY_FLOAT temp; /* Look it up in your favorite DSP text */
|
||||
|
||||
temp = sample * gain; /* Here's the math for the */
|
||||
temp += inputs[0] * poleCoeffs[0]; /* version which implements */
|
||||
temp += inputs[1] * poleCoeffs[1]; /* only 2 state variables. */
|
||||
|
||||
lastOutput = temp; /* This form takes */
|
||||
lastOutput += (inputs[0] * zeroCoeffs[0]); /* 5 multiplies and */
|
||||
lastOutput += (inputs[1] * zeroCoeffs[1]); /* 4 adds */
|
||||
inputs[1] = inputs[0]; /* and 3 moves */
|
||||
inputs[0] = temp; /* like the 2 state-var form*/
|
||||
|
||||
return lastOutput;
|
||||
|
||||
}
|
||||
|
||||
31
BiQuad.h
31
BiQuad.h
@@ -1,31 +0,0 @@
|
||||
/*******************************************/
|
||||
/* BiQuad (2-pole, 2-zero) Filter Class, */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* See books on filters to understand */
|
||||
/* more about how this works. Nothing */
|
||||
/* out of the ordinary in this version. */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__BiQuad_h)
|
||||
#define __BiQuad_h
|
||||
|
||||
#include "Filter.h"
|
||||
|
||||
class BiQuad : public Filter
|
||||
{
|
||||
protected:
|
||||
MY_FLOAT poleCoeffs[2];
|
||||
MY_FLOAT zeroCoeffs[2];
|
||||
public:
|
||||
BiQuad();
|
||||
~BiQuad();
|
||||
void clear();
|
||||
void setPoleCoeffs(MY_FLOAT *coeffs);
|
||||
void setZeroCoeffs(MY_FLOAT *coeffs);
|
||||
void setGain(MY_FLOAT aValue);
|
||||
void setFreqAndReson(MY_FLOAT freq, MY_FLOAT reson);
|
||||
void setEqualGainZeroes();
|
||||
MY_FLOAT tick(MY_FLOAT sample);
|
||||
};
|
||||
|
||||
#endif
|
||||
46
BowTabl.cpp
46
BowTabl.cpp
@@ -1,46 +0,0 @@
|
||||
/***********************************************/
|
||||
/* Simple Bow Table Object, after Smith */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/***********************************************/
|
||||
|
||||
#include "BowTabl.h"
|
||||
|
||||
BowTabl :: BowTabl()
|
||||
{
|
||||
offSet = (MY_FLOAT) 0.0; /* offset is a bias, really not needed unless */
|
||||
/* friction is different in each direction */
|
||||
slope = (MY_FLOAT) 0.1; /* controls width of friction pulse, */
|
||||
/* related to bowForce */
|
||||
}
|
||||
|
||||
BowTabl :: ~BowTabl()
|
||||
{
|
||||
}
|
||||
|
||||
void BowTabl :: setOffset(MY_FLOAT aValue)
|
||||
{
|
||||
offSet = aValue;
|
||||
}
|
||||
|
||||
void BowTabl :: setSlope(MY_FLOAT aValue)
|
||||
{
|
||||
slope = aValue;
|
||||
}
|
||||
|
||||
MY_FLOAT BowTabl :: lookup(MY_FLOAT sample) /* Perform Table Lookup */
|
||||
{ /* sample is differential */
|
||||
/* string vs. bow velocity */
|
||||
MY_FLOAT input;
|
||||
input = sample + offSet; /* add bias to sample */
|
||||
input *= slope; /* scale it */
|
||||
lastOutput = (MY_FLOAT) fabs((double) input) + (MY_FLOAT) 0.75; /* below min delta, friction = 1 */
|
||||
lastOutput = (MY_FLOAT) pow(lastOutput,(MY_FLOAT) -4.0);
|
||||
// if (lastOutput < 0.0 ) lastOutput = 0.0; /* minimum friction is 0.0 */
|
||||
if (lastOutput > 1.0 ) lastOutput = (MY_FLOAT) 1.0; /* maximum friction is 1.0 */
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
MY_FLOAT BowTabl :: lastOut()
|
||||
{
|
||||
return lastOutput;
|
||||
}
|
||||
22
BowTabl.h
22
BowTabl.h
@@ -1,22 +0,0 @@
|
||||
/***********************************************/
|
||||
/* Simple Bow Table Object, after Smith */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/***********************************************/
|
||||
|
||||
#include "Object.h"
|
||||
|
||||
class BowTabl : public Object
|
||||
{
|
||||
protected:
|
||||
MY_FLOAT offSet;
|
||||
MY_FLOAT slope;
|
||||
MY_FLOAT lastOutput;
|
||||
public:
|
||||
BowTabl();
|
||||
~BowTabl();
|
||||
void setOffset(MY_FLOAT aValue);
|
||||
void setSlope(MY_FLOAT aValue);
|
||||
MY_FLOAT lookup(MY_FLOAT sample);
|
||||
MY_FLOAT lastOut();
|
||||
};
|
||||
|
||||
161
Bowed.cpp
161
Bowed.cpp
@@ -1,161 +0,0 @@
|
||||
/******************************************/
|
||||
/* Bowed String model ala Smith */
|
||||
/* after McIntyre, Schumacher, Woodhouse */
|
||||
/* by Perry Cook, 1995-96 */
|
||||
/* */
|
||||
/* This is a waveguide model, and thus */
|
||||
/* relates to various Stanford Univ. */
|
||||
/* and possibly Yamaha and other patents.*/
|
||||
/* */
|
||||
/* Controls: CONTROL1 = bowPressure */
|
||||
/* CONTROL2 = bowPosition */
|
||||
/* CONTROL3 = vibrFreq */
|
||||
/* MOD_WHEEL= vibrGain */
|
||||
/* */
|
||||
/******************************************/
|
||||
|
||||
#include "Bowed.h"
|
||||
#include "SKINI11.msg"
|
||||
|
||||
Bowed :: Bowed(MY_FLOAT lowestFreq)
|
||||
{
|
||||
long length;
|
||||
length = (long) (SRATE / lowestFreq + 1);
|
||||
neckDelay = new DLineL(length);
|
||||
length >>= 1;
|
||||
bridgeDelay = new DLineL(length);
|
||||
bowTabl = new BowTabl;
|
||||
reflFilt = new OnePole;
|
||||
bodyFilt = new BiQuad;
|
||||
vibr = new RawLoop("rawwaves/sinewave.raw");
|
||||
adsr = new ADSR;
|
||||
vibrGain = (MY_FLOAT) 0.0;
|
||||
|
||||
neckDelay->setDelay((MY_FLOAT) 100.0);
|
||||
bridgeDelay->setDelay((MY_FLOAT) 29.0);
|
||||
|
||||
bowTabl->setSlope((MY_FLOAT) 3.0);
|
||||
|
||||
reflFilt->setPole((MY_FLOAT) (0.6 - (0.1 * 22050.0 / SRATE)));
|
||||
reflFilt->setGain((MY_FLOAT) 0.95);
|
||||
|
||||
bodyFilt->setFreqAndReson((MY_FLOAT) 500.0, (MY_FLOAT) 0.85);
|
||||
bodyFilt->setEqualGainZeroes();
|
||||
bodyFilt->setGain((MY_FLOAT) 0.2);
|
||||
|
||||
vibr->normalize();
|
||||
vibr->setFreq((MY_FLOAT) 6.12723);
|
||||
|
||||
adsr->setAllTimes((MY_FLOAT) 0.02,(MY_FLOAT) 0.005,(MY_FLOAT) 0.9,(MY_FLOAT) 0.01);
|
||||
|
||||
betaRatio = (MY_FLOAT) 0.127236;
|
||||
}
|
||||
|
||||
Bowed :: ~Bowed()
|
||||
{
|
||||
delete neckDelay;
|
||||
delete bridgeDelay;
|
||||
delete bowTabl;
|
||||
delete reflFilt;
|
||||
delete bodyFilt;
|
||||
delete vibr;
|
||||
delete adsr;
|
||||
}
|
||||
|
||||
void Bowed :: clear()
|
||||
{
|
||||
neckDelay->clear();
|
||||
bridgeDelay->clear();
|
||||
}
|
||||
|
||||
void Bowed :: setFreq(MY_FLOAT frequency)
|
||||
{
|
||||
baseDelay = SRATE / frequency - (MY_FLOAT) 4.0; /* delay - approx. filter delay */
|
||||
bridgeDelay->setDelay(baseDelay * betaRatio); /* bow to bridge length */
|
||||
neckDelay->setDelay(baseDelay * ((MY_FLOAT) 1.0 - betaRatio)); /* bow to nut (finger) length */
|
||||
}
|
||||
|
||||
void Bowed :: startBowing(MY_FLOAT amplitude, MY_FLOAT rate)
|
||||
{
|
||||
adsr->setRate(rate);
|
||||
adsr->keyOn();
|
||||
maxVelocity = (MY_FLOAT) 0.03 + ((MY_FLOAT) 0.2 * amplitude);
|
||||
}
|
||||
|
||||
void Bowed :: stopBowing(MY_FLOAT rate)
|
||||
{
|
||||
adsr->setRate(rate);
|
||||
adsr->keyOff();
|
||||
}
|
||||
|
||||
void Bowed :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
||||
{
|
||||
this->startBowing(amp,amp * (MY_FLOAT) 0.001);
|
||||
this->setFreq(freq);
|
||||
#if defined(_debug_)
|
||||
printf("Bowed : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Bowed :: noteOff(MY_FLOAT amp)
|
||||
{
|
||||
this->stopBowing(((MY_FLOAT) 1.0 - amp) * (MY_FLOAT) 0.005);
|
||||
#if defined(_debug_)
|
||||
printf("Bowed : NoteOff: Amp=%lf\n",amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Bowed :: setVibrato(MY_FLOAT amount)
|
||||
{
|
||||
vibrGain = amount;
|
||||
}
|
||||
|
||||
MY_FLOAT Bowed :: tick()
|
||||
{
|
||||
MY_FLOAT bowVelocity;
|
||||
MY_FLOAT bridgeRefl=(MY_FLOAT) 0,nutRefl=(MY_FLOAT) 0;
|
||||
MY_FLOAT newVel=(MY_FLOAT) 0,velDiff=(MY_FLOAT) 0,stringVel=(MY_FLOAT) 0;
|
||||
|
||||
bowVelocity = maxVelocity * adsr->tick();
|
||||
|
||||
bridgeRefl = -reflFilt->tick(
|
||||
bridgeDelay->lastOut()); /* Bridge Reflection */
|
||||
nutRefl = -neckDelay->lastOut(); /* Nut Reflection */
|
||||
stringVel = bridgeRefl + nutRefl; /* Sum is String Velocity */
|
||||
velDiff = bowVelocity - stringVel; /* Differential Velocity */
|
||||
newVel = velDiff * bowTabl->lookup(velDiff); /* Non-Lin Bow Function */
|
||||
neckDelay->tick(bridgeRefl + newVel); /* Do string */
|
||||
bridgeDelay->tick(nutRefl + newVel); /* propagations */
|
||||
|
||||
if (vibrGain > 0.0) {
|
||||
neckDelay->setDelay((baseDelay * ((MY_FLOAT) 1.0 - betaRatio)) +
|
||||
(baseDelay * vibrGain*vibr->tick()));
|
||||
}
|
||||
|
||||
lastOutput = bodyFilt->tick(bridgeDelay->lastOut());
|
||||
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
void Bowed :: controlChange(int number, MY_FLOAT value)
|
||||
{
|
||||
#if defined(_debug_)
|
||||
printf("Bowed : ControlChange: Number=%i Value=%f\n",number,value);
|
||||
#endif
|
||||
if (number == __SK_BowPressure_)
|
||||
bowTabl->setSlope((MY_FLOAT) 5.0 - ((MY_FLOAT) 4.0 * value * NORM_7));
|
||||
else if (number == __SK_BowPosition_) {
|
||||
betaRatio = (MY_FLOAT) 0.027236 + ((MY_FLOAT) 0.2 * value * NORM_7);
|
||||
bridgeDelay->setDelay(baseDelay * betaRatio); /* bow to bridge length */
|
||||
neckDelay->setDelay(baseDelay * ((MY_FLOAT) 1.0 - betaRatio)); /* bow to nut (finger) length */
|
||||
}
|
||||
else if (number == __SK_ModFrequency_)
|
||||
vibr->setFreq((value * NORM_7 * (MY_FLOAT) 12.0));
|
||||
else if (number == __SK_ModWheel_)
|
||||
vibrGain = (value * NORM_7 * (MY_FLOAT) 0.4);
|
||||
else if (number == __SK_AfterTouch_Cont_)
|
||||
adsr->setTarget(value * NORM_7);
|
||||
else {
|
||||
printf("Bowed : Undefined Control Number!!\n");
|
||||
}
|
||||
}
|
||||
56
Bowed.h
56
Bowed.h
@@ -1,56 +0,0 @@
|
||||
/******************************************/
|
||||
/* Bowed String model ala Smith */
|
||||
/* after McIntyre, Schumacher, Woodhouse */
|
||||
/* by Perry Cook, 1995-96 */
|
||||
/* */
|
||||
/* This is a waveguide model, and thus */
|
||||
/* relates to various Stanford Univ. */
|
||||
/* and possibly Yamaha and other patents.*/
|
||||
/* */
|
||||
/* Controls: CONTROL1 = bowPressure */
|
||||
/* CONTROL2 = bowPosition */
|
||||
/* CONTROL3 = vibrFreq */
|
||||
/* MOD_WHEEL= vibrGain */
|
||||
/* */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__Bowed_h)
|
||||
#define __Bowed_h
|
||||
|
||||
#include "Instrmnt.h"
|
||||
#include "DLineL.h"
|
||||
#include "BowTabl.h"
|
||||
#include "OnePole.h"
|
||||
#include "BiQuad.h"
|
||||
#include "RawLoop.h"
|
||||
#include "ADSR.h"
|
||||
|
||||
class Bowed : public Instrmnt
|
||||
{
|
||||
protected:
|
||||
DLineL *neckDelay;
|
||||
DLineL *bridgeDelay;
|
||||
BowTabl *bowTabl;
|
||||
OnePole *reflFilt;
|
||||
BiQuad *bodyFilt;
|
||||
RawLoop *vibr;
|
||||
ADSR *adsr;
|
||||
MY_FLOAT maxVelocity;
|
||||
MY_FLOAT baseDelay;
|
||||
MY_FLOAT vibrGain;
|
||||
MY_FLOAT betaRatio;
|
||||
public:
|
||||
Bowed(MY_FLOAT lowestFreq);
|
||||
~Bowed();
|
||||
void clear();
|
||||
void startBowing(MY_FLOAT amplitude,MY_FLOAT rate);
|
||||
void stopBowing(MY_FLOAT rate);
|
||||
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
|
||||
virtual void noteOff(MY_FLOAT amp);
|
||||
virtual void setFreq(MY_FLOAT frequency);
|
||||
void setVibrato(MY_FLOAT amount);
|
||||
virtual void controlChange(int number, MY_FLOAT value);
|
||||
virtual MY_FLOAT tick();
|
||||
};
|
||||
|
||||
#endif
|
||||
131
Brass.cpp
131
Brass.cpp
@@ -1,131 +0,0 @@
|
||||
/******************************************/
|
||||
/* Waveguide Brass Instrument Model ala */
|
||||
/* Cook (TBone, HosePlayer) */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* */
|
||||
/* This is a waveguide model, and thus */
|
||||
/* relates to various Stanford Univ. */
|
||||
/* and possibly Yamaha and other patents.*/
|
||||
/* */
|
||||
/* Controls: CONTROL1 = lipTension */
|
||||
/* CONTROL2 = slideLength */
|
||||
/* CONTROL3 = vibFreq */
|
||||
/* MOD_WHEEL= vibAmt */
|
||||
/******************************************/
|
||||
|
||||
#include "Brass.h"
|
||||
#include "SKINI11.msg"
|
||||
|
||||
Brass :: Brass(MY_FLOAT lowestFreq)
|
||||
{
|
||||
length = (long) (SRATE / lowestFreq + 1);
|
||||
delayLine = new DLineA(length);
|
||||
lipFilter = new LipFilt;
|
||||
dcBlock = new DCBlock;
|
||||
adsr = new ADSR;
|
||||
adsr->setAllTimes((MY_FLOAT) 0.005, (MY_FLOAT) 0.001, (MY_FLOAT) 1.0, (MY_FLOAT) 0.010);
|
||||
vibr = new RawLoop("rawwaves/sinewave.raw");
|
||||
this->clear();
|
||||
|
||||
vibr->normalize();
|
||||
vibr->setFreq((MY_FLOAT) 6.137);
|
||||
vibrGain = (MY_FLOAT) 0.05; /* breath periodic vibrato component */
|
||||
|
||||
maxPressure = (MY_FLOAT) 0.0;
|
||||
}
|
||||
|
||||
Brass :: ~Brass()
|
||||
{
|
||||
delete delayLine;
|
||||
delete lipFilter;
|
||||
delete dcBlock;
|
||||
delete adsr;
|
||||
delete vibr;
|
||||
}
|
||||
|
||||
void Brass :: clear()
|
||||
{
|
||||
delayLine->clear();
|
||||
lipFilter->clear();
|
||||
dcBlock->clear();
|
||||
}
|
||||
|
||||
void Brass :: setFreq(MY_FLOAT frequency)
|
||||
{
|
||||
slideTarget = (SRATE / frequency * (MY_FLOAT) 2.0) + (MY_FLOAT) 3.0;
|
||||
/* fudge correction for filter delays */
|
||||
delayLine->setDelay(slideTarget); /* we'll play a harmonic */
|
||||
lipTarget = frequency;
|
||||
lipFilter->setFreq(frequency);
|
||||
}
|
||||
|
||||
void Brass :: setLip(MY_FLOAT frequency)
|
||||
{
|
||||
lipFilter->setFreq(frequency);
|
||||
}
|
||||
|
||||
void Brass :: startBlowing(MY_FLOAT amplitude,MY_FLOAT rate)
|
||||
{
|
||||
adsr->setAttackRate(rate);
|
||||
maxPressure = amplitude;
|
||||
adsr->keyOn();
|
||||
}
|
||||
|
||||
void Brass :: stopBlowing(MY_FLOAT rate)
|
||||
{
|
||||
adsr->setReleaseRate(rate);
|
||||
adsr->keyOff();
|
||||
}
|
||||
|
||||
void Brass :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
||||
{
|
||||
this->setFreq(freq);
|
||||
this->startBlowing(amp, amp * (MY_FLOAT) 0.001);
|
||||
#if defined(_debug_)
|
||||
printf("Brass : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Brass :: noteOff(MY_FLOAT amp)
|
||||
{
|
||||
this->stopBlowing(amp * (MY_FLOAT) 0.005);
|
||||
#if defined(_debug_)
|
||||
printf("Brass : NoteOff: Amp=%lf\n",amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
MY_FLOAT Brass :: tick()
|
||||
{
|
||||
MY_FLOAT breathPressure;
|
||||
|
||||
breathPressure = maxPressure * adsr->tick();
|
||||
breathPressure += vibrGain * vibr->tick();
|
||||
lastOutput = delayLine->tick( /* bore delay */
|
||||
dcBlock->tick( /* block DC */
|
||||
lipFilter->tick((MY_FLOAT) 0.3 * breathPressure, /* mouth input */
|
||||
(MY_FLOAT) 0.85 * delayLine->lastOut()))); /* and bore reflection */
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
void Brass :: controlChange(int number, MY_FLOAT value)
|
||||
{
|
||||
MY_FLOAT temp;
|
||||
#if defined(_debug_)
|
||||
printf("Brass : ControlChange: Number=%i Value=%f\n",number,value);
|
||||
#endif
|
||||
if (number == __SK_LipTension_) {
|
||||
temp = lipTarget * (MY_FLOAT) pow(4.0,(2.0*value*NORM_7) - 1.0);
|
||||
this->setLip(temp);
|
||||
}
|
||||
else if (number == __SK_SlideLength_)
|
||||
delayLine->setDelay(slideTarget * ((MY_FLOAT) 0.5 + (value * NORM_7)));
|
||||
else if (number == __SK_ModFrequency_)
|
||||
vibr->setFreq((value * NORM_7 * (MY_FLOAT) 12.0));
|
||||
else if (number == __SK_ModWheel_ )
|
||||
vibrGain = (value * NORM_7 * (MY_FLOAT) 0.4);
|
||||
else if (number == __SK_AfterTouch_Cont_)
|
||||
adsr->setTarget(value * NORM_7);
|
||||
else {
|
||||
printf("Brass : Undefined Control Number!!\n");
|
||||
}
|
||||
}
|
||||
53
Brass.h
53
Brass.h
@@ -1,53 +0,0 @@
|
||||
/******************************************/
|
||||
/* Simple Brass Instrument Model ala */
|
||||
/* Cook (TBone, HosePlayer) */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* */
|
||||
/* This is a waveguide model, and thus */
|
||||
/* relates to various Stanford Univ. */
|
||||
/* and possibly Yamaha and other patents.*/
|
||||
/* */
|
||||
/* Controls: CONTROL1 = lipTension */
|
||||
/* CONTROL2 = slideLength */
|
||||
/* CONTROL3 = vibFreq */
|
||||
/* MOD_WHEEL= vibAmt */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__Brass_h)
|
||||
#define __Brass_h
|
||||
|
||||
#include "Instrmnt.h"
|
||||
#include "DLineA.h"
|
||||
#include "LipFilt.h"
|
||||
#include "DCBlock.h"
|
||||
#include "ADSR.h"
|
||||
#include "RawLoop.h"
|
||||
|
||||
class Brass: public Instrmnt
|
||||
{
|
||||
protected:
|
||||
DLineA *delayLine;
|
||||
LipFilt *lipFilter;
|
||||
DCBlock *dcBlock;
|
||||
ADSR *adsr;
|
||||
RawLoop *vibr;
|
||||
long length;
|
||||
MY_FLOAT lipTarget;
|
||||
MY_FLOAT slideTarget;
|
||||
MY_FLOAT vibrGain;
|
||||
MY_FLOAT maxPressure;
|
||||
public:
|
||||
Brass(MY_FLOAT lowestFreq);
|
||||
~Brass();
|
||||
void clear();
|
||||
virtual void setFreq(MY_FLOAT frequency);
|
||||
void setLip(MY_FLOAT frequency);
|
||||
void startBlowing(MY_FLOAT amplitude,MY_FLOAT rate);
|
||||
void stopBlowing(MY_FLOAT rate);
|
||||
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
|
||||
virtual void noteOff(MY_FLOAT amp);
|
||||
virtual void controlChange(int number, MY_FLOAT value);
|
||||
virtual MY_FLOAT tick();
|
||||
};
|
||||
|
||||
#endif
|
||||
126
Clarinet.cpp
126
Clarinet.cpp
@@ -1,126 +0,0 @@
|
||||
/******************************************/
|
||||
/* Waveguide Clarinet model ala Smith */
|
||||
/* after McIntyre, Schumacher, Woodhouse */
|
||||
/* by Perry Cook, 1995-96 */
|
||||
/* */
|
||||
/* This is a waveguide model, and thus */
|
||||
/* relates to various Stanford Univ. */
|
||||
/* and possibly Yamaha and other patents.*/
|
||||
/* */
|
||||
/* Controls: CONTROL1 = reedStiffns */
|
||||
/* CONTROL2 = noiseGain */
|
||||
/* CONTROL3 = vibFreq */
|
||||
/* MOD_WHEEL= vibAmt */
|
||||
/******************************************/
|
||||
|
||||
#include "Clarinet.h"
|
||||
#include "SKINI11.msg"
|
||||
|
||||
Clarinet :: Clarinet(MY_FLOAT lowestFreq)
|
||||
{
|
||||
length = (long) (SRATE / lowestFreq + 1);
|
||||
delayLine = new DLineL(length);
|
||||
reedTable = new ReedTabl;
|
||||
reedTable->setOffset((MY_FLOAT) 0.7);
|
||||
reedTable->setSlope((MY_FLOAT) -0.3);
|
||||
filter = new OneZero;
|
||||
envelope = new Envelope;
|
||||
noise = new Noise;
|
||||
vibr = new RawLoop("rawwaves/sinewave.raw");
|
||||
vibr->normalize();
|
||||
vibr->setFreq((MY_FLOAT) 5.735);
|
||||
outputGain = (MY_FLOAT) 1.0;
|
||||
noiseGain = (MY_FLOAT) 0.2;
|
||||
vibrGain = (MY_FLOAT) 0.1;
|
||||
}
|
||||
|
||||
Clarinet :: ~Clarinet()
|
||||
{
|
||||
delete delayLine;
|
||||
delete reedTable;
|
||||
delete filter;
|
||||
delete envelope;
|
||||
delete noise;
|
||||
delete vibr;
|
||||
}
|
||||
|
||||
void Clarinet :: clear()
|
||||
{
|
||||
delayLine->clear();
|
||||
filter->tick((MY_FLOAT) 0.0);
|
||||
}
|
||||
|
||||
void Clarinet :: setFreq(MY_FLOAT frequency)
|
||||
{
|
||||
delayLine->setDelay /* length - approx filter delay */
|
||||
((SRATE / frequency) * (MY_FLOAT) 0.5 - (MY_FLOAT) 1.5);
|
||||
}
|
||||
|
||||
void Clarinet :: startBlowing(MY_FLOAT amplitude,MY_FLOAT rate)
|
||||
{
|
||||
envelope->setRate(rate);
|
||||
envelope->setTarget(amplitude);
|
||||
}
|
||||
|
||||
void Clarinet :: stopBlowing(MY_FLOAT rate)
|
||||
{
|
||||
envelope->setRate(rate);
|
||||
envelope->setTarget((MY_FLOAT) 0.0);
|
||||
}
|
||||
|
||||
void Clarinet :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
||||
{
|
||||
this->setFreq(freq);
|
||||
this->startBlowing((MY_FLOAT) 0.55 + (amp * (MY_FLOAT) 0.30),amp * (MY_FLOAT) 0.005);
|
||||
outputGain = amp + (MY_FLOAT) 0.001;
|
||||
#if defined(_debug_)
|
||||
printf("Clarinet : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Clarinet :: noteOff(MY_FLOAT amp)
|
||||
{
|
||||
this->stopBlowing(amp * (MY_FLOAT) 0.01);
|
||||
#if defined(_debug_)
|
||||
printf("Clarinet : NoteOff: Amp=%lf\n",amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
MY_FLOAT Clarinet :: tick()
|
||||
{
|
||||
MY_FLOAT pressureDiff;
|
||||
MY_FLOAT breathPressure;
|
||||
|
||||
breathPressure = envelope->tick();
|
||||
breathPressure += breathPressure *
|
||||
noiseGain * noise->tick();
|
||||
breathPressure += breathPressure *
|
||||
vibrGain * vibr->tick();
|
||||
pressureDiff = filter->tick(delayLine->lastOut()); /* differential pressure */
|
||||
pressureDiff = (pressureDiff * (MY_FLOAT) -0.95) - breathPressure; /* of reflected and mouth */
|
||||
lastOutput = delayLine->tick(breathPressure + /* perform scattering */
|
||||
pressureDiff * reedTable->lookup(pressureDiff)); /* in economical way */
|
||||
lastOutput *= outputGain;
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
void Clarinet :: controlChange(int number, MY_FLOAT value)
|
||||
{
|
||||
#if defined(_debug_)
|
||||
printf("Clarinet : ControlChange: Number=%i Value=%f\n",number,value);
|
||||
#endif
|
||||
if (number == __SK_ReedStiffness_)
|
||||
reedTable->setSlope((MY_FLOAT) -0.44 + ((MY_FLOAT) 0.26 * value * NORM_7));
|
||||
else if (number == __SK_NoiseLevel_)
|
||||
noiseGain = (value * NORM_7 * (MY_FLOAT) 0.4);
|
||||
else if (number == __SK_ModFrequency_)
|
||||
vibr->setFreq((value * NORM_7 * (MY_FLOAT) 12.0));
|
||||
else if (number == __SK_ModWheel_)
|
||||
vibrGain = (value * NORM_7 * (MY_FLOAT) 0.5);
|
||||
else if (number == __SK_AfterTouch_Cont_) {
|
||||
envelope->setValue(value * NORM_7);
|
||||
}
|
||||
else {
|
||||
printf("Clarinet : Undefined Control Number!!\n");
|
||||
}
|
||||
}
|
||||
53
Clarinet.h
53
Clarinet.h
@@ -1,53 +0,0 @@
|
||||
/******************************************/
|
||||
/* Clarinet model ala Smith */
|
||||
/* after McIntyre, Schumacher, Woodhouse */
|
||||
/* by Perry Cook, 1995-96 */
|
||||
/* */
|
||||
/* This is a waveguide model, and thus */
|
||||
/* relates to various Stanford Univ. */
|
||||
/* and possibly Yamaha and other patents.*/
|
||||
/* */
|
||||
/* Controls: CONTROL1 = reedStiffns */
|
||||
/* CONTROL2 = noiseGain */
|
||||
/* CONTROL3 = vibFreq */
|
||||
/* MOD_WHEEL= vibAmt */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__Clarinet_h)
|
||||
#define __Clarinet_h
|
||||
|
||||
#include "Instrmnt.h"
|
||||
#include "DLineL.h"
|
||||
#include "ReedTabl.h"
|
||||
#include "OneZero.h"
|
||||
#include "Envelope.h"
|
||||
#include "Noise.h"
|
||||
#include "RawLoop.h"
|
||||
|
||||
class Clarinet : public Instrmnt
|
||||
{
|
||||
protected:
|
||||
DLineL *delayLine;
|
||||
ReedTabl *reedTable;
|
||||
OneZero *filter;
|
||||
Envelope *envelope;
|
||||
Noise *noise;
|
||||
RawLoop *vibr;
|
||||
long length;
|
||||
MY_FLOAT outputGain;
|
||||
MY_FLOAT noiseGain;
|
||||
MY_FLOAT vibrGain;
|
||||
public:
|
||||
Clarinet(MY_FLOAT lowestFreq);
|
||||
~Clarinet();
|
||||
void clear();
|
||||
virtual void setFreq(MY_FLOAT frequency);
|
||||
void startBlowing(MY_FLOAT amplitude,MY_FLOAT rate);
|
||||
void stopBlowing(MY_FLOAT rate);
|
||||
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
|
||||
virtual void noteOff(MY_FLOAT amp);
|
||||
virtual MY_FLOAT tick();
|
||||
virtual void controlChange(int number, MY_FLOAT value);
|
||||
};
|
||||
|
||||
#endif
|
||||
41
DCBlock.cpp
41
DCBlock.cpp
@@ -1,41 +0,0 @@
|
||||
/*******************************************/
|
||||
/* DC Blocking Filter */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* This guy is very helpful in, uh, */
|
||||
/* blocking DC. Needed because a simple */
|
||||
/* low-pass reflection filter allows DC */
|
||||
/* to build up inside recursive */
|
||||
/* structures. */
|
||||
/*******************************************/
|
||||
|
||||
#include "DCBlock.h"
|
||||
|
||||
DCBlock :: DCBlock()
|
||||
{
|
||||
inputs = (MY_FLOAT *) malloc(MY_FLOAT_SIZE);
|
||||
outputs = (MY_FLOAT *) malloc(MY_FLOAT_SIZE);
|
||||
this->clear();
|
||||
|
||||
}
|
||||
|
||||
DCBlock :: ~DCBlock()
|
||||
{
|
||||
free(inputs);
|
||||
free(outputs);
|
||||
}
|
||||
|
||||
void DCBlock :: clear()
|
||||
{
|
||||
outputs[0] = (MY_FLOAT) 0.0;
|
||||
inputs[0] = (MY_FLOAT) 0.0;
|
||||
lastOutput = (MY_FLOAT) 0.0;
|
||||
}
|
||||
|
||||
MY_FLOAT DCBlock :: tick(MY_FLOAT sample)
|
||||
{
|
||||
outputs[0] = sample - inputs[0] + ((MY_FLOAT) 0.99 * outputs[0]);
|
||||
inputs[0] = sample;
|
||||
lastOutput = outputs[0];
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
25
DCBlock.h
25
DCBlock.h
@@ -1,25 +0,0 @@
|
||||
/*******************************************/
|
||||
/* DC Blocking Filter */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* This guy is very helpful in, uh, */
|
||||
/* blocking DC. Needed because a simple */
|
||||
/* low-pass reflection filter allows DC */
|
||||
/* to build up inside recursive */
|
||||
/* structures. */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__DCBlock_h)
|
||||
#define __DCBlock_h
|
||||
|
||||
#include "Filter.h"
|
||||
|
||||
class DCBlock : public Filter
|
||||
{
|
||||
public:
|
||||
DCBlock();
|
||||
~DCBlock();
|
||||
void clear();
|
||||
MY_FLOAT tick(MY_FLOAT sample);
|
||||
};
|
||||
|
||||
#endif
|
||||
105
DLineA.cpp
105
DLineA.cpp
@@ -1,105 +0,0 @@
|
||||
/*******************************************/
|
||||
/* */
|
||||
/* AllPass Interpolating Delay Line */
|
||||
/* Object by Perry R. Cook 1995-96 */
|
||||
/* This one uses a delay line of maximum */
|
||||
/* length specified on creation, and */
|
||||
/* interpolates fractional length using */
|
||||
/* an all-pass filter. This version is */
|
||||
/* more efficient for computing static */
|
||||
/* length delay lines (alpha and coeff */
|
||||
/* are computed only when the length */
|
||||
/* is set, there probably is a more */
|
||||
/* efficient computational form if alpha */
|
||||
/* is changed often (each sample)). */
|
||||
/* */
|
||||
/*******************************************/
|
||||
|
||||
#include "DLineA.h"
|
||||
|
||||
DLineA :: DLineA(long max_length)
|
||||
{
|
||||
long i;
|
||||
length = max_length;
|
||||
inputs = (MY_FLOAT *) malloc(length * MY_FLOAT_SIZE);
|
||||
for (i=0;i<length;i++) inputs[i] = (MY_FLOAT) 0;
|
||||
this->clear();
|
||||
inPoint = 0;
|
||||
outPoint = length >> 1;
|
||||
}
|
||||
|
||||
DLineA :: ~DLineA()
|
||||
{
|
||||
free(inputs);
|
||||
}
|
||||
|
||||
void DLineA :: clear()
|
||||
{
|
||||
long i;
|
||||
for (i=0;i<length;i++) inputs[i] = (MY_FLOAT) 0.0;
|
||||
lastIn = (MY_FLOAT) 0;
|
||||
lastOutput = (MY_FLOAT) 0;
|
||||
}
|
||||
|
||||
void DLineA :: setDelay(MY_FLOAT lag)
|
||||
{
|
||||
MY_FLOAT outputPointer;
|
||||
outputPointer = inPoint - lag + 2; /* outPoint chases inpoint */
|
||||
/* + 2 for interp and other */
|
||||
while (outputPointer<0)
|
||||
outputPointer += length; /* modulo table length */
|
||||
outPoint = (long) outputPointer; /* Integer part of delay */
|
||||
alpha = (MY_FLOAT) 1.0 + outPoint - outputPointer; /* fractional part of delay */
|
||||
if (alpha<0.1) {
|
||||
outputPointer += (MY_FLOAT) 1.0;/* Hack to avoid pole/zero */
|
||||
outPoint += 1; /* cancellation. Keeps allpass */
|
||||
alpha += (MY_FLOAT) 1.0; /* delay in range of .1 to 1.1 */
|
||||
}
|
||||
coeff = ((MY_FLOAT) 1.0 - alpha) /
|
||||
((MY_FLOAT) 1.0 + alpha); /* coefficient for all pass */
|
||||
}
|
||||
|
||||
MY_FLOAT DLineA :: tick(MY_FLOAT sample) /* Take sample, yield sample */
|
||||
{
|
||||
MY_FLOAT temp;
|
||||
inputs[inPoint++] = sample; /* Write input sample */
|
||||
if (inPoint == length) /* Increment input pointer */
|
||||
inPoint -= length; /* modulo length */
|
||||
temp = inputs[outPoint++]; /* filter input */
|
||||
if (outPoint == length) /* Increment output pointer */
|
||||
outPoint -= length; /* modulo length */
|
||||
lastOutput = -coeff * lastOutput; /* delayed output */
|
||||
lastOutput += lastIn + (coeff * temp); /* input + delayed Input */
|
||||
lastIn = temp;
|
||||
return lastOutput; /* save output and return */
|
||||
}
|
||||
|
||||
/************ Test Main Program *****************/
|
||||
/*
|
||||
|
||||
void main()
|
||||
{
|
||||
DLineA delay(140);
|
||||
FILE *fd;
|
||||
MY_FLOAT temp;
|
||||
short data;
|
||||
long i;
|
||||
|
||||
fd = fopen("test.raw","wb");
|
||||
|
||||
delay.setDelay(128);
|
||||
for (i=0;i<4096;i++) {
|
||||
if (i%256 != 0) temp = 0.0; else temp = 1.0;
|
||||
data = (temp + delay.tick(temp)) * 16000.0;
|
||||
fwrite(&data,2,1,fd);
|
||||
}
|
||||
delay.setDelay(64.5);
|
||||
for (i=0;i<4096;i++) {
|
||||
if (i%256 != 0) temp = 0.0; else temp = 1.0;
|
||||
data = (temp + delay.tick(temp)) * 16000.0;
|
||||
fwrite(&data,2,1,fd);
|
||||
}
|
||||
|
||||
fclose(fd);
|
||||
}
|
||||
*/
|
||||
41
DLineA.h
41
DLineA.h
@@ -1,41 +0,0 @@
|
||||
/*******************************************/
|
||||
/* */
|
||||
/* AllPass Interpolating Delay Line */
|
||||
/* Object by Perry R. Cook 1995-96 */
|
||||
/* This one uses a delay line of maximum */
|
||||
/* length specified on creation, and */
|
||||
/* interpolates fractional length using */
|
||||
/* an all-pass filter. This version is */
|
||||
/* more efficient for computing static */
|
||||
/* length delay lines (alpha and coeff */
|
||||
/* are computed only when the length */
|
||||
/* is set, there probably is a more */
|
||||
/* efficient computational form if alpha */
|
||||
/* is changed often (each sample)). */
|
||||
/* */
|
||||
/*******************************************/
|
||||
|
||||
|
||||
#if !defined(__DLineA_h)
|
||||
#define __DLineA_h
|
||||
|
||||
#include "Filter.h"
|
||||
|
||||
class DLineA : public Filter
|
||||
{
|
||||
protected:
|
||||
long inPoint;
|
||||
long outPoint;
|
||||
long length;
|
||||
MY_FLOAT alpha;
|
||||
MY_FLOAT coeff;
|
||||
MY_FLOAT lastIn;
|
||||
public:
|
||||
DLineA(long max_length);
|
||||
~DLineA();
|
||||
void clear();
|
||||
void setDelay(MY_FLOAT length);
|
||||
MY_FLOAT tick(MY_FLOAT sample);
|
||||
};
|
||||
|
||||
#endif
|
||||
90
DLineL.cpp
90
DLineL.cpp
@@ -1,90 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Linearly Interpolating Delay Line */
|
||||
/* Object by Perry R. Cook 1995-96 */
|
||||
/* This one uses a delay line of maximum */
|
||||
/* length specified on creation, and */
|
||||
/* linearly interpolates fractional */
|
||||
/* length. It is designed to be more */
|
||||
/* efficient if the delay length is not */
|
||||
/* changed very often. */
|
||||
/*******************************************/
|
||||
|
||||
#include "DLineL.h"
|
||||
|
||||
DLineL :: DLineL(long max_length)
|
||||
{
|
||||
length = max_length;
|
||||
inputs = (MY_FLOAT *) malloc(length * MY_FLOAT_SIZE);
|
||||
this->clear();
|
||||
outPoint = 0;
|
||||
inPoint = length >> 1;
|
||||
}
|
||||
|
||||
DLineL :: ~DLineL()
|
||||
{
|
||||
free(inputs);
|
||||
}
|
||||
|
||||
void DLineL :: clear()
|
||||
{
|
||||
long i;
|
||||
for (i=0;i<length;i++) inputs[i] = (MY_FLOAT) 0.0;
|
||||
lastOutput = (MY_FLOAT) 0;
|
||||
}
|
||||
|
||||
void DLineL :: setDelay(MY_FLOAT lag)
|
||||
{
|
||||
MY_FLOAT outputPointer;
|
||||
outputPointer = inPoint - lag; /* read chases write, add 1 for interp. */
|
||||
while (outputPointer<0)
|
||||
outputPointer += length; /* modulo maximum length */
|
||||
outPoint = (long) outputPointer; /* integer part */
|
||||
alpha = outputPointer - outPoint; /* fractional part */
|
||||
omAlpha = (MY_FLOAT) 1.0 - alpha; /* 1.0 - fractional part (more efficient) */
|
||||
}
|
||||
|
||||
MY_FLOAT DLineL :: tick(MY_FLOAT sample) /* Take one, yield one */
|
||||
{
|
||||
inputs[inPoint++] = sample; /* Input next sample */
|
||||
if (inPoint == length) /* Check for end condition */
|
||||
inPoint -= length;
|
||||
lastOutput = inputs[outPoint++] * omAlpha; /* first 1/2 of interpolation */
|
||||
if (outPoint<length) { /* Check for end condition */
|
||||
lastOutput += inputs[outPoint] * alpha; /* second 1/2 of interpolation */
|
||||
}
|
||||
else { /* if at end . . . */
|
||||
lastOutput += inputs[0] * alpha; /* second 1/2 of interpolation */
|
||||
outPoint -= length;
|
||||
}
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
/************ Test Main Program *****************/
|
||||
/*
|
||||
|
||||
void main()
|
||||
{
|
||||
DLineL delay(140);
|
||||
FILE *fd;
|
||||
MY_FLOAT temp;
|
||||
short data;
|
||||
long i;
|
||||
|
||||
fd = fopen("test.raw","wb");
|
||||
|
||||
delay.setDelay(128);
|
||||
for (i=0;i<4096;i++) {
|
||||
if (i%256 != 0) temp = 0.0; else temp = 1.0;
|
||||
data = (temp + delay.tick(temp)) * 16000.0;
|
||||
fwrite(&data,2,1,fd);
|
||||
}
|
||||
delay.setDelay(64.5);
|
||||
for (i=0;i<4096;i++) {
|
||||
if (i%256 != 0) temp = 0.0; else temp = 1.0;
|
||||
data = (temp + delay.tick(temp)) * 16000.0;
|
||||
fwrite(&data,2,1,fd);
|
||||
}
|
||||
|
||||
fclose(fd);
|
||||
}
|
||||
*/
|
||||
33
DLineL.h
33
DLineL.h
@@ -1,33 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Linearly Interpolating Delay Line */
|
||||
/* Object by Perry R. Cook 1995-96 */
|
||||
/* This one uses a delay line of maximum */
|
||||
/* length specified on creation, and */
|
||||
/* linearly interpolates fractional */
|
||||
/* length. It is designed to be more */
|
||||
/* efficient if the delay length is not */
|
||||
/* changed very often. */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__DLineL_h)
|
||||
#define __DLineL_h
|
||||
|
||||
#include "Filter.h"
|
||||
|
||||
class DLineL : public Filter
|
||||
{
|
||||
protected:
|
||||
long inPoint;
|
||||
long outPoint;
|
||||
long length;
|
||||
MY_FLOAT alpha;
|
||||
MY_FLOAT omAlpha;
|
||||
public:
|
||||
DLineL(long max_length);
|
||||
~DLineL();
|
||||
void clear();
|
||||
void setDelay(MY_FLOAT length);
|
||||
MY_FLOAT tick(MY_FLOAT sample);
|
||||
};
|
||||
|
||||
#endif
|
||||
80
DLineN.cpp
80
DLineN.cpp
@@ -1,80 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Non-Interpolating Delay Line */
|
||||
/* Object by Perry R. Cook 1995-96 */
|
||||
/* This one uses a delay line of maximum */
|
||||
/* length specified on creation. A non- */
|
||||
/* interpolating delay line should be */
|
||||
/* used in non-time varying (reverb) or */
|
||||
/* non-critical (????) applications. */
|
||||
/*******************************************/
|
||||
|
||||
#include "DLineN.h"
|
||||
|
||||
DLineN :: DLineN(long max_length)
|
||||
{
|
||||
length = max_length;
|
||||
inputs = (MY_FLOAT *) malloc(length * MY_FLOAT_SIZE);
|
||||
this->clear();
|
||||
this->setDelay(length * (MY_FLOAT) 0.5);
|
||||
inPoint = 0;
|
||||
outPoint = 0;
|
||||
}
|
||||
|
||||
DLineN :: ~DLineN()
|
||||
{
|
||||
free(inputs);
|
||||
}
|
||||
|
||||
void DLineN :: clear()
|
||||
{
|
||||
long i;
|
||||
for (i=0;i<length;i++) inputs[i] = (MY_FLOAT) 0.0;
|
||||
lastOutput = (MY_FLOAT) 0;
|
||||
}
|
||||
|
||||
void DLineN :: setDelay(MY_FLOAT lag)
|
||||
{
|
||||
outPoint = inPoint - (long) lag; /* read chases write */
|
||||
while (outPoint<0) outPoint += length; /* modulo maximum length */
|
||||
}
|
||||
|
||||
MY_FLOAT DLineN :: tick(MY_FLOAT sample) /* Take one, yield one */
|
||||
{
|
||||
inputs[inPoint++] = sample; /* Input next sample */
|
||||
if (inPoint == length) /* Check for end condition */
|
||||
inPoint -= length;
|
||||
lastOutput = inputs[outPoint++]; // first 1/2 of interpolation */
|
||||
if (outPoint>=length) { // Check for end condition */
|
||||
outPoint -= length;
|
||||
}
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
/************ Test Main Program *****************/
|
||||
/*
|
||||
void main()
|
||||
{
|
||||
DLineN delay(140);
|
||||
FILE *fd;
|
||||
MY_FLOAT temp;
|
||||
short data;
|
||||
long i;
|
||||
|
||||
fd = fopen("test.raw","wb");
|
||||
|
||||
delay.setDelay(128);
|
||||
for (i=0;i<4096;i++) {
|
||||
if (i%256 != 0) temp = 0.0; else temp = 1.0;
|
||||
data = (temp + delay.tick(temp)) * 16000.0;
|
||||
fwrite(&data,2,1,fd);
|
||||
}
|
||||
delay.setDelay(64.5);
|
||||
for (i=0;i<4096;i++) {
|
||||
if (i%256 != 0) temp = 0.0; else temp = 1.0;
|
||||
data = (temp + delay.tick(temp)) * 16000.0;
|
||||
fwrite(&data,2,1,fd);
|
||||
}
|
||||
|
||||
fclose(fd);
|
||||
}
|
||||
*/
|
||||
31
DLineN.h
31
DLineN.h
@@ -1,31 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Non-Interpolating Delay Line */
|
||||
/* Object by Perry R. Cook 1995-96 */
|
||||
/* This one uses a delay line of maximum */
|
||||
/* length specified on creation. A non- */
|
||||
/* interpolating delay line should be */
|
||||
/* used in non-time varying (reverb) or */
|
||||
/* non-critical (????) applications. */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__DLineN_h)
|
||||
#define __DLineN_h
|
||||
|
||||
#include "Filter.h"
|
||||
|
||||
class DLineN : public Filter
|
||||
{
|
||||
protected:
|
||||
long inPoint;
|
||||
long outPoint;
|
||||
long length;
|
||||
public:
|
||||
DLineN(long max_length);
|
||||
~DLineN();
|
||||
void clear();
|
||||
void setDelay(MY_FLOAT length);
|
||||
MY_FLOAT tick(MY_FLOAT sample);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
171
DrumSynt.cpp
171
DrumSynt.cpp
@@ -1,171 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Master Class for Drum Synthesizer */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* This instrument contains a bunch of */
|
||||
/* RawWave objects, run through a bunch */
|
||||
/* of one-pole filters. All the */
|
||||
/* corresponding rawwave files have been */
|
||||
/* sampled at 22050 Hz. Thus, if the */
|
||||
/* compile-time SRATE = 22050, then */
|
||||
/* RawShot objects are used. Otherwise, */
|
||||
/* RawInterp objects are used. You can */
|
||||
/* specify the maximum Polyphony (maximum */
|
||||
/* number of simultaneous voices) in a */
|
||||
/* #define in the .h file. */
|
||||
/* */
|
||||
/* Modified for RawWave abstract class */
|
||||
/* by Gary P. Scavone (11/11/98) */
|
||||
/*******************************************/
|
||||
|
||||
#include "DrumSynt.h"
|
||||
#include <string.h>
|
||||
|
||||
/* Not really General MIDI yet. Coming soon. */
|
||||
unsigned char genMIDIMap[128] = { 0,0,0,0,0,0,0,0, // 0-7
|
||||
0,0,0,0,0,0,0,0, // 8-15
|
||||
0,0,0,0,0,0,0,0, // 16-23
|
||||
0,0,0,0,0,0,0,0, // 24-31
|
||||
0,0,0,0,1,0,2,0, // 32-39
|
||||
2,3,6,3,6,4,7,4, // 40-47
|
||||
5,8,5,0,0,0,10,0, // 48-55
|
||||
9,0,0,0,0,0,0,0, // 56-63
|
||||
0,0,0,0,0,0,0,0, // 64-71
|
||||
0,0,0,0,0,0,0,0, // 72-79
|
||||
0,0,0,0,0,0,0,0, // 80-87
|
||||
0,0,0,0,0,0,0,0, // 88-95
|
||||
0,0,0,0,0,0,0,0, // 96-103
|
||||
0,0,0,0,0,0,0,0, // 104-111
|
||||
0,0,0,0,0,0,0,0, // 112-119
|
||||
0,0,0,0,0,0,0,0}; // 120-127
|
||||
|
||||
char waveNames[DRUM_NUMWAVES][16] = {
|
||||
"dope.raw",
|
||||
"bassdrum.raw",
|
||||
"snardrum.raw",
|
||||
"tomlowdr.raw",
|
||||
"tommiddr.raw",
|
||||
"tomhidrm.raw",
|
||||
"hihatcym.raw",
|
||||
"ridecymb.raw",
|
||||
"crashcym.raw",
|
||||
"cowbell1.raw",
|
||||
"tambourn.raw"
|
||||
};
|
||||
|
||||
DrumSynt :: DrumSynt() : Instrmnt()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0;i<DRUM_POLYPHONY;i++) {
|
||||
filters[i] = new OnePole;
|
||||
sounding[i] = -1;
|
||||
}
|
||||
/* This counts the number of sounding voices */
|
||||
numSounding = 0;
|
||||
|
||||
/* Print warning about aliasing if SRATE < 22050 */
|
||||
if (SRATE < 22050) {
|
||||
printf("\nWarning: DrumSynt is designed for sampling rates of\n");
|
||||
printf("22050 Hz or greater. You will likely encounter aliasing\n");
|
||||
printf("at the current sampling rate of %.0f Hz.\n\n", SRATE);
|
||||
}
|
||||
}
|
||||
|
||||
DrumSynt :: ~DrumSynt()
|
||||
{
|
||||
int i;
|
||||
for ( i=0; i<numSounding-1; i++ ) delete waves[i];
|
||||
for ( i=0; i<DRUM_POLYPHONY; i++ ) delete filters[i];
|
||||
}
|
||||
|
||||
void DrumSynt :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
||||
{
|
||||
int i, notDone;
|
||||
int noteNum;
|
||||
int vel;
|
||||
char tempString[64];
|
||||
RawWave *tempWv;
|
||||
OnePole *tempFilt;
|
||||
|
||||
/* Yes I know, this is tres kludgey */
|
||||
noteNum = (int) ((12*log(freq/220)/log(2)) + 57.01);
|
||||
vel = (int) (amp * 127);
|
||||
|
||||
#if defined(_debug_)
|
||||
printf("NoteOn: %s vel=%i\n",waveNames[genMIDIMap[noteNum]],vel);
|
||||
#endif
|
||||
|
||||
notDone = -1;
|
||||
for (i=0;i<DRUM_POLYPHONY;i++) { /* Check first to see */
|
||||
if (sounding[i] == noteNum) notDone = i; /* if there's already */
|
||||
} /* one like this sounding */
|
||||
|
||||
if (notDone<0) { /* If not, then */
|
||||
if (numSounding == DRUM_POLYPHONY) { /* If we're already */
|
||||
delete waves[0]; /* at max polyphony, */
|
||||
filters[0]->clear(); /* then */
|
||||
tempWv = waves[0];
|
||||
tempFilt = filters[0];
|
||||
for (i=0;i<DRUM_POLYPHONY-1;i++) { /* preempt oldest */
|
||||
waves[i] = waves[i+1]; /* voice and */
|
||||
filters[i] = filters[i+1]; /* ripple all down */
|
||||
}
|
||||
waves[DRUM_POLYPHONY-1] = tempWv;
|
||||
filters[DRUM_POLYPHONY-1] = tempFilt;
|
||||
} else {
|
||||
numSounding += 1; /* otherwise just add one */
|
||||
}
|
||||
|
||||
sounding[numSounding-1] = noteNum; /* allocate new wave */
|
||||
strcpy(tempString,"rawwaves/");
|
||||
strcat(tempString,waveNames[genMIDIMap[noteNum]]);
|
||||
if (SRATE == 22050) {
|
||||
waves[numSounding-1] = new RawShot(tempString);
|
||||
} else {
|
||||
waves[numSounding-1] = new RawInterp(tempString);
|
||||
waves[numSounding-1]->setRate((MY_FLOAT) (22050.0/SRATE));
|
||||
}
|
||||
waves[numSounding-1]->normalize((MY_FLOAT) 0.4);
|
||||
filters[numSounding-1]->setPole((MY_FLOAT) 0.999 - ((MY_FLOAT) vel * NORM_7 * 0.6));
|
||||
filters[numSounding-1]->setGain(vel / (MY_FLOAT) 128.0);
|
||||
}
|
||||
else {
|
||||
waves[notDone]->reset();
|
||||
filters[notDone]->setPole((MY_FLOAT) 0.999 - ((MY_FLOAT) vel * NORM_7 * 0.6));
|
||||
filters[notDone]->setGain(vel / (MY_FLOAT) 128.0);
|
||||
}
|
||||
|
||||
#if defined(_debug_)
|
||||
printf("Number Sounding = %i\n",numSounding);
|
||||
for (i=0;i<numSounding;i++) printf(" %i ",sounding[i]);
|
||||
printf("\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
MY_FLOAT DrumSynt :: tick()
|
||||
{
|
||||
int j, i = 0;
|
||||
MY_FLOAT output = 0.0;
|
||||
OnePole *tempFilt;
|
||||
|
||||
while (i < numSounding) {
|
||||
output += filters[i]->tick(waves[i]->lastOut());
|
||||
if (waves[i]->informTick() == 1) {
|
||||
delete waves[i];
|
||||
tempFilt = filters[i];
|
||||
|
||||
for (j=i;j<numSounding-1;j++) {
|
||||
sounding[j] = sounding[j+1];
|
||||
waves[j] = waves[j+1];
|
||||
filters[j] = filters[j+1];
|
||||
}
|
||||
filters[j] = tempFilt;
|
||||
filters[j]->clear();
|
||||
sounding[j] = -1;
|
||||
numSounding -= 1;
|
||||
i -= 1;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
46
DrumSynt.h
46
DrumSynt.h
@@ -1,46 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Master Class for Drum Synthesizer */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* This instrument contains a bunch of */
|
||||
/* RawWave objects, run through a bunch */
|
||||
/* of one-pole filters. All the */
|
||||
/* corresponding rawwave files have been */
|
||||
/* sampled at 22050 Hz. Thus, if the */
|
||||
/* compile-time SRATE = 22050, then */
|
||||
/* RawShot objects are used. Otherwise, */
|
||||
/* RawInterp objects are used. You can */
|
||||
/* specify the maximum Polyphony (maximum */
|
||||
/* number of simultaneous voices) in a */
|
||||
/* #define in the .h file. */
|
||||
/* */
|
||||
/* Modified for RawWave abstract class */
|
||||
/* by Gary P. Scavone (11/11/98) */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__DrumSynt_h)
|
||||
#define __DrumSynt_h
|
||||
|
||||
#include "Instrmnt.h"
|
||||
#include "RawWave.h"
|
||||
#include "RawShot.h"
|
||||
#include "RawInterp.h"
|
||||
#include "OnePole.h"
|
||||
|
||||
#define DRUM_NUMWAVES 11
|
||||
#define DRUM_POLYPHONY 4
|
||||
|
||||
class DrumSynt : public Instrmnt
|
||||
{
|
||||
protected:
|
||||
RawWave *waves[DRUM_POLYPHONY];
|
||||
OnePole *filters[DRUM_POLYPHONY];
|
||||
int sounding[DRUM_POLYPHONY];
|
||||
int numSounding;
|
||||
public:
|
||||
DrumSynt();
|
||||
~DrumSynt();
|
||||
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
|
||||
virtual MY_FLOAT tick();
|
||||
};
|
||||
|
||||
#endif
|
||||
121
Envelope.cpp
121
Envelope.cpp
@@ -1,121 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Envelope Class, Perry R. Cook, 1995-96 */
|
||||
/* This is the base class for envelopes. */
|
||||
/* This one is capable of ramping state */
|
||||
/* from where it is to a target value by */
|
||||
/* a rate. It also responds to simple */
|
||||
/* KeyOn and KeyOff messages, ramping to */
|
||||
/* 1.0 on keyon and to 0.0 on keyoff. */
|
||||
/* There are two tick (update value) */
|
||||
/* methods, one returns the value, and */
|
||||
/* other returns 0 if the envelope is at */
|
||||
/* the target value (the state bit). */
|
||||
/*******************************************/
|
||||
|
||||
#include "Envelope.h"
|
||||
|
||||
Envelope :: Envelope() : Object()
|
||||
{
|
||||
target = (MY_FLOAT) 0.0;
|
||||
value = (MY_FLOAT) 0.0;
|
||||
rate = (MY_FLOAT) 0.001;
|
||||
state = 0;
|
||||
}
|
||||
|
||||
Envelope :: ~Envelope()
|
||||
{
|
||||
}
|
||||
|
||||
void Envelope :: keyOn()
|
||||
{
|
||||
target = (MY_FLOAT) 1.0;
|
||||
if (value != target) state = 1;
|
||||
}
|
||||
|
||||
void Envelope :: keyOff()
|
||||
{
|
||||
target = (MY_FLOAT) 0.0;
|
||||
if (value != target) state = 1;
|
||||
}
|
||||
|
||||
void Envelope :: setRate(MY_FLOAT aRate)
|
||||
{
|
||||
if (aRate < 0.0) {
|
||||
printf("negative rates not allowed!!, correcting\n");
|
||||
rate = -aRate;
|
||||
}
|
||||
else rate = aRate;
|
||||
}
|
||||
|
||||
void Envelope :: setTime(MY_FLOAT aTime)
|
||||
{
|
||||
if (aTime < 0.0) {
|
||||
printf("negative times not allowed!!, correcting\n");
|
||||
rate = ONE_OVER_SRATE / -aTime ;
|
||||
}
|
||||
else rate = ONE_OVER_SRATE / aTime ;
|
||||
}
|
||||
|
||||
void Envelope :: setTarget(MY_FLOAT aTarget)
|
||||
{
|
||||
target = aTarget;
|
||||
if (value != target) state = 1;
|
||||
}
|
||||
|
||||
void Envelope :: setValue(MY_FLOAT aValue)
|
||||
{
|
||||
state = 0;
|
||||
target = aValue;
|
||||
value = aValue;
|
||||
}
|
||||
|
||||
MY_FLOAT Envelope :: tick()
|
||||
{
|
||||
if (state) {
|
||||
if (target > value) {
|
||||
value += rate;
|
||||
if (value >= target) {
|
||||
value = target;
|
||||
state = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
value -= rate;
|
||||
if (value <= target) {
|
||||
value = target;
|
||||
state = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
int Envelope :: informTick()
|
||||
{
|
||||
this->tick();
|
||||
return state;
|
||||
}
|
||||
|
||||
MY_FLOAT Envelope :: lastOut()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
/************ Test Main ************************/
|
||||
/*
|
||||
void main()
|
||||
{
|
||||
long i;
|
||||
Envelope test;
|
||||
|
||||
test.setRate(0.15);
|
||||
test.keyOn();
|
||||
for (i=0;i<10;i++) printf("%lf\n",test.tick());
|
||||
test.setRate(0.1);
|
||||
test.setTarget(0.5);
|
||||
while (test.informTick()) printf("%lf\n",test.lastOut());
|
||||
test.setRate(0.05);
|
||||
test.keyOff();
|
||||
while(test.informTick()) printf("%lf\n",test.lastOut());
|
||||
}
|
||||
*/
|
||||
41
Envelope.h
41
Envelope.h
@@ -1,41 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Envelope Class, Perry R. Cook, 1995-96 */
|
||||
/* This is the base class for envelopes. */
|
||||
/* This one is capable of ramping state */
|
||||
/* from where it is to a target value by */
|
||||
/* a rate. It also responds to simple */
|
||||
/* KeyOn and KeyOff messages, ramping to */
|
||||
/* 1.0 on keyon and to 0.0 on keyoff. */
|
||||
/* There are two tick (update value) */
|
||||
/* methods, one returns the value, and */
|
||||
/* other returns 0 if the envelope is at */
|
||||
/* the target value (the state bit). */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__Envelope_h)
|
||||
#define __Envelope_h
|
||||
|
||||
#include "Object.h"
|
||||
|
||||
class Envelope : public Object
|
||||
{
|
||||
protected:
|
||||
MY_FLOAT value;
|
||||
MY_FLOAT target;
|
||||
MY_FLOAT rate;
|
||||
int state;
|
||||
public:
|
||||
Envelope();
|
||||
virtual ~Envelope();
|
||||
void keyOn();
|
||||
void keyOff();
|
||||
void setRate(MY_FLOAT aRate);
|
||||
void setTime(MY_FLOAT aTime);
|
||||
void setTarget(MY_FLOAT aTarget);
|
||||
void setValue(MY_FLOAT aValue);
|
||||
MY_FLOAT tick();
|
||||
int informTick();
|
||||
MY_FLOAT lastOut();
|
||||
};
|
||||
|
||||
#endif
|
||||
56
FM4Alg3.cpp
56
FM4Alg3.cpp
@@ -1,56 +0,0 @@
|
||||
/******************************************/
|
||||
/* Algorithm 3 (TX81Z) Subclass of */
|
||||
/* 4 Operator FM Synth */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* */
|
||||
/* Alg 3 is : 4--\ */
|
||||
/* 3-->2-- + -->1-->Out */
|
||||
/* */
|
||||
/* Controls: control1 = total mod index */
|
||||
/* control2 = crossfade of two */
|
||||
/* modulators */
|
||||
/* control3 = LFO speed */
|
||||
/* modWheel = LFO amount */
|
||||
/* */
|
||||
/******************************************/
|
||||
|
||||
#include "FM4Alg3.h"
|
||||
|
||||
FM4Alg3 :: FM4Alg3() : FM4Op()
|
||||
{
|
||||
/* We still don't make the waves here yet, because */
|
||||
/* we still don't know what they will be. */
|
||||
}
|
||||
|
||||
FM4Alg3 :: ~FM4Alg3()
|
||||
{
|
||||
}
|
||||
|
||||
MY_FLOAT FM4Alg3 :: tick()
|
||||
{
|
||||
MY_FLOAT temp;
|
||||
|
||||
temp = vibWave->tick() * modDepth * (MY_FLOAT) 0.2;
|
||||
waves[0]->setFreq(baseFreq * ((MY_FLOAT) 1.0 + temp) * ratios[0]);
|
||||
waves[1]->setFreq(baseFreq * ((MY_FLOAT) 1.0 + temp) * ratios[1]);
|
||||
waves[2]->setFreq(baseFreq * ((MY_FLOAT) 1.0 + temp) * ratios[2]);
|
||||
waves[3]->setFreq(baseFreq * ((MY_FLOAT) 1.0 + temp) * ratios[3]);
|
||||
|
||||
temp = gains[2] * adsr[2]->tick() * waves[2]->tick();
|
||||
waves[1]->addPhaseOffset(temp);
|
||||
|
||||
waves[3]->addPhaseOffset(twozero->lastOut());
|
||||
temp = ((MY_FLOAT) 1.0 - (control2 * (MY_FLOAT) 0.5)) *
|
||||
gains[3] * adsr[3]->tick() * waves[3]->tick();
|
||||
twozero->tick(temp);
|
||||
|
||||
temp += control2 * (MY_FLOAT) 0.5 * gains[1] * adsr[1]->tick() * waves[1]->tick();
|
||||
temp = temp * control1;
|
||||
|
||||
waves[0]->addPhaseOffset(temp);
|
||||
temp = gains[0] * adsr[0]->tick() * waves[0]->tick();
|
||||
|
||||
lastOutput = temp * (MY_FLOAT) 0.5;
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
30
FM4Alg3.h
30
FM4Alg3.h
@@ -1,30 +0,0 @@
|
||||
/******************************************/
|
||||
/* Algorithm 3 (TX81Z) Subclass of */
|
||||
/* 4 Operator FM Synth */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* */
|
||||
/* Alg 3 is : 4--\ */
|
||||
/* 3-->2-- + -->1-->Out */
|
||||
/* */
|
||||
/* Controls: control1 = total mod index */
|
||||
/* control2 = crossfade of two */
|
||||
/* modulators */
|
||||
/* control3 = LFO speed */
|
||||
/* modWheel = LFO amount */
|
||||
/* */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__FM4Alg3_h)
|
||||
#define __FM4Alg3_h
|
||||
|
||||
#include "FM4Op.h"
|
||||
|
||||
class FM4Alg3 : public FM4Op
|
||||
{
|
||||
public:
|
||||
FM4Alg3();
|
||||
virtual ~FM4Alg3();
|
||||
MY_FLOAT tick();
|
||||
};
|
||||
|
||||
#endif
|
||||
53
FM4Alg4.cpp
53
FM4Alg4.cpp
@@ -1,53 +0,0 @@
|
||||
/******************************************/
|
||||
/* Algorithm 4 (TX81Z) Subclass of */
|
||||
/* 4 Operator FM Synth */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* */
|
||||
/* Alg 4 is : 4->3--\ */
|
||||
/* 2-- + -->1-->Out */
|
||||
/* */
|
||||
/* Controls: control1 = total mod index */
|
||||
/* control2 = crossfade of two */
|
||||
/* modulators */
|
||||
/* control3 = LFO speed */
|
||||
/* modWheel = LFO amount */
|
||||
/* */
|
||||
/******************************************/
|
||||
|
||||
#include "FM4Alg4.h"
|
||||
|
||||
FM4Alg4 :: FM4Alg4() : FM4Op()
|
||||
{
|
||||
/* We still don't make the waves here yet, because */
|
||||
/* we still don't know what they will be. */
|
||||
}
|
||||
|
||||
FM4Alg4 :: ~FM4Alg4()
|
||||
{
|
||||
}
|
||||
|
||||
MY_FLOAT FM4Alg4 :: tick()
|
||||
{
|
||||
MY_FLOAT temp;
|
||||
|
||||
temp = vibWave->tick() * modDepth * (MY_FLOAT) 0.2;
|
||||
waves[0]->setFreq(baseFreq * ((MY_FLOAT) 1.0 + temp) * ratios[0]);
|
||||
waves[1]->setFreq(baseFreq * ((MY_FLOAT) 1.0 + temp) * ratios[1]);
|
||||
waves[2]->setFreq(baseFreq * ((MY_FLOAT) 1.0 + temp) * ratios[2]);
|
||||
waves[3]->setFreq(baseFreq * ((MY_FLOAT) 1.0 + temp) * ratios[3]);
|
||||
|
||||
waves[3]->addPhaseOffset(twozero->lastOut());
|
||||
temp = gains[3] * adsr[3]->tick() * waves[3]->tick();
|
||||
twozero->tick(temp);
|
||||
waves[2]->addPhaseOffset(temp);
|
||||
temp = ((MY_FLOAT) 1.0 - (control2 * (MY_FLOAT) 0.5)) *
|
||||
gains[2] * adsr[2]->tick() * waves[2]->tick();
|
||||
temp += control2 * (MY_FLOAT) 0.5 * gains[1] * adsr[1]->tick() * waves[1]->tick();
|
||||
temp = temp * control1;
|
||||
waves[0]->addPhaseOffset(temp);
|
||||
temp = gains[0] * adsr[0]->tick() * waves[0]->tick();
|
||||
|
||||
lastOutput = temp * (MY_FLOAT) 0.5;
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
30
FM4Alg4.h
30
FM4Alg4.h
@@ -1,30 +0,0 @@
|
||||
/******************************************/
|
||||
/* Algorithm 4 (TX81Z) Subclass of */
|
||||
/* 4 Operator FM Synth */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* */
|
||||
/* Alg 4 is : 4->3--\ */
|
||||
/* 2-- + -->1-->Out */
|
||||
/* */
|
||||
/* Controls: control1 = total mod index */
|
||||
/* control2 = crossfade of two */
|
||||
/* modulators */
|
||||
/* control3 = LFO speed */
|
||||
/* modWheel = LFO amount */
|
||||
/* */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__FM4Alg4_h)
|
||||
#define __FM4Alg4_h
|
||||
|
||||
#include "FM4Op.h"
|
||||
|
||||
class FM4Alg4 : public FM4Op
|
||||
{
|
||||
public:
|
||||
FM4Alg4();
|
||||
virtual ~FM4Alg4();
|
||||
MY_FLOAT tick();
|
||||
};
|
||||
|
||||
#endif
|
||||
53
FM4Alg5.cpp
53
FM4Alg5.cpp
@@ -1,53 +0,0 @@
|
||||
/******************************************/
|
||||
/* Algorithm 5 (TX81Z) Subclass of */
|
||||
/* 4 Operator FM Synth */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* This connection topology is 2 simple */
|
||||
/* FM Pairs summed together, like: */
|
||||
/* */
|
||||
/* Alg 5 is : 4->3--\ */
|
||||
/* + --> Out */
|
||||
/* 2->1--/ */
|
||||
/* */
|
||||
/* Controls: control1 = mod index 1 */
|
||||
/* control2 = crossfade of two */
|
||||
/* outputs */
|
||||
/* control3 = LFO speed */
|
||||
/* modWheel = LFO amount */
|
||||
/* */
|
||||
/******************************************/
|
||||
|
||||
#include "FM4Alg5.h"
|
||||
|
||||
FM4Alg5 :: FM4Alg5() : FM4Op()
|
||||
{
|
||||
/* We still don't make the waves here yet, because */
|
||||
/* we still don't know what they will be. */
|
||||
}
|
||||
|
||||
FM4Alg5 :: ~FM4Alg5()
|
||||
{
|
||||
}
|
||||
|
||||
MY_FLOAT FM4Alg5 :: tick()
|
||||
{
|
||||
MY_FLOAT temp,temp2;
|
||||
|
||||
temp = gains[1] * adsr[1]->tick() * waves[1]->tick();
|
||||
temp = temp * control1;
|
||||
waves[0]->addPhaseOffset(temp);
|
||||
waves[3]->addPhaseOffset(twozero->lastOut());
|
||||
temp = gains[3] * adsr[3]->tick() * waves[3]->tick();
|
||||
twozero->tick(temp);
|
||||
waves[2]->addPhaseOffset(temp);
|
||||
temp = ((MY_FLOAT) 1.0 - (control2 * (MY_FLOAT) 0.5)) *
|
||||
gains[0] * adsr[0]->tick() * waves[0]->tick();
|
||||
temp += control2 * (MY_FLOAT) 0.5 * gains[2] * adsr[2]->tick() * waves[2]->tick();
|
||||
|
||||
temp2 = vibWave->tick() * modDepth; /* Calculate amplitude mod */
|
||||
temp = temp * ((MY_FLOAT) 1.0 + temp2); /* and apply it to output */
|
||||
|
||||
lastOutput = temp * (MY_FLOAT) 0.5;
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
33
FM4Alg5.h
33
FM4Alg5.h
@@ -1,33 +0,0 @@
|
||||
/******************************************/
|
||||
/* Algorithm 5 (TX81Z) Subclass of */
|
||||
/* 4 Operator FM Synth */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* This connection topology is 2 simple */
|
||||
/* FM Pairs summed together, like: */
|
||||
/* */
|
||||
/* 1 -> 2 -\ */
|
||||
/* +-> Out */
|
||||
/* 3 -> 4 -/ */
|
||||
/* */
|
||||
/* Controls: control1 = mod index 1 */
|
||||
/* control2 = crossfade of two */
|
||||
/* outputs */
|
||||
/* control3 = LFO speed */
|
||||
/* modWheel = LFO amount */
|
||||
/* */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__FM4Alg5_h)
|
||||
#define __FM4Alg5_h
|
||||
|
||||
#include "FM4Op.h"
|
||||
|
||||
class FM4Alg5 : public FM4Op
|
||||
{
|
||||
public:
|
||||
FM4Alg5();
|
||||
virtual ~FM4Alg5();
|
||||
MY_FLOAT tick();
|
||||
};
|
||||
|
||||
#endif
|
||||
58
FM4Alg6.cpp
58
FM4Alg6.cpp
@@ -1,58 +0,0 @@
|
||||
/******************************************/
|
||||
/* Algorithm 6 (TX81Z) Subclass of */
|
||||
/* 4 Operator FM Synth */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* This connection topology is three */
|
||||
/* Carriers and a common Modulator */
|
||||
/* */
|
||||
/* /->1 -\ */
|
||||
/* 4-|-->2 - +-> Out */
|
||||
/* \->3 -/ */
|
||||
/* */
|
||||
/* Controls: control1 = vowel */
|
||||
/* control2 = spectral tilt */
|
||||
/* control3 = LFO speed */
|
||||
/* modWheel = LFO amount */
|
||||
/* */
|
||||
/******************************************/
|
||||
|
||||
#include "FM4Alg6.h"
|
||||
|
||||
FM4Alg6 :: FM4Alg6() : FM4Op()
|
||||
{
|
||||
/* We still don't make the waves here yet, because */
|
||||
/* we still don't know what they will be. */
|
||||
}
|
||||
|
||||
FM4Alg6 :: ~FM4Alg6()
|
||||
{
|
||||
}
|
||||
|
||||
MY_FLOAT FM4Alg6 :: tick()
|
||||
{
|
||||
MY_FLOAT temp,temp2;
|
||||
|
||||
temp = gains[3] * adsr[3]->tick() * waves[3]->tick();
|
||||
temp2 = vibWave->tick() * modDepth * (MY_FLOAT) 0.1; /* Calculate frequency mod */
|
||||
|
||||
waves[0]->setFreq(baseFreq * ((MY_FLOAT) 1.0 + temp2) * ratios[0]);
|
||||
waves[1]->setFreq(baseFreq * ((MY_FLOAT) 1.0 + temp2) * ratios[1]);
|
||||
waves[2]->setFreq(baseFreq * ((MY_FLOAT) 1.0 + temp2) * ratios[2]);
|
||||
waves[3]->setFreq(baseFreq * ((MY_FLOAT) 1.0 + temp2) * ratios[3]);
|
||||
|
||||
waves[0]->addPhaseOffset(temp * mods[0]);
|
||||
waves[1]->addPhaseOffset(temp * mods[1]);
|
||||
waves[2]->addPhaseOffset(temp * mods[2]);
|
||||
waves[3]->addPhaseOffset(twozero->lastOut());
|
||||
twozero->tick(temp);
|
||||
temp = gains[0] * tilt[0] * adsr[0]->tick() * waves[0]->tick();
|
||||
temp += gains[1] * tilt[1] * adsr[1]->tick() * waves[1]->tick();
|
||||
temp += gains[2] * tilt[2] * adsr[2]->tick() * waves[2]->tick();
|
||||
|
||||
return temp * (MY_FLOAT) 0.33;
|
||||
}
|
||||
|
||||
void FM4Alg6 :: controlChange(int number, MY_FLOAT value)
|
||||
{
|
||||
|
||||
}
|
||||
36
FM4Alg6.h
36
FM4Alg6.h
@@ -1,36 +0,0 @@
|
||||
/******************************************/
|
||||
/* Algorithm 6 (TX81Z) Subclass of */
|
||||
/* 4 Operator FM Synth */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* This connection topology is three */
|
||||
/* Carriers and a common Modulator */
|
||||
/* */
|
||||
/* /->1 -\ */
|
||||
/* 4-|-->2 - +-> Out */
|
||||
/* \->3 -/ */
|
||||
/* */
|
||||
/* Controls: control1 = vowel */
|
||||
/* control2 = spectral tilt */
|
||||
/* control3 = LFO speed */
|
||||
/* modWheel = LFO amount */
|
||||
/* */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__FM4Alg6_h)
|
||||
#define __FM4Alg6_h
|
||||
|
||||
#include "FM4Op.h"
|
||||
|
||||
class FM4Alg6 : public FM4Op
|
||||
{
|
||||
protected:
|
||||
MY_FLOAT tilt[3];
|
||||
MY_FLOAT mods[3];
|
||||
public:
|
||||
FM4Alg6();
|
||||
virtual ~FM4Alg6();
|
||||
MY_FLOAT tick();
|
||||
virtual void controlChange(int number, MY_FLOAT value);
|
||||
};
|
||||
|
||||
#endif
|
||||
47
FM4Alg8.cpp
47
FM4Alg8.cpp
@@ -1,47 +0,0 @@
|
||||
/******************************************/
|
||||
/* Algorithm 8 (TX81Z) Subclass of */
|
||||
/* 4 Operator FM Synth */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* This connection topology is simple */
|
||||
/* Additive Synthesis, like: */
|
||||
/* */
|
||||
/* 1 --. */
|
||||
/* 2 -\| */
|
||||
/* +-> Out */
|
||||
/* 3 -/| */
|
||||
/* 4 -- */
|
||||
/* */
|
||||
/* Controls: control1 = op4 (fb) gain */
|
||||
/* control2 = op3 gain */
|
||||
/* control3 = LFO speed */
|
||||
/* modWheel = LFO amount */
|
||||
/* */
|
||||
/******************************************/
|
||||
|
||||
#include "FM4Alg8.h"
|
||||
|
||||
FM4Alg8 :: FM4Alg8() : FM4Op()
|
||||
{
|
||||
/* We still don't make the waves here yet, because */
|
||||
/* we still don't know what they will be. */
|
||||
}
|
||||
|
||||
FM4Alg8 :: ~FM4Alg8()
|
||||
{
|
||||
}
|
||||
|
||||
MY_FLOAT FM4Alg8 :: tick()
|
||||
{
|
||||
MY_FLOAT temp;
|
||||
|
||||
waves[3]->addPhaseOffset(twozero->lastOut());
|
||||
temp = control1 * (MY_FLOAT) 2.0 * gains[3] * adsr[3]->tick() * waves[3]->tick();
|
||||
twozero->tick(temp);
|
||||
temp += control2 * (MY_FLOAT) 2.0 * gains[2] * adsr[2]->tick() * waves[2]->tick();
|
||||
temp += gains[1] * adsr[1]->tick() * waves[1]->tick();
|
||||
temp += gains[0] * adsr[0]->tick() * waves[0]->tick();
|
||||
|
||||
lastOutput = temp * (MY_FLOAT) 0.125;
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
34
FM4Alg8.h
34
FM4Alg8.h
@@ -1,34 +0,0 @@
|
||||
/******************************************/
|
||||
/* Algorithm 8 (TX81Z) Subclass of */
|
||||
/* 4 Operator FM Synth */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* This connection topology is simple */
|
||||
/* Additive Synthesis, like: */
|
||||
/* */
|
||||
/* 1 --. */
|
||||
/* 2 -\| */
|
||||
/* +-> Out */
|
||||
/* 3 -/| */
|
||||
/* 4 -- */
|
||||
/* */
|
||||
/* Controls: control1 = op4 (fb) gain */
|
||||
/* control2 = op3 gain */
|
||||
/* control3 = LFO speed */
|
||||
/* modWheel = LFO amount */
|
||||
/* */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__FM4Alg8_h)
|
||||
#define __FM4Alg8_h
|
||||
|
||||
#include "FM4Op.h"
|
||||
|
||||
class FM4Alg8 : public FM4Op
|
||||
{
|
||||
public:
|
||||
FM4Alg8();
|
||||
virtual ~FM4Alg8();
|
||||
virtual MY_FLOAT tick();
|
||||
};
|
||||
|
||||
#endif
|
||||
180
FM4Op.cpp
180
FM4Op.cpp
@@ -1,180 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Master Class for 4 Operator FM Synth */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* This instrument contains 4 waves, */
|
||||
/* 4 adsr, and various state vars. */
|
||||
/* */
|
||||
/* The basic Chowning/Stanford FM patent */
|
||||
/* expired April 1995, but there exist */
|
||||
/* follow-on patents, mostly assigned to */
|
||||
/* Yamaha. If you are of the type who */
|
||||
/* should worry about this (making money) */
|
||||
/* worry away. */
|
||||
/* */
|
||||
/*******************************************/
|
||||
|
||||
#include "FM4Op.h"
|
||||
#include "SKINI11.msg"
|
||||
|
||||
FM4Op :: FM4Op()
|
||||
{
|
||||
int i;
|
||||
MY_FLOAT temp;
|
||||
MY_FLOAT tempCoeffs[2] = {(MY_FLOAT) 0.0, (MY_FLOAT) -1.0};
|
||||
adsr[0] = new ADSR;
|
||||
adsr[1] = new ADSR;
|
||||
adsr[2] = new ADSR;
|
||||
adsr[3] = new ADSR;
|
||||
twozero = new TwoZero;
|
||||
vibWave = new RawLoop("rawwaves/sinewave.raw");
|
||||
vibWave->normalize();
|
||||
vibWave->setFreq((MY_FLOAT) 6.0); /* should make this random?? */
|
||||
modDepth = (MY_FLOAT) 0.0;
|
||||
/* We don't make the waves here yet, because */
|
||||
/* we don't know what they will be. */
|
||||
baseFreq = (MY_FLOAT) 440.0;
|
||||
ratios[0] = (MY_FLOAT) 1.0;
|
||||
ratios[1] = (MY_FLOAT) 1.0;
|
||||
ratios[2] = (MY_FLOAT) 1.0;
|
||||
ratios[3] = (MY_FLOAT) 1.0;
|
||||
gains[0] = (MY_FLOAT) 1.0;
|
||||
gains[1] = (MY_FLOAT) 1.0;
|
||||
gains[2] = (MY_FLOAT) 1.0;
|
||||
gains[3] = (MY_FLOAT) 1.0;
|
||||
twozero->setZeroCoeffs(tempCoeffs);
|
||||
twozero->setGain((MY_FLOAT) 0.0);
|
||||
control1 = (MY_FLOAT) 1.0;
|
||||
control2 = (MY_FLOAT) 1.0;
|
||||
temp = (MY_FLOAT) 1.0;
|
||||
for (i=99;i>=0;i--) {
|
||||
__FM4Op_gains[i] = temp;
|
||||
temp *= (MY_FLOAT) 0.933033;
|
||||
}
|
||||
temp = (MY_FLOAT) 1.0;
|
||||
for (i=15;i>=0;i--) {
|
||||
__FM4Op_susLevels[i] = temp;
|
||||
temp *= (MY_FLOAT) 0.707101;
|
||||
}
|
||||
temp = (MY_FLOAT) 8.498186;
|
||||
for (i=0;i<32;i++) {
|
||||
__FM4Op_attTimes[i] = temp;
|
||||
temp *= (MY_FLOAT) 0.707101;
|
||||
}
|
||||
}
|
||||
|
||||
FM4Op :: ~FM4Op()
|
||||
{
|
||||
delete adsr[0];
|
||||
delete adsr[1];
|
||||
delete adsr[2];
|
||||
delete adsr[3];
|
||||
delete waves[0];
|
||||
delete waves[1];
|
||||
delete waves[2];
|
||||
delete waves[3];
|
||||
delete vibWave;
|
||||
delete twozero;
|
||||
}
|
||||
|
||||
void FM4Op :: loadWaves(char* wave1, char* wave2, char* wave3, char* wave4)
|
||||
{
|
||||
int i;
|
||||
waves[0] = new RawLoop(wave1);
|
||||
waves[1] = new RawLoop(wave2);
|
||||
waves[2] = new RawLoop(wave3);
|
||||
waves[3] = new RawLoop(wave4);
|
||||
for (i=0;i<4;i++) {
|
||||
waves[i]->normalize();
|
||||
}
|
||||
}
|
||||
void FM4Op :: setFreq(MY_FLOAT frequency)
|
||||
{
|
||||
baseFreq = frequency;
|
||||
waves[0]->setFreq(baseFreq * ratios[0]);
|
||||
waves[1]->setFreq(baseFreq * ratios[1]);
|
||||
waves[2]->setFreq(baseFreq * ratios[2]);
|
||||
waves[3]->setFreq(baseFreq * ratios[3]);
|
||||
}
|
||||
|
||||
void FM4Op :: setRatio(int whichOne, MY_FLOAT ratio)
|
||||
{
|
||||
ratios[whichOne] = ratio;
|
||||
if (ratio>0.0)
|
||||
waves[whichOne]->setFreq(baseFreq * ratio);
|
||||
else
|
||||
waves[whichOne]->setFreq(ratio);
|
||||
}
|
||||
|
||||
void FM4Op :: setGain(int whichOne, MY_FLOAT gain)
|
||||
{
|
||||
gains[whichOne]=gain;
|
||||
}
|
||||
|
||||
void FM4Op :: keyOn()
|
||||
{
|
||||
adsr[0]->keyOn();
|
||||
adsr[1]->keyOn();
|
||||
adsr[2]->keyOn();
|
||||
adsr[3]->keyOn();
|
||||
}
|
||||
|
||||
void FM4Op :: keyOff()
|
||||
{
|
||||
adsr[0]->keyOff();
|
||||
adsr[1]->keyOff();
|
||||
adsr[2]->keyOff();
|
||||
adsr[3]->keyOff();
|
||||
}
|
||||
|
||||
void FM4Op :: noteOff(MY_FLOAT amp)
|
||||
{
|
||||
this->keyOff();
|
||||
#if defined(_debug_)
|
||||
printf("FM4Op : NoteOff: Amp=%lf\n",amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void FM4Op :: setModulationSpeed(MY_FLOAT mSpeed)
|
||||
{
|
||||
vibWave->setFreq(mSpeed);
|
||||
}
|
||||
|
||||
void FM4Op :: setModulationDepth(MY_FLOAT mDepth)
|
||||
{
|
||||
modDepth = mDepth;
|
||||
}
|
||||
|
||||
void FM4Op :: setControl1(MY_FLOAT cVal)
|
||||
{
|
||||
control1 = cVal * (MY_FLOAT) 2.0;
|
||||
}
|
||||
|
||||
void FM4Op :: setControl2(MY_FLOAT cVal)
|
||||
{
|
||||
control2 = cVal * (MY_FLOAT) 2.0;
|
||||
}
|
||||
|
||||
void FM4Op :: controlChange(int number, MY_FLOAT value)
|
||||
{
|
||||
#if defined(_debug_)
|
||||
printf("FM4Op : ControlChange: Number=%i Value=%f\n",number,value);
|
||||
#endif
|
||||
if (number == __SK_Breath_)
|
||||
this->setControl1(value * NORM_7);
|
||||
else if (number == __SK_FootControl_)
|
||||
this->setControl2(value * NORM_7);
|
||||
else if (number == __SK_ModFrequency_)
|
||||
this->setModulationSpeed(value * NORM_7 * (MY_FLOAT) 12.0); /* 0 to 12 Hz */
|
||||
else if (number == __SK_ModWheel_)
|
||||
this->setModulationDepth(value * NORM_7);
|
||||
else if (number == __SK_AfterTouch_Cont_) {
|
||||
adsr[0]->setTarget(value * NORM_7);
|
||||
adsr[1]->setTarget(value * NORM_7);
|
||||
adsr[2]->setTarget(value * NORM_7);
|
||||
adsr[3]->setTarget(value * NORM_7);
|
||||
}
|
||||
else {
|
||||
printf("FM4Op : Undefined Control Number!!\n");
|
||||
}
|
||||
}
|
||||
|
||||
59
FM4Op.h
59
FM4Op.h
@@ -1,59 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Master Class for 4 Operator FM Synth */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* This instrument contains an 4 waves, */
|
||||
/* 4 envelopes, and various state vars. */
|
||||
/* */
|
||||
/* The basic Chowning/Stanford FM patent */
|
||||
/* expired April 1995, but there exist */
|
||||
/* follow-on patents, mostly assigned to */
|
||||
/* Yamaha. If you are of the type who */
|
||||
/* should worry about this (making money) */
|
||||
/* worry away. */
|
||||
/* */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__FM4Op_h)
|
||||
#define __FM4Op_h
|
||||
|
||||
#include "Instrmnt.h"
|
||||
#include "ADSR.h"
|
||||
#include "RawLoop.h"
|
||||
#include "TwoZero.h"
|
||||
|
||||
class FM4Op : public Instrmnt
|
||||
{
|
||||
protected:
|
||||
ADSR *adsr[4];
|
||||
RawLoop *waves[4];
|
||||
RawLoop *vibWave;
|
||||
TwoZero *twozero;
|
||||
MY_FLOAT baseFreq;
|
||||
MY_FLOAT ratios[4];
|
||||
MY_FLOAT gains[4];
|
||||
MY_FLOAT modDepth;
|
||||
MY_FLOAT control1;
|
||||
MY_FLOAT control2;
|
||||
MY_FLOAT __FM4Op_gains[100];
|
||||
MY_FLOAT __FM4Op_susLevels[16];
|
||||
MY_FLOAT __FM4Op_attTimes[32];
|
||||
public:
|
||||
FM4Op();
|
||||
virtual ~FM4Op();
|
||||
void loadWaves(char* wave1, char* wave2, char* wave3, char* wave4);
|
||||
void clear();
|
||||
void setFreq(MY_FLOAT frequency);
|
||||
void setRatio(int whichOne, MY_FLOAT ratio);
|
||||
void setGain(int whichOne, MY_FLOAT gain);
|
||||
void keyOn();
|
||||
void keyOff();
|
||||
void noteOff(MY_FLOAT amp);
|
||||
/* There's no tick() method here, because that depends on the algorithm */
|
||||
void setModulationSpeed(MY_FLOAT mSpeed);
|
||||
void setModulationDepth(MY_FLOAT mDepth);
|
||||
void setControl1(MY_FLOAT cVal);
|
||||
void setControl2(MY_FLOAT cVal);
|
||||
virtual void controlChange(int number, MY_FLOAT value);
|
||||
};
|
||||
|
||||
#endif
|
||||
127
FMVoices.cpp
127
FMVoices.cpp
@@ -1,127 +0,0 @@
|
||||
/******************************************/
|
||||
/* Singing Voice Synthesis Subclass */
|
||||
/* of Algorithm 6 (TX81Z) Subclass of */
|
||||
/* 4 Operator FM Synth */
|
||||
/* by Perry R. Cook, 1996 */
|
||||
/******************************************/
|
||||
|
||||
#include "FMVoices.h"
|
||||
#include "SKINI11.msg"
|
||||
|
||||
FMVoices :: FMVoices() : FM4Alg6()
|
||||
{
|
||||
this->loadWaves("rawwaves/sinewave.raw",
|
||||
"rawwaves/sinewave.raw",
|
||||
"rawwaves/sinewave.raw",
|
||||
"rawwaves/sinewave.raw");
|
||||
|
||||
this->setRatio(0,(MY_FLOAT) 2.00);
|
||||
this->setRatio(1,(MY_FLOAT) 4.00);
|
||||
this->setRatio(2,(MY_FLOAT) 12.0);
|
||||
this->setRatio(3,(MY_FLOAT) 1.00);
|
||||
gains[3] = __FM4Op_gains[80];
|
||||
adsr[0]->setAllTimes((MY_FLOAT) 0.050,(MY_FLOAT) 0.050,
|
||||
__FM4Op_susLevels[15],(MY_FLOAT) 0.050);
|
||||
adsr[1]->setAllTimes((MY_FLOAT) 0.050,(MY_FLOAT) 0.050,
|
||||
__FM4Op_susLevels[15],(MY_FLOAT) 0.050);
|
||||
adsr[2]->setAllTimes((MY_FLOAT) 0.050,(MY_FLOAT) 0.050,
|
||||
__FM4Op_susLevels[15],(MY_FLOAT) 0.050);
|
||||
adsr[3]->setAllTimes((MY_FLOAT) 0.010,(MY_FLOAT) 0.010,
|
||||
__FM4Op_susLevels[15],(MY_FLOAT) 0.500);
|
||||
twozero->setGain((MY_FLOAT) 0.0);
|
||||
modDepth = (MY_FLOAT) 0.005;
|
||||
currentVowel = 0;
|
||||
tilt[0] = (MY_FLOAT) 1.0;
|
||||
tilt[1] = (MY_FLOAT) 0.5;
|
||||
tilt[2] = (MY_FLOAT) 0.2;
|
||||
mods[0] = (MY_FLOAT) 1.0;
|
||||
mods[1] = (MY_FLOAT) 1.1;
|
||||
mods[2] = (MY_FLOAT) 1.1;
|
||||
baseFreq = (MY_FLOAT) 110.0;
|
||||
this->setFreq((MY_FLOAT) 110.0);
|
||||
}
|
||||
|
||||
/* #include "phonTabl.h" */
|
||||
|
||||
extern double phonGains[32][2];
|
||||
extern double phonParams[32][4][3];
|
||||
extern char phonemes[32][4];
|
||||
|
||||
void FMVoices :: setFreq(MY_FLOAT frequency)
|
||||
{
|
||||
MY_FLOAT temp,temp2;
|
||||
int tempi,tempi2;
|
||||
|
||||
if (currentVowel < 16) {
|
||||
tempi2 = currentVowel;
|
||||
temp2 = (MY_FLOAT) 0.9;
|
||||
}
|
||||
else if (currentVowel < 32) {
|
||||
tempi2 = currentVowel - 16;
|
||||
temp2 = (MY_FLOAT) 1.0;
|
||||
}
|
||||
else if (currentVowel < 48) {
|
||||
tempi2 = currentVowel - 32;
|
||||
temp2 = (MY_FLOAT) 1.1;
|
||||
}
|
||||
else if (currentVowel <= 64) {
|
||||
tempi2 = currentVowel - 48;
|
||||
temp2 = (MY_FLOAT) 1.2;
|
||||
}
|
||||
baseFreq = frequency;
|
||||
temp = (temp2 * (MY_FLOAT) phonParams[tempi2][0][0] / baseFreq) + (MY_FLOAT) 0.5;
|
||||
tempi = (int) temp;
|
||||
this->setRatio(0,(MY_FLOAT) tempi);
|
||||
temp = (temp2 * (MY_FLOAT) phonParams[tempi2][1][0] / baseFreq) + (MY_FLOAT) 0.5;
|
||||
tempi = (int) temp;
|
||||
this->setRatio(1,(MY_FLOAT) tempi);
|
||||
temp = (temp2 * (MY_FLOAT) phonParams[tempi2][2][0] / baseFreq) + (MY_FLOAT) 0.5;
|
||||
tempi = (int) temp;
|
||||
this->setRatio(2,(MY_FLOAT) tempi);
|
||||
gains[0] = (MY_FLOAT) 1.0; // pow(10.0,phonParams[tempi2][0][2] * 0.05);
|
||||
gains[1] = (MY_FLOAT) 1.0; // pow(10.0,phonParams[tempi2][1][2] * 0.05);
|
||||
gains[2] = (MY_FLOAT) 1.0; // pow(10.0,phonParams[tempi2][2][2] * 0.05);
|
||||
}
|
||||
|
||||
void FMVoices :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
||||
{
|
||||
this->setFreq(freq);
|
||||
tilt[0] = amp;
|
||||
tilt[1] = amp * amp;
|
||||
tilt[2] = amp * amp * amp;
|
||||
this->keyOn();
|
||||
#if defined(_debug_)
|
||||
printf("FMVoices : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void FMVoices :: controlChange(int number, MY_FLOAT value)
|
||||
{
|
||||
MY_FLOAT temp;
|
||||
int tempi;
|
||||
|
||||
#if defined(_debug_)
|
||||
printf("FM4Op : ControlChange: Number=%i Value=%f\n",number,value);
|
||||
#endif
|
||||
if (number == __SK_Breath_)
|
||||
gains[3] = __FM4Op_gains[(int) (value * 0.78125)];
|
||||
else if (number == __SK_FootControl_) {
|
||||
tempi = (int) (value / 2);
|
||||
currentVowel = tempi;
|
||||
this->setFreq(baseFreq);
|
||||
}
|
||||
else if (number == __SK_ModFrequency_)
|
||||
this->setModulationSpeed(value * NORM_7 * (MY_FLOAT) 12.0); /* 0 to 12 Hz */
|
||||
else if (number == __SK_ModWheel_)
|
||||
this->setModulationDepth(value * NORM_7);
|
||||
else if (number == __SK_AfterTouch_Cont_) {
|
||||
temp = value * NORM_7;
|
||||
tilt[0] = temp;
|
||||
tilt[1] = temp * temp;
|
||||
tilt[2] = temp * temp * temp;
|
||||
}
|
||||
else {
|
||||
printf("FM4Op : Undefined Control Number!!\n");
|
||||
}
|
||||
}
|
||||
|
||||
24
FMVoices.h
24
FMVoices.h
@@ -1,24 +0,0 @@
|
||||
/******************************************/
|
||||
/* Singing Voice Synthesis Subclass */
|
||||
/* of Algorithm 6 (TX81Z) Subclass of */
|
||||
/* 4 Operator FM Synth */
|
||||
/* by Perry R. Cook, 1996 */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__FMVoices_h)
|
||||
#define __FMVoices_h
|
||||
|
||||
#include "FM4Alg6.h"
|
||||
|
||||
class FMVoices : public FM4Alg6
|
||||
{
|
||||
protected:
|
||||
int currentVowel;
|
||||
public:
|
||||
FMVoices();
|
||||
virtual void setFreq(MY_FLOAT frequency);
|
||||
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
|
||||
virtual void controlChange(int number, MY_FLOAT value);
|
||||
};
|
||||
|
||||
#endif
|
||||
24
Filter.cpp
24
Filter.cpp
@@ -1,24 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Filter Class, by Perry R. Cook, 1995-96*/
|
||||
/* This is the base class for all filters.*/
|
||||
/* To me, most anything is a filter, but */
|
||||
/* I'll be a little less general here, and*/
|
||||
/* define a filter as something which has */
|
||||
/* input(s), output(s), and gain. */
|
||||
/*******************************************/
|
||||
|
||||
#include "Filter.h"
|
||||
|
||||
Filter :: Filter() : Object()
|
||||
{
|
||||
}
|
||||
|
||||
Filter :: ~Filter()
|
||||
{
|
||||
}
|
||||
|
||||
MY_FLOAT Filter :: lastOut()
|
||||
{
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
28
Filter.h
28
Filter.h
@@ -1,28 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Filter Class, by Perry R. Cook, 1995-96*/
|
||||
/* This is the base class for all filters.*/
|
||||
/* To me, most anything is a filter, but */
|
||||
/* I'll be a little less general here, and*/
|
||||
/* define a filter as something which has */
|
||||
/* input(s), output(s), and gain. */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__Filter_h)
|
||||
#define __Filter_h
|
||||
|
||||
#include "Object.h"
|
||||
|
||||
class Filter : public Object
|
||||
{
|
||||
protected:
|
||||
MY_FLOAT gain;
|
||||
MY_FLOAT *outputs;
|
||||
MY_FLOAT *inputs;
|
||||
MY_FLOAT lastOutput;
|
||||
public:
|
||||
Filter();
|
||||
virtual ~Filter();
|
||||
MY_FLOAT lastOut();
|
||||
};
|
||||
|
||||
#endif
|
||||
175
Flute.cpp
175
Flute.cpp
@@ -1,175 +0,0 @@
|
||||
/******************************************/
|
||||
/* WaveGuide Flute ala Karjalainen, */
|
||||
/* Smith, Waryznyk, etc. */
|
||||
/* with polynomial Jet ala Cook */
|
||||
/* by Perry Cook, 1995-96 */
|
||||
/* */
|
||||
/* This is a waveguide model, and thus */
|
||||
/* relates to various Stanford Univ. */
|
||||
/* and possibly Yamaha and other patents.*/
|
||||
/* */
|
||||
/* Controls: CONTROL1 = jetDelay */
|
||||
/* CONTROL2 = noiseGain */
|
||||
/* CONTROL3 = vibFreq */
|
||||
/* MOD_WHEEL= vibAmt */
|
||||
/******************************************/
|
||||
|
||||
#include "Flute.h"
|
||||
#include "SKINI11.msg"
|
||||
|
||||
Flute :: Flute(MY_FLOAT lowestFreq)
|
||||
{
|
||||
long length;
|
||||
length = (long) (SRATE / lowestFreq + 1);
|
||||
boreDelay = new DLineL(length);
|
||||
length >>= 1;
|
||||
jetDelay = new DLineL(length);
|
||||
jetTable = new JetTabl;
|
||||
filter = new OnePole;
|
||||
dcBlock = new DCBlock;
|
||||
noise = new Noise;
|
||||
adsr = new ADSR;
|
||||
vibr = new RawLoop("rawwaves/sinewave.raw");
|
||||
this->clear();
|
||||
|
||||
boreDelay->setDelay((MY_FLOAT) 100.0);
|
||||
jetDelay->setDelay((MY_FLOAT) 49.0);
|
||||
|
||||
filter->setPole((MY_FLOAT) 0.7 - ((MY_FLOAT) 0.1 * (MY_FLOAT) 22050.0 / SRATE));
|
||||
filter->setGain((MY_FLOAT) -1.0);
|
||||
vibr->normalize();
|
||||
vibr->setFreq((MY_FLOAT) 5.925);
|
||||
adsr->setAllTimes((MY_FLOAT) 0.005, (MY_FLOAT) 0.01, (MY_FLOAT) 0.8, (MY_FLOAT) 0.010);
|
||||
endRefl = (MY_FLOAT) 0.5;
|
||||
jetRefl = (MY_FLOAT) 0.5;
|
||||
noiseGain = (MY_FLOAT) 0.15; /* Breath pressure random component */
|
||||
vibrGain = (MY_FLOAT) 0.05; /* breath periodic vibrato component */
|
||||
jetRatio = (MY_FLOAT) 0.32;
|
||||
|
||||
maxPressure = (MY_FLOAT) 0.0;
|
||||
}
|
||||
|
||||
Flute :: ~Flute()
|
||||
{
|
||||
delete jetDelay;
|
||||
delete boreDelay;
|
||||
delete jetTable;
|
||||
delete filter;
|
||||
delete dcBlock;
|
||||
delete noise;
|
||||
delete adsr;
|
||||
delete vibr;
|
||||
}
|
||||
|
||||
void Flute :: clear()
|
||||
{
|
||||
jetDelay->clear();
|
||||
boreDelay->clear();
|
||||
filter->clear();
|
||||
dcBlock->clear();
|
||||
/* adsr->reset(); */
|
||||
}
|
||||
|
||||
void Flute :: setFreq(MY_FLOAT frequency)
|
||||
{
|
||||
MY_FLOAT temp;
|
||||
lastFreq = frequency * (MY_FLOAT) 0.66666; /* we're overblowing here */
|
||||
temp = SRATE / lastFreq - (MY_FLOAT) 2.0; /* Length - approx. filter delay */
|
||||
boreDelay->setDelay(temp); /* Length of bore tube */
|
||||
jetDelay->setDelay(temp * jetRatio); /* jet delay shorter */
|
||||
}
|
||||
|
||||
void Flute :: startBlowing(MY_FLOAT amplitude, MY_FLOAT rate)
|
||||
{
|
||||
adsr->setAttackRate(rate);
|
||||
maxPressure = amplitude / (MY_FLOAT) 0.8;
|
||||
adsr->keyOn();
|
||||
}
|
||||
|
||||
void Flute :: stopBlowing(MY_FLOAT rate)
|
||||
{
|
||||
adsr->setReleaseRate(rate);
|
||||
adsr->keyOff();
|
||||
}
|
||||
|
||||
void Flute :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
||||
{
|
||||
this->setFreq(freq);
|
||||
this->startBlowing((MY_FLOAT) 1.1 + (amp * (MY_FLOAT) 0.20),amp * (MY_FLOAT) 0.02);
|
||||
outputGain = amp + (MY_FLOAT) 0.001;
|
||||
#if defined(_debug_)
|
||||
printf("Flute : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Flute :: noteOff(MY_FLOAT amp)
|
||||
{
|
||||
this->stopBlowing(amp * (MY_FLOAT) 0.02);
|
||||
#if defined(_debug_)
|
||||
printf("Flute : NoteOff: Amp=%lf\n",amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Flute :: setJetRefl(MY_FLOAT refl)
|
||||
{
|
||||
jetRefl = refl;
|
||||
}
|
||||
|
||||
void Flute :: setEndRefl(MY_FLOAT refl)
|
||||
{
|
||||
endRefl = refl;
|
||||
}
|
||||
|
||||
void Flute :: setJetDelay(MY_FLOAT aRatio)
|
||||
{
|
||||
MY_FLOAT temp;
|
||||
temp = SRATE / lastFreq - (MY_FLOAT) 2.0; /* Length - approx. filter delay */
|
||||
jetRatio = aRatio;
|
||||
jetDelay->setDelay(temp * aRatio); /* Scaled by ratio */
|
||||
}
|
||||
|
||||
MY_FLOAT Flute :: tick()
|
||||
{
|
||||
MY_FLOAT temp;
|
||||
MY_FLOAT pressureDiff;
|
||||
MY_FLOAT randPressure;
|
||||
MY_FLOAT breathPressure;
|
||||
|
||||
breathPressure = maxPressure * adsr->tick(); /* Breath Pressure */
|
||||
randPressure = noiseGain * noise->tick(); /* Random Deviation */
|
||||
randPressure += vibrGain * vibr->tick(); /* + breath vibrato */
|
||||
randPressure *= breathPressure; /* All scaled by Breath Pressure */
|
||||
|
||||
temp = filter->tick(boreDelay->lastOut());
|
||||
temp = dcBlock->tick(temp); /* Block DC on reflection */
|
||||
pressureDiff = breathPressure + randPressure - /* Breath Pressure */
|
||||
(jetRefl * temp); /* - reflected */
|
||||
pressureDiff = jetDelay->tick(pressureDiff); /* Jet Delay Line */
|
||||
pressureDiff = jetTable->lookup(pressureDiff) /* Non-Lin Jet + reflected */
|
||||
+ (endRefl * temp);
|
||||
lastOutput = (MY_FLOAT) 0.3 * boreDelay->tick(pressureDiff); /* Bore Delay and "bell" filter */
|
||||
|
||||
lastOutput *= outputGain;
|
||||
return lastOutput;
|
||||
|
||||
}
|
||||
|
||||
void Flute :: controlChange(int number, MY_FLOAT value)
|
||||
{
|
||||
#if defined(_debug_)
|
||||
printf("Flute : ControlChange: Number=%i Value=%f\n",number,value);
|
||||
#endif
|
||||
if (number == __SK_JetDelay_)
|
||||
this->setJetDelay((MY_FLOAT) 0.08 + ((MY_FLOAT) 0.48 * value * NORM_7));
|
||||
else if (number == __SK_NoiseLevel_)
|
||||
noiseGain = (value * NORM_7 * (MY_FLOAT) 0.4);
|
||||
else if (number == __SK_ModFrequency_)
|
||||
vibr->setFreq((value * NORM_7 * (MY_FLOAT) 12.0));
|
||||
else if (number == __SK_ModWheel_)
|
||||
vibrGain = (value * NORM_7 * (MY_FLOAT) 0.4);
|
||||
else if (number == __SK_AfterTouch_Cont_)
|
||||
adsr->setTarget(value * NORM_7);
|
||||
else {
|
||||
printf("Flute : Undefined Control Number!!\n");
|
||||
}
|
||||
}
|
||||
64
Flute.h
64
Flute.h
@@ -1,64 +0,0 @@
|
||||
/******************************************/
|
||||
/* WaveGuide Flute ala Karjalainen, */
|
||||
/* Smith, Waryznyk, etc. */
|
||||
/* with polynomial Jet ala Cook */
|
||||
/* by Perry Cook, 1995-96 */
|
||||
/* */
|
||||
/* This is a waveguide model, and thus */
|
||||
/* relates to various Stanford Univ. */
|
||||
/* and possibly Yamaha and other patents.*/
|
||||
/* */
|
||||
/* Controls: CONTROL1 = jetDelay */
|
||||
/* CONTROL2 = noiseGain */
|
||||
/* CONTROL3 = vibFreq */
|
||||
/* MOD_WHEEL= vibAmt */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__Flute_h)
|
||||
#define __Flute_h
|
||||
|
||||
#include "Instrmnt.h"
|
||||
#include "JetTabl.h"
|
||||
#include "DLineL.h"
|
||||
#include "OnePole.h"
|
||||
#include "DCBlock.h"
|
||||
#include "Noise.h"
|
||||
#include "ADSR.h"
|
||||
#include "RawLoop.h"
|
||||
|
||||
class Flute : public Instrmnt
|
||||
{
|
||||
protected:
|
||||
DLineL *jetDelay;
|
||||
DLineL *boreDelay;
|
||||
JetTabl *jetTable;
|
||||
OnePole *filter;
|
||||
DCBlock *dcBlock;
|
||||
Noise *noise;
|
||||
ADSR *adsr;
|
||||
RawLoop *vibr;
|
||||
MY_FLOAT lastFreq;
|
||||
MY_FLOAT maxPressure;
|
||||
MY_FLOAT jetRefl;
|
||||
MY_FLOAT endRefl;
|
||||
MY_FLOAT noiseGain;
|
||||
MY_FLOAT vibrGain;
|
||||
MY_FLOAT outputGain;
|
||||
MY_FLOAT jetRatio;
|
||||
public:
|
||||
Flute(MY_FLOAT lowestFreq);
|
||||
~Flute();
|
||||
void clear();
|
||||
void startBlowing(MY_FLOAT amplitude,MY_FLOAT rate);
|
||||
void stopBlowing(MY_FLOAT rate);
|
||||
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
|
||||
virtual void noteOff(MY_FLOAT amp);
|
||||
void setJetRefl(MY_FLOAT refl);
|
||||
void setEndRefl(MY_FLOAT refl);
|
||||
virtual void setFreq(MY_FLOAT frequency);
|
||||
virtual MY_FLOAT tick();
|
||||
virtual void controlChange(int number, MY_FLOAT value);
|
||||
void setJetDelay(MY_FLOAT aLength);
|
||||
};
|
||||
|
||||
#endif
|
||||
176
FormSwep.cpp
176
FormSwep.cpp
@@ -1,176 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Sweepable Formant (2-pole) */
|
||||
/* Filter Class, by Perry R. Cook, 1995-96*/
|
||||
/* See books on filters to understand */
|
||||
/* more about how this works. This drives*/
|
||||
/* to a target at speed set by rate. */
|
||||
/*******************************************/
|
||||
|
||||
#include "FormSwep.h"
|
||||
|
||||
FormSwep :: FormSwep() : Filter()
|
||||
{
|
||||
outputs = (MY_FLOAT *) malloc(2 * MY_FLOAT_SIZE);
|
||||
poleCoeffs[0] = (MY_FLOAT) 0.0;
|
||||
poleCoeffs[1] = (MY_FLOAT) 0.0;
|
||||
gain = (MY_FLOAT) 1.0;
|
||||
freq = (MY_FLOAT) 0.0;
|
||||
reson = (MY_FLOAT) 0.0;
|
||||
currentGain = (MY_FLOAT) 1.0;
|
||||
currentFreq = (MY_FLOAT) 0.0;
|
||||
currentReson = (MY_FLOAT) 0.0;
|
||||
targetGain = (MY_FLOAT) 1.0;
|
||||
targetFreq = (MY_FLOAT) 0.0;
|
||||
targetReson = (MY_FLOAT) 0.0;
|
||||
deltaGain = (MY_FLOAT) 0.0;
|
||||
deltaFreq = (MY_FLOAT) 0.0;
|
||||
deltaReson = (MY_FLOAT) 0.0;
|
||||
sweepState = (MY_FLOAT) 0.0;
|
||||
sweepRate = (MY_FLOAT) 0.002;
|
||||
dirty = 0;
|
||||
this->clear();
|
||||
}
|
||||
|
||||
FormSwep :: ~FormSwep()
|
||||
{
|
||||
free(outputs);
|
||||
}
|
||||
|
||||
void FormSwep :: clear()
|
||||
{
|
||||
outputs[0] = (MY_FLOAT) 0.0;
|
||||
outputs[1] = (MY_FLOAT) 0.0;
|
||||
}
|
||||
|
||||
void FormSwep :: setPoleCoeffs(MY_FLOAT *coeffs)
|
||||
{
|
||||
dirty = 0;
|
||||
poleCoeffs[0] = coeffs[0];
|
||||
poleCoeffs[1] = coeffs[1];
|
||||
}
|
||||
|
||||
void FormSwep :: setFreqAndReson(MY_FLOAT aFreq, MY_FLOAT aReson)
|
||||
{
|
||||
dirty = 0;
|
||||
reson = aReson;
|
||||
freq = aFreq;
|
||||
currentReson = aReson;
|
||||
currentFreq = aFreq;
|
||||
poleCoeffs[1] = - (reson * reson);
|
||||
poleCoeffs[0] = (MY_FLOAT) 2.0 * reson * (MY_FLOAT) cos(TWO_PI * freq / SRATE);
|
||||
}
|
||||
|
||||
void FormSwep :: setStates(MY_FLOAT aFreq, MY_FLOAT aReson, MY_FLOAT aGain)
|
||||
{
|
||||
dirty = 0;
|
||||
freq = aFreq;
|
||||
reson = aReson;
|
||||
gain = aGain;
|
||||
targetFreq = aFreq;
|
||||
targetReson = aReson;
|
||||
targetGain = aGain;
|
||||
currentFreq = aFreq;
|
||||
currentReson = aReson;
|
||||
currentGain = aGain;
|
||||
}
|
||||
|
||||
void FormSwep :: setTargets(MY_FLOAT aFreq, MY_FLOAT aReson, MY_FLOAT aGain)
|
||||
{
|
||||
dirty = 1;
|
||||
targetFreq = aFreq;
|
||||
targetReson = aReson;
|
||||
targetGain = aGain;
|
||||
deltaFreq = aFreq - currentFreq;
|
||||
deltaReson = aReson - currentReson;
|
||||
deltaGain = aGain - currentGain;
|
||||
sweepState = (MY_FLOAT) 0.0;
|
||||
}
|
||||
|
||||
void FormSwep :: setSweepRate(MY_FLOAT aRate)
|
||||
{
|
||||
sweepRate = aRate;
|
||||
}
|
||||
|
||||
void FormSwep :: setSweepTime(MY_FLOAT aTime)
|
||||
{
|
||||
sweepRate = ONE_OVER_SRATE / aTime;
|
||||
}
|
||||
|
||||
void FormSwep :: setGain(MY_FLOAT aValue)
|
||||
{
|
||||
gain = aValue;
|
||||
}
|
||||
|
||||
MY_FLOAT FormSwep :: tick(MY_FLOAT sample) /* Perform Filter Operation */
|
||||
{
|
||||
MY_FLOAT temp;
|
||||
|
||||
if (dirty) {
|
||||
sweepState += sweepRate;
|
||||
if (sweepState>= 1.0) {
|
||||
sweepState = (MY_FLOAT) 1.0;
|
||||
dirty = 0;
|
||||
currentReson = targetReson;
|
||||
reson = targetReson;
|
||||
currentFreq = targetFreq;
|
||||
freq = targetFreq;
|
||||
currentGain = targetGain;
|
||||
gain = targetGain;
|
||||
}
|
||||
else {
|
||||
currentReson = reson + (deltaReson * sweepState);
|
||||
currentFreq = freq + (deltaFreq * sweepState);
|
||||
currentGain = gain + (deltaGain * sweepState);
|
||||
}
|
||||
poleCoeffs[1] = - (currentReson * currentReson);
|
||||
poleCoeffs[0] = (MY_FLOAT) 2.0 * currentReson *
|
||||
(MY_FLOAT) cos(TWO_PI * currentFreq / SRATE);
|
||||
}
|
||||
|
||||
temp = currentGain * sample;
|
||||
temp += poleCoeffs[0] * outputs[0];
|
||||
temp += poleCoeffs[1] * outputs[1];
|
||||
outputs[1] = outputs[0];
|
||||
outputs[0] = temp;
|
||||
lastOutput = outputs[0];
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
/************ Test Main Program *****************/
|
||||
/*
|
||||
|
||||
void main()
|
||||
{
|
||||
FormSwep filter;
|
||||
FILE *fd;
|
||||
MY_FLOAT temp;
|
||||
short data;
|
||||
long i;
|
||||
|
||||
fd = fopen("test.raw","wb");
|
||||
|
||||
filter.setTargets(100.0,0.99,0.01);
|
||||
for (i=0;i<20000;i++) {
|
||||
if (i%100 != 0) temp = 0.0; else temp = 1.0;
|
||||
data = filter.tick(temp) * 32000.0;
|
||||
fwrite(&data,2,1,fd);
|
||||
}
|
||||
|
||||
filter.setTargets(1000.0,0.99,0.01);
|
||||
for (i=0;i<20000;i++) {
|
||||
if (i%100 != 0) temp = 0.0; else temp = 1.0;
|
||||
data = filter.tick(temp) * 32000.0;
|
||||
fwrite(&data,2,1,fd);
|
||||
}
|
||||
|
||||
filter.setTargets(500.0,0.9999,0.001);
|
||||
for (i=0;i<20000;i++) {
|
||||
if (i%100 != 0) temp = 0.0; else temp = 1.0;
|
||||
data = filter.tick(temp) * 32000.0;
|
||||
fwrite(&data,2,1,fd);
|
||||
}
|
||||
|
||||
fclose(fd);
|
||||
}
|
||||
*/
|
||||
|
||||
46
FormSwep.h
46
FormSwep.h
@@ -1,46 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Sweepable Formant (2-pole) */
|
||||
/* Filter Class, by Perry R. Cook, 1995-96*/
|
||||
/* See books on filters to understand */
|
||||
/* more about how this works. Nothing */
|
||||
/* out of the ordinary in this version. */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__FormSwep_h)
|
||||
#define __FormSwep_h
|
||||
|
||||
#include "Filter.h"
|
||||
|
||||
class FormSwep : public Filter
|
||||
{
|
||||
protected:
|
||||
MY_FLOAT poleCoeffs[2];
|
||||
MY_FLOAT freq;
|
||||
MY_FLOAT reson;
|
||||
int dirty;
|
||||
MY_FLOAT targetFreq;
|
||||
MY_FLOAT targetReson;
|
||||
MY_FLOAT targetGain;
|
||||
MY_FLOAT currentFreq;
|
||||
MY_FLOAT currentReson;
|
||||
MY_FLOAT currentGain;
|
||||
MY_FLOAT deltaFreq;
|
||||
MY_FLOAT deltaReson;
|
||||
MY_FLOAT deltaGain;
|
||||
MY_FLOAT sweepState;
|
||||
MY_FLOAT sweepRate;
|
||||
public:
|
||||
FormSwep();
|
||||
~FormSwep();
|
||||
void clear();
|
||||
void setPoleCoeffs(MY_FLOAT *coeffs);
|
||||
void setGain(MY_FLOAT aValue);
|
||||
void setFreqAndReson(MY_FLOAT aFreq, MY_FLOAT aReson);
|
||||
void setStates(MY_FLOAT aFreq, MY_FLOAT aReson, MY_FLOAT aGain);
|
||||
void setTargets(MY_FLOAT aFreq, MY_FLOAT aReson, MY_FLOAT aGain);
|
||||
void setSweepRate(MY_FLOAT aRate);
|
||||
void setSweepTime(MY_FLOAT aTime);
|
||||
MY_FLOAT tick(MY_FLOAT sample);
|
||||
};
|
||||
|
||||
#endif
|
||||
60
HeavyMtl.cpp
60
HeavyMtl.cpp
@@ -1,60 +0,0 @@
|
||||
/******************************************/
|
||||
/* Heavy Metal Synth Subclass */
|
||||
/* of Algorithm 3 (TX81Z) Subclass of */
|
||||
/* 3 Operator FM Synth */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/******************************************/
|
||||
|
||||
#include "HeavyMtl.h"
|
||||
|
||||
HeavyMtl :: HeavyMtl() : FM4Alg3()
|
||||
{
|
||||
this->loadWaves("rawwaves/sinewave.raw",
|
||||
"rawwaves/twopeaks.raw",
|
||||
"rawwaves/twopeaks.raw",
|
||||
"rawwaves/sinewave.raw");
|
||||
|
||||
this->setRatio(0,(MY_FLOAT) (1.00 * 1.000));
|
||||
this->setRatio(1,(MY_FLOAT) (4.00 * 0.999));
|
||||
this->setRatio(2,(MY_FLOAT) (3.00 * 1.001));
|
||||
this->setRatio(3,(MY_FLOAT) (0.50 * 1.002));
|
||||
gains[0] = __FM4Op_gains[92];
|
||||
gains[1] = __FM4Op_gains[76];
|
||||
gains[2] = __FM4Op_gains[91];
|
||||
gains[3] = __FM4Op_gains[68];
|
||||
adsr[0]->setAllTimes((MY_FLOAT) 0.001,(MY_FLOAT) 0.001,(MY_FLOAT) 1.0,(MY_FLOAT) 0.01);
|
||||
adsr[1]->setAllTimes((MY_FLOAT) 0.001,(MY_FLOAT) 0.010,(MY_FLOAT) 1.0,(MY_FLOAT) 0.50);
|
||||
adsr[2]->setAllTimes((MY_FLOAT) 0.010,(MY_FLOAT) 0.005,(MY_FLOAT) 1.0,(MY_FLOAT) 0.20);
|
||||
adsr[3]->setAllTimes((MY_FLOAT) 0.030,(MY_FLOAT) 0.010,(MY_FLOAT) 0.2,(MY_FLOAT) 0.20);
|
||||
twozero->setGain((MY_FLOAT) 2.0);
|
||||
vibWave->setFreq((MY_FLOAT) 5.5);
|
||||
modDepth = (MY_FLOAT) 0.00;
|
||||
}
|
||||
|
||||
HeavyMtl :: ~HeavyMtl()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void HeavyMtl :: setFreq(MY_FLOAT frequency)
|
||||
{
|
||||
baseFreq = frequency;
|
||||
waves[0]->setFreq(baseFreq * ratios[0]);
|
||||
waves[1]->setFreq(baseFreq * ratios[1]);
|
||||
waves[2]->setFreq(baseFreq * ratios[2]);
|
||||
waves[3]->setFreq(baseFreq * ratios[3]);
|
||||
}
|
||||
|
||||
void HeavyMtl :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
||||
{
|
||||
gains[0] = amp * __FM4Op_gains[92];
|
||||
gains[1] = amp * __FM4Op_gains[76];
|
||||
gains[2] = amp * __FM4Op_gains[91];
|
||||
gains[3] = amp * __FM4Op_gains[68];
|
||||
this->setFreq(freq);
|
||||
this->keyOn();
|
||||
#if defined(_debug_)
|
||||
printf("HeavyMtl : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
22
HeavyMtl.h
22
HeavyMtl.h
@@ -1,22 +0,0 @@
|
||||
/******************************************/
|
||||
/* Heavy Metal Synth Subclass */
|
||||
/* of Algorithm 3 (TX81Z) Subclass of */
|
||||
/* 3 Operator FM Synth */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__HeavyMtl_h)
|
||||
#define __HeavyMtl_h
|
||||
|
||||
#include "FM4Alg3.h"
|
||||
|
||||
class HeavyMtl : public FM4Alg3
|
||||
{
|
||||
public:
|
||||
HeavyMtl();
|
||||
~HeavyMtl();
|
||||
virtual void setFreq(MY_FLOAT frequency);
|
||||
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
|
||||
};
|
||||
|
||||
#endif
|
||||
58
INSTALL.md
Normal file
58
INSTALL.md
Normal file
@@ -0,0 +1,58 @@
|
||||
% The Synthesis ToolKit in C++ (STK)
|
||||
% Perry R. Cook and Gary P. Scavone
|
||||
% 1995--2016
|
||||
|
||||
# The Synthesis ToolKit in C++ (STK)
|
||||
By Perry R. Cook and Gary P. Scavone, 1995--2016.
|
||||
|
||||
The Synthesis ToolKit in C++ can be used in a variety of ways, depending on your particular needs. Some people simply choose the classes they need for a particular project and copy those to their project directory. Others like to compile and link to a library of object files. STK was not designed with one particular style of use in mind.
|
||||
|
||||
## Unix systems and MinGW
|
||||
|
||||
1. If you downloaded the software from the git repository, first run autoconf,
|
||||
|
||||
autoconf
|
||||
|
||||
otherwise, if you downloaded the software from the STK source distribution, unpack the tar file,
|
||||
|
||||
tar -xzf stk-4.x.x.tar.gz
|
||||
|
||||
2. From within the directory containing this file, run configure:
|
||||
|
||||
./configure
|
||||
|
||||
3. From within each project directory, type `make`.
|
||||
|
||||
4. To compile a library of objects, type `make` from within the `src` directory.
|
||||
|
||||
Several options can be passed to configure, including:
|
||||
|
||||
--disable-realtime = only compile generic non-realtime classes
|
||||
--enable-debug = enable various debug output
|
||||
--with-alsa = choose native ALSA API support (default, linux only)
|
||||
--with-oss = choose native OSS API support (linux only)
|
||||
--with-jack = choose native JACK server API support (linux and macintosh OS-X)
|
||||
--with-core = choose OS-X Core Audio API (macintosh OS-X only)
|
||||
--with-asio = choose ASIO API support (windows only)
|
||||
--with-ds = choose DirectSound API support (windows only)
|
||||
--with-wasapi = choose Windows Audio Session API support (windows only)
|
||||
|
||||
It is now possible to specify more than one audio and MIDI API where supported. Note, however, that the ALSA library is required in order to compile the RtMidi class in Linux if the `--with-oss` option is provided (only the OSS audio API will be used, not the OSS MIDI API). Typing `./configure --help` will display all the available options. In addition, it is possible to specify the RAWWAVES and INCLUDE paths to configure as (ex. to set to /home/me/rawwaves and /home/me/include):
|
||||
|
||||
./configure RAWWAVE_PATH='$(HOME)/rawwaves/'
|
||||
./configure INCLUDE_PATH='$(HOME)/include/'
|
||||
|
||||
The ending "/" is required for the RAWWAVES path. The default behavior will set a relative path that works for the project files included with the distribution (assuming they are not moved). You can also change the RAWWAVE_PATH dynamically via the static Stk::setRawwavePath() function.
|
||||
|
||||
If you wish to use a different compiler than that selected by configure, specify that compiler in the command line (ex. to use CC):
|
||||
|
||||
./configure CXX=CC
|
||||
|
||||
|
||||
## Windows
|
||||
|
||||
MinGW support is provided in the configure script. In addition, Visual C++ 6.0 project files are included for each of the example STK projects, though these may not work with more recent versions of Visual Studio.
|
||||
|
||||
##iOS
|
||||
|
||||
You can integrate the STK in iOS projects either by using its iOS static library or Cocoapods. See the [iOS README file](iOS/README-iOS.md) for instructions.
|
||||
45
Instrmnt.cpp
45
Instrmnt.cpp
@@ -1,45 +0,0 @@
|
||||
/******************************************/
|
||||
/* Instrument SuperClass for Toolkit96 */
|
||||
/* Perry R. Cook, Princeton University */
|
||||
/******************************************/
|
||||
|
||||
#include "Instrmnt.h"
|
||||
|
||||
Instrmnt :: Instrmnt()
|
||||
{
|
||||
}
|
||||
|
||||
Instrmnt :: ~Instrmnt()
|
||||
{
|
||||
}
|
||||
|
||||
void Instrmnt :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
||||
{
|
||||
printf("Warning!! Instrument Class noteOn here!! %f %f\n",freq,amp);
|
||||
}
|
||||
|
||||
void Instrmnt :: noteOff(MY_FLOAT amp)
|
||||
{
|
||||
printf("Warning!! Instrument Class noteOff here!! %f\n",amp);
|
||||
}
|
||||
|
||||
void Instrmnt :: setFreq(MY_FLOAT freq)
|
||||
{
|
||||
printf("Warning!! Instrument Class setFreq here!! %f\n",freq);
|
||||
}
|
||||
|
||||
MY_FLOAT Instrmnt :: tick()
|
||||
{
|
||||
printf("Warning!! Instrument Class tick here!!\n");
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
MY_FLOAT Instrmnt :: lastOut()
|
||||
{
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
void Instrmnt :: controlChange(int number, MY_FLOAT value)
|
||||
{
|
||||
printf("Warning!! Instrument Class Control Change here!! %i %f\n",number,value);
|
||||
}
|
||||
26
Instrmnt.h
26
Instrmnt.h
@@ -1,26 +0,0 @@
|
||||
/******************************************/
|
||||
/* Instrument SuperClass for Toolkit96 */
|
||||
/* Perry R. Cook, Princeton University */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__Instrmnt_h)
|
||||
#define __Instrmnt_h
|
||||
|
||||
#include "Object.h"
|
||||
|
||||
class Instrmnt : public Object
|
||||
{
|
||||
protected:
|
||||
MY_FLOAT lastOutput;
|
||||
public:
|
||||
Instrmnt();
|
||||
virtual ~Instrmnt();
|
||||
MY_FLOAT lastOut();
|
||||
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
|
||||
virtual void noteOff(MY_FLOAT amp);
|
||||
virtual void setFreq(MY_FLOAT frequency);
|
||||
virtual MY_FLOAT tick();
|
||||
virtual void controlChange(int number, MY_FLOAT value);
|
||||
};
|
||||
|
||||
#endif
|
||||
166
JCRev.cpp
166
JCRev.cpp
@@ -1,166 +0,0 @@
|
||||
/*******************************************/
|
||||
/* JVRev Reverb Subclass */
|
||||
/* by Tim Stilson, 1998 */
|
||||
/* based on CLM JCRev */
|
||||
/* Integrated into STK by Gary Scavone */
|
||||
/* */
|
||||
/* This is based on some of the famous */
|
||||
/* Stanford CCRMA reverbs (NRev, KipRev) */
|
||||
/* all based on the the Chowning/Moorer/ */
|
||||
/* Schroeder reverberators, which use */
|
||||
/* networks of simple allpass and comb */
|
||||
/* delay filters. This particular */
|
||||
/* arrangement consists of 3 allpass */
|
||||
/* filters in series, followed by 4 comb */
|
||||
/* filters in parallel, an optional */
|
||||
/* lowpass filter, and two decorrelation */
|
||||
/* delay lines in parallel at the output. */
|
||||
/*******************************************/
|
||||
|
||||
#include "JCRev.h"
|
||||
|
||||
//#define LOWPASS
|
||||
|
||||
JCRev :: JCRev(MY_FLOAT T60)
|
||||
{
|
||||
/* These are the values from CLM's JCRev.ins ... I found that the
|
||||
impulse response sounded better with the shorter delay lengths.
|
||||
--Gary Scavone, 2/1998
|
||||
int lens[9] = {4799,4999,5399,5801,1051,337,113,573,487};
|
||||
*/
|
||||
int lens[9] = {1777,1847,1993,2137,389,127,43,211,179};
|
||||
int val, i;
|
||||
|
||||
if (SRATE < 44100.0) {
|
||||
double srscale = SRATE / 44100.0;
|
||||
for (i=0; i<9; i++) {
|
||||
val = (int) floor(srscale * lens[i]);
|
||||
if ((val & 1) == 0) val++;
|
||||
while (!this->isprime(val)) val += 2;
|
||||
lens[i] = val;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i<3; i++)
|
||||
{
|
||||
APdelayLine[i] = new DLineN(lens[i+4] + 2);
|
||||
APdelayLine[i]->setDelay(lens[i+4]);
|
||||
}
|
||||
for (i=0; i<4; i++)
|
||||
{
|
||||
CdelayLine[i] = new DLineN(lens[i] + 2);
|
||||
CdelayLine[i]->setDelay(lens[i]);
|
||||
combCoeff[i] = pow(10,(-3 * lens[i] / (T60 * SRATE)));
|
||||
// printf("combCoeff[%d] = %f\n", i, combCoeff[i]);
|
||||
}
|
||||
outLdelayLine = new DLineN(lens[7] + 2);
|
||||
outLdelayLine->setDelay(lens[7]);
|
||||
outRdelayLine = new DLineN(lens[8] + 2);
|
||||
outRdelayLine->setDelay(lens[8]);
|
||||
allPassCoeff = 0.7;
|
||||
effectMix = 0.3;
|
||||
this->clear();
|
||||
}
|
||||
|
||||
JCRev :: ~JCRev()
|
||||
{
|
||||
delete APdelayLine[0];
|
||||
delete APdelayLine[1];
|
||||
delete APdelayLine[2];
|
||||
delete CdelayLine[0];
|
||||
delete CdelayLine[1];
|
||||
delete CdelayLine[2];
|
||||
delete CdelayLine[3];
|
||||
delete outLdelayLine;
|
||||
delete outRdelayLine;
|
||||
}
|
||||
|
||||
void JCRev :: clear()
|
||||
{
|
||||
APdelayLine[0]->clear();
|
||||
APdelayLine[1]->clear();
|
||||
APdelayLine[2]->clear();
|
||||
CdelayLine[0]->clear();
|
||||
CdelayLine[1]->clear();
|
||||
CdelayLine[2]->clear();
|
||||
CdelayLine[3]->clear();
|
||||
outRdelayLine->clear();
|
||||
outLdelayLine->clear();
|
||||
lastOutL = 0.0;
|
||||
lastOutR = 0.0;
|
||||
combsum1=0.0;
|
||||
combsum2=0.0;
|
||||
combsum=0.0;
|
||||
}
|
||||
|
||||
void JCRev :: setEffectMix(MY_FLOAT mix)
|
||||
{
|
||||
effectMix = mix;
|
||||
}
|
||||
|
||||
MY_FLOAT JCRev :: lastOutput()
|
||||
{
|
||||
return (lastOutL + lastOutR) * 0.5;
|
||||
}
|
||||
|
||||
MY_FLOAT JCRev :: lastOutputL()
|
||||
{
|
||||
return lastOutL;
|
||||
}
|
||||
|
||||
MY_FLOAT JCRev :: lastOutputR()
|
||||
{
|
||||
return lastOutR;
|
||||
}
|
||||
|
||||
MY_FLOAT JCRev :: tick(MY_FLOAT input)
|
||||
{
|
||||
MY_FLOAT temp,temp0,temp1,temp2,temp3,temp4,temp5,temp6;
|
||||
MY_FLOAT filtout;
|
||||
|
||||
temp = APdelayLine[0]->lastOut();
|
||||
temp0 = allPassCoeff * temp;
|
||||
temp0 += input;
|
||||
APdelayLine[0]->tick(temp0);
|
||||
temp0 = -(allPassCoeff * temp0) + temp;
|
||||
|
||||
temp = APdelayLine[1]->lastOut();
|
||||
temp1 = allPassCoeff * temp;
|
||||
temp1 += temp0;
|
||||
APdelayLine[1]->tick(temp1);
|
||||
temp1 = -(allPassCoeff * temp1) + temp;
|
||||
|
||||
temp = APdelayLine[2]->lastOut();
|
||||
temp2 = allPassCoeff * temp;
|
||||
temp2 += temp1;
|
||||
APdelayLine[2]->tick(temp2);
|
||||
temp2 = -(allPassCoeff * temp2) + temp;
|
||||
|
||||
temp3 = temp2 + (combCoeff[0] * CdelayLine[0]->lastOut());
|
||||
temp4 = temp2 + (combCoeff[1] * CdelayLine[1]->lastOut());
|
||||
temp5 = temp2 + (combCoeff[2] * CdelayLine[2]->lastOut());
|
||||
temp6 = temp2 + (combCoeff[3] * CdelayLine[3]->lastOut());
|
||||
|
||||
CdelayLine[0]->tick(temp3);
|
||||
CdelayLine[1]->tick(temp4);
|
||||
CdelayLine[2]->tick(temp5);
|
||||
CdelayLine[3]->tick(temp6);
|
||||
|
||||
#ifdef LOWPASS
|
||||
combsum2=combsum1;
|
||||
combsum1=combsum;
|
||||
combsum = temp3+temp4+temp5+temp6;
|
||||
filtout= 0.5*combsum1+0.25*(combsum+combsum2);
|
||||
#else
|
||||
filtout = temp3+temp4+temp5+temp6;
|
||||
#endif
|
||||
|
||||
lastOutL = effectMix * (outLdelayLine->tick(filtout));
|
||||
lastOutR = effectMix * (outRdelayLine->tick(filtout));
|
||||
temp = (1.0 - effectMix) * input;
|
||||
lastOutL += temp;
|
||||
lastOutR += temp;
|
||||
|
||||
return (lastOutL + lastOutR) * 0.5;
|
||||
|
||||
}
|
||||
52
JCRev.h
52
JCRev.h
@@ -1,52 +0,0 @@
|
||||
/*******************************************/
|
||||
/* JVRev Reverb Subclass */
|
||||
/* by Tim Stilson, 1998 */
|
||||
/* based on CLM JCRev */
|
||||
/* Integrated into STK by Gary Scavone */
|
||||
/* */
|
||||
/* This is based on some of the famous */
|
||||
/* Stanford CCRMA reverbs (NRev, KipRev) */
|
||||
/* all based on the the Chowning/Moorer/ */
|
||||
/* Schroeder reverberators, which use */
|
||||
/* networks of simple allpass and comb */
|
||||
/* delay filters. This particular */
|
||||
/* arrangement consists of 3 allpass */
|
||||
/* filters in series, followed by 4 comb */
|
||||
/* filters in parallel, an optional */
|
||||
/* lowpass filter, and two decorrelation */
|
||||
/* delay lines in parallel at the output. */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__JCRev_h)
|
||||
#define __JCRev_h
|
||||
|
||||
#include "Object.h"
|
||||
#include "Reverb.h"
|
||||
#include "DLineN.h"
|
||||
|
||||
class JCRev : public Reverb
|
||||
{
|
||||
protected:
|
||||
DLineN *APdelayLine[3];
|
||||
DLineN *CdelayLine[4];
|
||||
DLineN *outLdelayLine;
|
||||
DLineN *outRdelayLine;
|
||||
MY_FLOAT allPassCoeff;
|
||||
MY_FLOAT combCoeff[4];
|
||||
MY_FLOAT combsum,combsum1,combsum2;
|
||||
MY_FLOAT lastOutL;
|
||||
MY_FLOAT lastOutR;
|
||||
MY_FLOAT effectMix;
|
||||
public:
|
||||
JCRev(MY_FLOAT T60);
|
||||
~JCRev();
|
||||
void clear();
|
||||
void setEffectMix(MY_FLOAT mix);
|
||||
MY_FLOAT lastOutput();
|
||||
MY_FLOAT lastOutputL();
|
||||
MY_FLOAT lastOutputR();
|
||||
MY_FLOAT tick(MY_FLOAT input);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
36
JetTabl.cpp
36
JetTabl.cpp
@@ -1,36 +0,0 @@
|
||||
/**********************************************/
|
||||
/* Jet Table Object by Perry R. Cook, 1995-96 */
|
||||
/* Consult Fletcher and Rossing, Karjalainen, */
|
||||
/* Cook, more, for information. */
|
||||
/* This, as with many other of my "tables", */
|
||||
/* is not a table, but is computed by poly- */
|
||||
/* nomial calculation. */
|
||||
/**********************************************/
|
||||
|
||||
#include "JetTabl.h"
|
||||
|
||||
JetTabl :: JetTabl()
|
||||
{
|
||||
lastOutput = (MY_FLOAT) 0.0;
|
||||
}
|
||||
|
||||
JetTabl :: ~JetTabl()
|
||||
{
|
||||
}
|
||||
|
||||
MY_FLOAT JetTabl :: lookup(MY_FLOAT sample) /* Perform "Table Lookup" */
|
||||
{ /* By Polynomial Calculation */
|
||||
lastOutput = sample *
|
||||
(sample*sample - (MY_FLOAT) 1.0); /* (x^3 - x) approximates sigmoid of jet */
|
||||
if (lastOutput > 1.0)
|
||||
lastOutput = (MY_FLOAT) 1.0; /* Saturation at +/- 1.0 */
|
||||
if (lastOutput < -1.0)
|
||||
lastOutput = (MY_FLOAT) -1.0;
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
MY_FLOAT JetTabl :: lastOut()
|
||||
{
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
22
JetTabl.h
22
JetTabl.h
@@ -1,22 +0,0 @@
|
||||
/**********************************************/
|
||||
/* Jet Table Object by Perry R. Cook, 1995-96 */
|
||||
/* Consult Fletcher and Rossing, Karjalainen, */
|
||||
/* Cook, more, for information. */
|
||||
/* This, as with many other of my "tables", */
|
||||
/* is not a table, but is computed by poly- */
|
||||
/* nomial calculation. */
|
||||
/**********************************************/
|
||||
|
||||
#include "Object.h"
|
||||
|
||||
class JetTabl : public Object
|
||||
{
|
||||
protected:
|
||||
MY_FLOAT lastOutput;
|
||||
public:
|
||||
JetTabl();
|
||||
~JetTabl();
|
||||
MY_FLOAT lookup(MY_FLOAT deltaP);
|
||||
MY_FLOAT lastOut();
|
||||
};
|
||||
|
||||
27
LICENSE
Normal file
27
LICENSE
Normal file
@@ -0,0 +1,27 @@
|
||||
The Synthesis ToolKit in C++ (STK)
|
||||
|
||||
Copyright (c) 1995--2016 Perry R. Cook and Gary P. Scavone
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
Any person wishing to distribute modifications to the Software is
|
||||
asked to send the modifications to the original developer so that they
|
||||
can be incorporated into the canonical version. This is, however, not
|
||||
a binding provision of this license.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
67
LipFilt.cpp
67
LipFilt.cpp
@@ -1,67 +0,0 @@
|
||||
/**********************************************/
|
||||
/* Lip Filter Object by Perry R. Cook, 1995-96*/
|
||||
/* The lip of the brass player has dynamics */
|
||||
/* which are controlled by the mass, spring */
|
||||
/* constant, and damping of the lip. This */
|
||||
/* filter simulates that behavior and the */
|
||||
/* transmission/reflection properties as */
|
||||
/* well. See Cook TBone and HosePlayer */
|
||||
/* instruments and articles. */
|
||||
/**********************************************/
|
||||
|
||||
#include "LipFilt.h"
|
||||
|
||||
LipFilt :: LipFilt()
|
||||
{
|
||||
MY_FLOAT coeffs[2];
|
||||
filter = new BiQuad;
|
||||
coeffs[0] = (MY_FLOAT) 0.0;
|
||||
coeffs[1] = (MY_FLOAT) 0.0;
|
||||
filter->setZeroCoeffs(coeffs);
|
||||
this->clear();
|
||||
}
|
||||
|
||||
LipFilt :: ~LipFilt()
|
||||
{
|
||||
delete filter;
|
||||
}
|
||||
|
||||
void LipFilt :: clear()
|
||||
{
|
||||
filter->clear();
|
||||
lastOutput = (MY_FLOAT) 0.0;
|
||||
}
|
||||
|
||||
void LipFilt :: setFreq(MY_FLOAT frequency)
|
||||
{
|
||||
MY_FLOAT coeffs[2];
|
||||
coeffs[0] = (MY_FLOAT) 2.0 * (MY_FLOAT) 0.997 *
|
||||
(MY_FLOAT) cos(TWO_PI * frequency / SRATE); /* damping should change with */
|
||||
coeffs[1] = (MY_FLOAT) (-0.997 * 0.997); /* lip parameters, but not yet.*/
|
||||
filter->setPoleCoeffs(coeffs);
|
||||
filter->setGain((MY_FLOAT) 0.03);
|
||||
}
|
||||
|
||||
/* NOTE: Here we should add lip tension */
|
||||
/* settings based on Mass/Spring/Damping */
|
||||
/* Maybe in TookKit97 */
|
||||
|
||||
MY_FLOAT LipFilt :: tick(MY_FLOAT mouthSample,MY_FLOAT boreSample)
|
||||
/* Perform "Table Lookup" By Polynomial Calculation */
|
||||
{
|
||||
MY_FLOAT temp;
|
||||
temp = mouthSample - boreSample; /* Differential pressure */
|
||||
temp = filter->tick(temp); /* Force -> position */
|
||||
temp = temp*temp; /* Simple position to area mapping */
|
||||
if (temp > 1.0) temp = (MY_FLOAT) 1.0; /* Saturation at + 1.0 */
|
||||
lastOutput = temp * mouthSample; /* Assume mouth input = area */
|
||||
lastOutput += ((MY_FLOAT) 1.0 - temp)
|
||||
* boreSample; /* and Bore reflection is compliment. */
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
MY_FLOAT LipFilt :: lastOut()
|
||||
{
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
28
LipFilt.h
28
LipFilt.h
@@ -1,28 +0,0 @@
|
||||
/**********************************************/
|
||||
/* Lip Filter Object by Perry R. Cook, 1995-96*/
|
||||
/* The lip of the brass player has dynamics */
|
||||
/* which are controlled by the mass, spring */
|
||||
/* constant, and damping of the lip. This */
|
||||
/* filter simulates that behavior and the */
|
||||
/* transmission/reflection properties as */
|
||||
/* well. See Cook TBone and HosePlayer */
|
||||
/* instruments and articles. */
|
||||
/**********************************************/
|
||||
|
||||
#include "Object.h"
|
||||
#include "BiQuad.h"
|
||||
|
||||
class LipFilt : public Object
|
||||
{
|
||||
protected:
|
||||
BiQuad *filter;
|
||||
MY_FLOAT lastOutput;
|
||||
public:
|
||||
LipFilt();
|
||||
~LipFilt();
|
||||
void clear();
|
||||
void setFreq(MY_FLOAT frequency);
|
||||
MY_FLOAT tick(MY_FLOAT mouthSample,MY_FLOAT boreSample);
|
||||
MY_FLOAT lastOut();
|
||||
};
|
||||
|
||||
369
MD2SKINI.cpp
369
MD2SKINI.cpp
@@ -1,369 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Simple Realtime MIDI to SKINI Parser */
|
||||
/* Gary P. Scavone, February 1998. */
|
||||
/* Revised for sockets, May & June 1998. */
|
||||
/* */
|
||||
/* This object takes MIDI from the input */
|
||||
/* stream (via the MIDIIO class), */
|
||||
/* parses it, and turns it into SKINI */
|
||||
/* messages. */
|
||||
/*******************************************/
|
||||
|
||||
#include "miditabl.h"
|
||||
#include "MIDIIO.h"
|
||||
#include "SKINI11.msg"
|
||||
|
||||
int outAHere = 0;
|
||||
|
||||
#if defined(__SGI_REALTIME_)
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
|
||||
pid_t exit_thread;
|
||||
|
||||
void newString(void *)
|
||||
{
|
||||
char inputString[128];
|
||||
printf("Type 'ex<cr>' to quit.\n");
|
||||
while (!outAHere) {
|
||||
fgets(inputString, 128, stdin);
|
||||
if (inputString[0] == 'e' && inputString[1] == 'x') {
|
||||
outAHere = 1;
|
||||
}
|
||||
else printf("Type 'ex<cr>' to quit.\n");
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(__USS_REALTIME_)
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
pthread_t exit_thread;
|
||||
|
||||
void *newString(void *)
|
||||
{
|
||||
char inputString[128];
|
||||
printf("Type 'ex<cr>' to quit.\n");
|
||||
while (!outAHere) {
|
||||
fgets(inputString, 128, stdin);
|
||||
if (inputString[0] == 'e' && inputString[1] == 'x') {
|
||||
outAHere = 1;
|
||||
}
|
||||
else printf("Type 'ex<cr>' to quit.\n");
|
||||
}
|
||||
}
|
||||
|
||||
#elif (defined(__WINDS_REALTIME_) || defined(__WINMM_REALTIME_) )
|
||||
|
||||
#include <process.h>
|
||||
#include <winsock.h>
|
||||
|
||||
unsigned long exit_thread;
|
||||
|
||||
void newString(void *)
|
||||
{
|
||||
char inputString[128];
|
||||
printf("Type 'ex<cr>' to quit.\n");
|
||||
while (!outAHere) {
|
||||
fgets(inputString, 128, stdin);
|
||||
if (inputString[0] == 'e' && inputString[1] == 'x') {
|
||||
outAHere = 1;
|
||||
}
|
||||
else printf("Type 'ex<cr>' to quit.\n");
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void errorf(void) {
|
||||
printf("useage: MD2SKINI <file name>\n");
|
||||
printf(" where the optional <file name> specifies a file\n");
|
||||
printf(" to which the SKINI output stream is written.\n");
|
||||
printf(" The SKINI output stream is always written to stdout,\n");
|
||||
printf(" whether an output file is specified or not.\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void main(int argc,char *argv[])
|
||||
{
|
||||
long j;
|
||||
MY_FLOAT byte2, byte3;
|
||||
int channel;
|
||||
int firstMessage = 1;
|
||||
int writeFileOut = 0;
|
||||
FILE *fileOut;
|
||||
MIDIIO *controller;
|
||||
|
||||
if (argc>2) {
|
||||
errorf();
|
||||
}
|
||||
|
||||
if (argc == 2) {
|
||||
fileOut = fopen(argv[1],"wb");
|
||||
writeFileOut = 1;
|
||||
}
|
||||
|
||||
MY_FLOAT dt=0.0;
|
||||
|
||||
controller = new MIDIIO();
|
||||
|
||||
/* Setup the exit thread. */
|
||||
#if defined(__SGI_REALTIME_)
|
||||
exit_thread = sproc(newString, PR_SALL);
|
||||
if (exit_thread == -1) {
|
||||
fprintf(stderr, "Unable to create exit thread.\n");
|
||||
printf("Exiting MD2SKINI process.\n");
|
||||
exit(0);
|
||||
}
|
||||
#elif defined(__USS_REALTIME_)
|
||||
int err = 0;
|
||||
err = pthread_create(&exit_thread, NULL, newString, NULL);
|
||||
if (err)
|
||||
{
|
||||
fprintf(stderr, "Unable to create exit thread.\n");
|
||||
printf("Exiting MD2SKINI process.\n");
|
||||
exit(0);
|
||||
}
|
||||
#elif (defined(__WINDS_REALTIME_) || defined(__WINMM_REALTIME_) )
|
||||
exit_thread = _beginthread(newString, 0, NULL);
|
||||
if (exit_thread == -1) {
|
||||
fprintf(stderr, "Unable to create exit thread.\n");
|
||||
printf("Exiting MD2SKINI process.\n");
|
||||
exit(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Setup the client socket */
|
||||
#if defined(__SOCKET)
|
||||
|
||||
WORD wVersionRequested = MAKEWORD(1,1);
|
||||
WSADATA wsaData;
|
||||
SOCKET theSocket;
|
||||
int nRet;
|
||||
|
||||
nRet = WSAStartup(wVersionRequested, &wsaData);
|
||||
if (wsaData.wVersion != wVersionRequested)
|
||||
{
|
||||
fprintf(stderr,"\n Wrong version\n");
|
||||
outAHere = 1;
|
||||
WSACleanup();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
theSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (theSocket == INVALID_SOCKET)
|
||||
{
|
||||
fprintf(stderr,"socket open failed\n");
|
||||
outAHere = 1;
|
||||
WSACleanup();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* Fill in the address structure */
|
||||
SOCKADDR_IN saServer;
|
||||
|
||||
/* Modified to always use the loopback address of 127.0.0.1 */
|
||||
saServer.sin_family = AF_INET;
|
||||
saServer.sin_port = htons(2001); // Port number from command line
|
||||
saServer.sin_addr.S_un.S_addr = inet_addr( "127.0.0.1" );
|
||||
|
||||
/* connect to the server */
|
||||
nRet = connect(theSocket, (LPSOCKADDR)&saServer, sizeof(struct sockaddr));
|
||||
if (nRet == SOCKET_ERROR)
|
||||
{
|
||||
fprintf(stderr,"socket connect failed\n");
|
||||
closesocket(theSocket);
|
||||
outAHere = 1;
|
||||
WSACleanup();
|
||||
exit(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Write SKINI messages to buffer 's'. This is the easiest way
|
||||
to allow this single executable to work for both socketing
|
||||
and printf's to stdout.
|
||||
*/
|
||||
char s[128];
|
||||
|
||||
while (!outAHere) {
|
||||
if (controller->nextMessage() > 0) {
|
||||
byte3 = controller->getByteThree();
|
||||
byte2 = controller->getByteTwo();
|
||||
channel = controller->getChannel();
|
||||
if (writeFileOut) dt = controller->getDeltaTime();
|
||||
if (firstMessage) { /* first MIDI message time stamp is meaningless */
|
||||
dt = 0.0;
|
||||
firstMessage = 0;
|
||||
}
|
||||
|
||||
switch(controller->getType()) {
|
||||
case __SK_NoteOn_:
|
||||
if (byte3 < 1.0) {
|
||||
sprintf(s,"NoteOff\t\t%.3f %d %.1f %.1f\n",0.0,channel,byte2,64.0);
|
||||
if (writeFileOut) {
|
||||
}
|
||||
} else {
|
||||
sprintf(s,"NoteOn\t\t%.3f %d %.1f %.1f\n",0.0,channel,byte2,byte3);
|
||||
if (writeFileOut) {
|
||||
fprintf(fileOut,"NoteOn\t\t%.3f %d %.1f %.1f\n",dt,channel,byte2,byte3);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case __SK_NoteOff_:
|
||||
if (byte3 < 2.0) byte3 = 64.0;
|
||||
sprintf(s,"NoteOff\t\t%.3f %d %.1f %.1f\n",0.0,channel,byte2,byte3);
|
||||
if (writeFileOut) {
|
||||
fprintf(fileOut,"NoteOff\t\t%.3f %d %.1f %.1f\n",dt,channel,byte2,byte3);
|
||||
}
|
||||
break;
|
||||
|
||||
case __SK_PolyPressure_:
|
||||
sprintf(s,"PolyPressure\t%.3f %d %.1f %.1f\n",0.0,channel,byte2,byte3);
|
||||
if (writeFileOut) {
|
||||
fprintf(fileOut,"PolyPressure\t%.3f %d %.1f %.1f\n",dt,channel,byte2,byte3);
|
||||
}
|
||||
break;
|
||||
|
||||
case __SK_ControlChange_:
|
||||
j = (int) byte2;
|
||||
switch(j) {
|
||||
case __SK_Volume_:
|
||||
sprintf(s,"Volume\t%.3f %d %.1f\n",0.0,channel,byte3);
|
||||
if (writeFileOut) {
|
||||
fprintf(fileOut,"Volume\t%.3f %d %.1f\n",dt,channel,byte3);
|
||||
}
|
||||
break;
|
||||
case __SK_ModWheel_:
|
||||
sprintf(s,"ModWheel\t%.3f %d %.1f\n",0.0,channel,byte3);
|
||||
if (writeFileOut) {
|
||||
fprintf(fileOut,"ModWheel\t%.3f %d %.1f\n",dt,channel,byte3);
|
||||
}
|
||||
break;
|
||||
case __SK_Breath_:
|
||||
sprintf(s,"Breath\t\t%.3f %d %.1f\n",0.0,channel,byte3);
|
||||
if (writeFileOut) {
|
||||
fprintf(fileOut,"Breath\t\t%.3f %d %.1f\n",dt,channel,byte3);
|
||||
}
|
||||
break;
|
||||
case __SK_FootControl_:
|
||||
sprintf(s,"FootControl\t%.3f %d %.1f\n",0.0,channel,byte3);
|
||||
if (writeFileOut) {
|
||||
fprintf(fileOut,"FootControl\t%.3f %d %.1f\n",dt,channel,byte3);
|
||||
}
|
||||
break;
|
||||
case __SK_Portamento_:
|
||||
sprintf(s,"Portamento\t%.3f %d %.1f\n",0.0,channel,byte3);
|
||||
if (writeFileOut) {
|
||||
fprintf(fileOut,"Portamento\t%.3f %d %.1f\n",dt,channel,byte3);
|
||||
}
|
||||
break;
|
||||
case __SK_Balance_:
|
||||
sprintf(s,"Balance\t%.3f %d %.1f\n",0.0,channel,byte3);
|
||||
if (writeFileOut) {
|
||||
fprintf(fileOut,"Balance\t%.3f %d %.1f\n",dt,channel,byte3);
|
||||
}
|
||||
break;
|
||||
case __SK_Pan_:
|
||||
sprintf(s,"Pan\t\t%.3f %d %.1f\n",0.0,channel,byte3);
|
||||
if (writeFileOut) {
|
||||
fprintf(fileOut,"Pan\t\t%.3f %d %.1f\n",dt,channel,byte3);
|
||||
}
|
||||
break;
|
||||
case __SK_Sustain_:
|
||||
sprintf(s,"Sustain\t%.3f %d %.1f\n",0.0,channel,byte3);
|
||||
if (writeFileOut) {
|
||||
fprintf(fileOut,"Sustain\t%.3f %d %.1f\n",dt,channel,byte3);
|
||||
}
|
||||
break;
|
||||
case __SK_Expression_:
|
||||
sprintf(s,"Expression\t%.3f %d %.1f\n",0.0,channel,byte3);
|
||||
if (writeFileOut) {
|
||||
fprintf(fileOut,"Expression\t%.3f %d %.1f\n",dt,channel,byte3);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
sprintf(s,"ControlChange\t%.3f %d %ld %.1f\n",0.0,channel,j,byte3);
|
||||
if (writeFileOut) {
|
||||
fprintf(fileOut,"ControlChange\t%.3f %d %ld %.1f\n",dt,channel,j,byte3);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case __SK_ProgramChange_:
|
||||
j = (int) byte2;
|
||||
sprintf(s,"ProgramChange\t%.3f %d %ld\n",0.0,channel,j);
|
||||
if (writeFileOut) {
|
||||
fprintf(fileOut,"ProgramChange\t%.3f %d %ld\n",dt,channel,j);
|
||||
}
|
||||
break;
|
||||
|
||||
case __SK_ChannelPressure_:
|
||||
sprintf(s,"ChannelPressure\t%.3f %d %.1f\n",0.0,channel,byte2);
|
||||
if (writeFileOut) {
|
||||
fprintf(fileOut,"ChannelPressure\t%.3f %d %.1f\n",dt,channel,byte2);
|
||||
}
|
||||
break;
|
||||
|
||||
case __SK_PitchBend_:
|
||||
sprintf(s,"PitchBend\t%.3f %d %f\n",0.0,channel,byte2);
|
||||
if (writeFileOut) {
|
||||
fprintf(fileOut,"PitchBend\t%.3f %d %f\n",dt,channel,byte2);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
sprintf(s,"// Unknown\t%.3f %d %f %f\n",0.0,channel,byte2,byte3);
|
||||
if (writeFileOut) {
|
||||
fprintf(fileOut,"// Unknown\t\t%.3f %d %f %f\n",dt,channel,byte2,byte3);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(__SOCKET)
|
||||
nRet = send(theSocket, s, strlen(s), 0);
|
||||
if (nRet == SOCKET_ERROR)
|
||||
{
|
||||
fprintf(stderr,"send failed\n");
|
||||
closesocket(theSocket);
|
||||
outAHere = 1;
|
||||
WSACleanup();
|
||||
exit(0);
|
||||
}
|
||||
#else
|
||||
printf("%s", s);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
memset(s, 0, sizeof(s));
|
||||
#if defined(__OS_Win_)
|
||||
} else Sleep ( (DWORD) 2);
|
||||
#else
|
||||
} else usleep( (unsigned long) 2000);
|
||||
#endif
|
||||
}
|
||||
|
||||
sprintf(s,"Exiting MD2SKINI process ... bye!\n");
|
||||
#if defined(__SOCKET)
|
||||
nRet = send(theSocket, s, strlen(s), 0);
|
||||
closesocket(theSocket);
|
||||
WSACleanup();
|
||||
#else
|
||||
printf("%s", s);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
|
||||
if (writeFileOut) {
|
||||
printf("Wrote SKINI output to file %s.\n", argv[1]);
|
||||
fclose(fileOut);
|
||||
}
|
||||
delete controller;
|
||||
|
||||
#if defined(__SGI_REALTIME_)
|
||||
kill(exit_thread, SIGKILL);
|
||||
#endif
|
||||
}
|
||||
|
||||
575
MIDIIO.cpp
575
MIDIIO.cpp
@@ -1,575 +0,0 @@
|
||||
/******************************************/
|
||||
/* MIDIIO.cpp */
|
||||
/* Realtime MIDI I/O Object for STK, */
|
||||
/* by Gary P. Scavone, 1998. */
|
||||
/* Based in part on code by Perry */
|
||||
/* Cook (SGI), Paul Leonard (Linux), */
|
||||
/* the RoseGarden team (Linux), and */
|
||||
/* Bill Putnam (Win95/NT). */
|
||||
/* */
|
||||
/* At the moment, this object only */
|
||||
/* handles MIDI Input, though MIDI */
|
||||
/* Output code can go here when someone */
|
||||
/* decides they need it (and writes it). */
|
||||
/* */
|
||||
/* This object opens a MIDI Input device */
|
||||
/* and parses MIDI messages into a MIDI */
|
||||
/* buffer. Time stamp info is converted */
|
||||
/* to deltaTime. MIDI data is stored as */
|
||||
/* MY_FLOAT to conform with SKINI. */
|
||||
/******************************************/
|
||||
|
||||
#include "MIDIIO.h"
|
||||
|
||||
#define MIDI_BUFFER_SIZE 1024
|
||||
int writeOffset;
|
||||
int readOffset;
|
||||
|
||||
|
||||
#if defined(__SGI_REALTIME_)
|
||||
|
||||
/*************************************/
|
||||
/* __SGI_REALTIME_ */
|
||||
/*************************************/
|
||||
|
||||
#include <dmedia/midi.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <signal.h>
|
||||
|
||||
MDport inport;
|
||||
|
||||
MDevent *midiBuffer;
|
||||
|
||||
pid_t midi_input_pid;
|
||||
|
||||
void midiInputThread(void *)
|
||||
{
|
||||
MDevent newMessage;
|
||||
int status;
|
||||
|
||||
while (1) {
|
||||
mdReceive(inport, &newMessage, 1);
|
||||
status = (newMessage.msg[0] & MD_STATUSMASK);
|
||||
|
||||
// Ignore Active Sensing messages
|
||||
if (!((status & 0xff) == 0xfe || (status & 0xff) == 0xf8)) {
|
||||
midiBuffer[writeOffset] = newMessage;
|
||||
writeOffset++;
|
||||
|
||||
if( writeOffset >= MIDI_BUFFER_SIZE )
|
||||
writeOffset = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MIDIIO :: MIDIIO()
|
||||
{
|
||||
int nports;
|
||||
|
||||
nports = mdInit();
|
||||
printf("%d MIDI devices available\n", nports);
|
||||
inport = mdOpenInPort(NULL);
|
||||
if (inport == NULL) {
|
||||
fprintf(stderr,"Cannot open MIDI device.\n");
|
||||
printf("Exiting MIDIIO Process.\n");
|
||||
exit(0);
|
||||
}
|
||||
mdSetStampMode(inport, MD_NOSTAMP);
|
||||
|
||||
// Set up the circular buffer for the Midi Input Messages
|
||||
midiBuffer = new MDevent[MIDI_BUFFER_SIZE];
|
||||
readOffset = 0;
|
||||
writeOffset = 0;
|
||||
|
||||
midi_input_pid = sproc(midiInputThread, PR_SALL);
|
||||
if (midi_input_pid == -1) {
|
||||
fprintf(stderr, "unable to create MIDI input thread...aborting.\n");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
MIDIIO :: ~MIDIIO()
|
||||
{
|
||||
kill (midi_input_pid, SIGKILL);
|
||||
mdClosePort(inport);
|
||||
delete [] midiBuffer;
|
||||
}
|
||||
|
||||
int MIDIIO :: nextMessage()
|
||||
{
|
||||
int status;
|
||||
int byte1;
|
||||
int byte2;
|
||||
MDevent lastEvent;
|
||||
static unsigned long long lastTimeStamp = 0;
|
||||
|
||||
if ( readOffset == writeOffset ) return 0;
|
||||
|
||||
lastEvent = midiBuffer[readOffset];
|
||||
|
||||
readOffset++;
|
||||
if ( readOffset >= MIDI_BUFFER_SIZE ) readOffset = 0;
|
||||
|
||||
status = (lastEvent.msg[0] & MD_STATUSMASK);
|
||||
byte1 = lastEvent.msg[1];
|
||||
byte2 = lastEvent.msg[2];
|
||||
channel = (lastEvent.msg[0] & MD_CHANNELMASK);
|
||||
|
||||
if ((status == MD_PROGRAMCHANGE) ||
|
||||
(status == MD_CHANNELPRESSURE))
|
||||
{
|
||||
messageType = status;
|
||||
byteTwo = (float) byte1;
|
||||
deltaTime = (MY_FLOAT) ((lastEvent.stamp - lastTimeStamp) * 0.000000001);
|
||||
lastTimeStamp = lastEvent.stamp;
|
||||
}
|
||||
else if ((status == MD_NOTEON) || (status == MD_NOTEOFF) ||
|
||||
(status == MD_CONTROLCHANGE) || (status == MD_POLYKEYPRESSURE))
|
||||
{
|
||||
messageType = status;
|
||||
byteTwo = (float) byte1;
|
||||
byteThree = (float) byte2;
|
||||
deltaTime = (MY_FLOAT) ((lastEvent.stamp - lastTimeStamp) * 0.000000001);
|
||||
lastTimeStamp = lastEvent.stamp;
|
||||
}
|
||||
else if (status == MD_PITCHBENDCHANGE)
|
||||
{
|
||||
messageType = status;
|
||||
byteTwo = (float) byte1 * NORM_7;
|
||||
byteTwo += (float) byte2;
|
||||
deltaTime = (MY_FLOAT) ((lastEvent.stamp - lastTimeStamp) * 0.000000001);
|
||||
lastTimeStamp = lastEvent.stamp;
|
||||
}
|
||||
else
|
||||
{
|
||||
messageType = -1;
|
||||
}
|
||||
|
||||
return messageType;
|
||||
}
|
||||
|
||||
|
||||
#elif defined(__USS_REALTIME_)
|
||||
|
||||
/*************************************/
|
||||
/* __USS_REALTIME_ */
|
||||
/*************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/soundcard.h>
|
||||
#include <pthread.h>
|
||||
//#include <pthread/mit/pthread.h>
|
||||
|
||||
int _seqfd;
|
||||
|
||||
typedef unsigned char byte;
|
||||
|
||||
typedef struct {
|
||||
byte data[4];
|
||||
unsigned long time;
|
||||
} MIDIMESSAGE;
|
||||
|
||||
MIDIMESSAGE *midiBuffer;
|
||||
|
||||
/* System Messages */
|
||||
#define MIDI_SYSTEM_MSG ((byte)0xF0)
|
||||
#define MessageType(MSG) (byte)((MSG) & ((byte)0xF0))
|
||||
|
||||
#define SEQUENCER_PATH "/dev/sequencer"
|
||||
|
||||
/* MIDI time code at 100 ticks per second. */
|
||||
#define OSS_MIDI_CLOCK_RATE 100
|
||||
|
||||
pthread_t midi_input_thread;
|
||||
|
||||
void *midiInputThread(void *)
|
||||
{
|
||||
byte NumArgs = 0;
|
||||
byte ArgsLeft = 0;
|
||||
unsigned long lastTime = 0;
|
||||
unsigned long newTime = 0;
|
||||
byte InBytes[4];
|
||||
static MIDIMESSAGE newMessage;
|
||||
int n;
|
||||
|
||||
while (1) {
|
||||
if ((n = read(_seqfd, &InBytes, sizeof(InBytes))) == -1) {
|
||||
fprintf(stderr,"Error reading " SEQUENCER_PATH "\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
switch ( InBytes[0] )
|
||||
{
|
||||
case SEQ_WAIT:
|
||||
/* MIDI clock ticks ... the first MIDI message deltaTime is calculated
|
||||
* with respect to the start of the MIDI clock.
|
||||
*/
|
||||
newTime = ((InBytes[3]<<16)|(InBytes[2]<<8)| InBytes[1]);
|
||||
break;
|
||||
|
||||
case SEQ_ECHO:
|
||||
/* no echo events yet defined */
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,"ECHO EVENT\n");
|
||||
#endif
|
||||
break;
|
||||
|
||||
case SEQ_MIDIPUTC:
|
||||
/* Determination of a full MIDI message from the input MIDI stream is based
|
||||
here on the observation that MIDI status bytes and subsequent data bytes
|
||||
are NOT returned in the same read() call. Rather, they are spread out
|
||||
over multiple read() returns, with only a single value per return. So,
|
||||
if we find a status byte, we then determine the number of expected
|
||||
operands and process that number of subsequent read()s to determine the
|
||||
complete MIDI message.
|
||||
*/
|
||||
if (InBytes[1] & 0x80) { /* Status Byte */
|
||||
if (MessageType(InBytes[1]) == MIDI_SYSTEM_MSG)
|
||||
{
|
||||
NumArgs = 0; /* no timing info */
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "SYSTEM MESSAGE\n");
|
||||
#endif
|
||||
}
|
||||
else if (MessageType(InBytes[1]) == MIDI_PGM_CHANGE ||
|
||||
MessageType(InBytes[1]) == MIDI_CHN_PRESSURE)
|
||||
{
|
||||
NumArgs = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
NumArgs = 2;
|
||||
}
|
||||
newMessage.data[0] = InBytes[1];
|
||||
ArgsLeft = NumArgs;
|
||||
newMessage.data[1] = 0;
|
||||
newMessage.data[2] = 0;
|
||||
}
|
||||
|
||||
if (ArgsLeft && !(InBytes[1] & 0x80)) { /* not a status byte */
|
||||
if (ArgsLeft == NumArgs)
|
||||
newMessage.data[1] = InBytes[1];
|
||||
else
|
||||
{
|
||||
newMessage.data[2] = InBytes[1];
|
||||
}
|
||||
|
||||
--ArgsLeft;
|
||||
|
||||
/* If MIDI message complete, then setup for running status mode
|
||||
(another event of the same type without status byte).
|
||||
*/
|
||||
if ( !ArgsLeft ) {
|
||||
if (MessageType(newMessage.data[0]) == (int) MIDI_PGM_CHANGE ||
|
||||
MessageType(newMessage.data[0]) == (int) MIDI_CHN_PRESSURE)
|
||||
{
|
||||
ArgsLeft = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
ArgsLeft = 2;
|
||||
}
|
||||
newMessage.time = newTime - lastTime;
|
||||
lastTime = newTime;
|
||||
|
||||
// Put newMessage in the circular buffer
|
||||
midiBuffer[writeOffset] = newMessage;
|
||||
writeOffset++;
|
||||
|
||||
if( writeOffset >= MIDI_BUFFER_SIZE )
|
||||
writeOffset = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MIDIIO :: MIDIIO()
|
||||
{
|
||||
int err = 0;
|
||||
_seqfd = 0;
|
||||
|
||||
#ifdef NONBLOCKING_MIDI
|
||||
if((_seqfd = open(SEQUENCER_PATH, O_RDONLY+O_NONBLOCK, 0)) == -1) {
|
||||
#else
|
||||
if((_seqfd = open(SEQUENCER_PATH, O_RDONLY, 0)) == -1) {
|
||||
#endif
|
||||
fprintf(stderr,"Cannot open " SEQUENCER_PATH ". \n");
|
||||
printf("Exiting MIDIIO Process.\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// Set up the circular buffer for the Midi Input Messages
|
||||
midiBuffer = new MIDIMESSAGE[MIDI_BUFFER_SIZE];
|
||||
readOffset = 0;
|
||||
writeOffset = 0;
|
||||
|
||||
err = pthread_create(&midi_input_thread, NULL, midiInputThread, NULL);
|
||||
if (err)
|
||||
{
|
||||
fprintf(stderr, "Unable to create MIDI input thread.\n");
|
||||
printf("Exiting MIDIIO Process.\n");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
MIDIIO :: ~MIDIIO()
|
||||
{
|
||||
if (_seqfd != 0) close(_seqfd);
|
||||
delete [] midiBuffer;
|
||||
}
|
||||
|
||||
int MIDIIO::nextMessage()
|
||||
{
|
||||
MIDIMESSAGE lastEvent;
|
||||
unsigned long micros = 2000;
|
||||
|
||||
if ( readOffset == writeOffset ) return 0;
|
||||
|
||||
lastEvent = midiBuffer[readOffset];
|
||||
|
||||
readOffset++;
|
||||
if ( readOffset >= MIDI_BUFFER_SIZE ) readOffset = 0;
|
||||
|
||||
messageType = (int) (lastEvent.data[0] & 0xf0);
|
||||
channel = (int) (lastEvent.data[0] & 0x0f);
|
||||
byteTwo = (float) lastEvent.data[1];
|
||||
if (messageType == (int) MIDI_PITCH_BEND)
|
||||
byteTwo = (float) lastEvent.data[2] + (byteTwo * NORM_7);
|
||||
else
|
||||
byteThree = (float) lastEvent.data[2];
|
||||
deltaTime = (float) lastEvent.time / OSS_MIDI_CLOCK_RATE;
|
||||
|
||||
return messageType;
|
||||
}
|
||||
|
||||
|
||||
#elif (defined(__WINDS_REALTIME_) || defined(__WINMM_REALTIME_) )
|
||||
|
||||
/*************************************/
|
||||
/* __WIN_REALTIME_ */
|
||||
/*************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "MIDIIO.h"
|
||||
|
||||
#define MIDI_NOTEON 0x90
|
||||
#define MIDI_NOTEOFF 0x80
|
||||
#define MIDI_POLYKEYPRESSURE 0xA0
|
||||
#define MIDI_CHANNELPRESSURE 0xD0
|
||||
#define MIDI_PROGRAMCHANGE 0xC0
|
||||
#define MIDI_CONTROLCHANGE 0xB0
|
||||
#define MIDI_PITCHBEND 0xE0
|
||||
|
||||
typedef struct {
|
||||
DWORD data;
|
||||
DWORD time;
|
||||
} MIDIMESSAGE;
|
||||
|
||||
MIDIMESSAGE *midiBuffer;
|
||||
|
||||
static void CALLBACK midiInputCallback( HMIDIOUT hmin, UINT inputStatus,
|
||||
DWORD instancePtr, DWORD midiMessage, DWORD timestamp)
|
||||
{
|
||||
MIDIMESSAGE newMessage;
|
||||
|
||||
switch (inputStatus) {
|
||||
case MIM_OPEN:
|
||||
#ifdef TESTING_MIDI_IN
|
||||
printf("MIM_OPEN\n");
|
||||
#endif
|
||||
break;
|
||||
|
||||
case MIM_CLOSE:
|
||||
#ifdef TESTING_MIDI_IN
|
||||
printf("MIM_CLOSE\n");
|
||||
#endif
|
||||
break;
|
||||
|
||||
case MIM_DATA:
|
||||
#ifdef TESTING_MIDI_IN
|
||||
printf("MIM_DATA\n");
|
||||
#endif
|
||||
// Ignore Active Sensing messages
|
||||
if ((midiMessage & 0xff) == 0xfe || (midiMessage & 0xff) == 0xf8) {
|
||||
break;
|
||||
}
|
||||
newMessage.data = midiMessage;
|
||||
newMessage.time = timestamp;
|
||||
|
||||
// Put newMessage in the circular buffer
|
||||
midiBuffer[writeOffset] = newMessage;
|
||||
writeOffset++;
|
||||
|
||||
if( writeOffset >= MIDI_BUFFER_SIZE )
|
||||
writeOffset = 0;
|
||||
break;
|
||||
|
||||
case MIM_ERROR:
|
||||
fprintf(stderr,"Invalid MIDI message received!\n");
|
||||
#ifdef TESTING_MIDI_IN
|
||||
printf("MIM_ERROR\n");
|
||||
#endif
|
||||
break;
|
||||
|
||||
case MIM_LONGDATA:
|
||||
/* System exclusive buffer is returned */
|
||||
break;
|
||||
|
||||
case MIM_LONGERROR:
|
||||
#ifdef TESTING_MIDI_IN
|
||||
printf("MIM_LONGERROR\n");
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
HMIDIIN hMidiIn ; // Handle to Midi Output Device
|
||||
|
||||
MIDIIO :: MIDIIO()
|
||||
{
|
||||
MMRESULT result;
|
||||
UINT uDeviceID;
|
||||
MIDIINCAPS deviceCaps;
|
||||
UINT i;
|
||||
char inputString[128];
|
||||
|
||||
uDeviceID = midiInGetNumDevs();
|
||||
printf("%i MIDI Input Devices Available.\n",uDeviceID);
|
||||
if (uDeviceID == 0) {
|
||||
printf("Exiting MIDIIO Process.\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
for (i=0; i<uDeviceID; i++) {
|
||||
result = midiInGetDevCaps(i, &deviceCaps, sizeof(MIDIINCAPS));
|
||||
printf("MIDI Device %d is %s.\n", i, deviceCaps.szPname);
|
||||
}
|
||||
|
||||
if (uDeviceID > 1) {
|
||||
printf("\nType the MIDI Device to open: ");
|
||||
fgets(inputString, 128, stdin);
|
||||
uDeviceID = (UINT) atoi(inputString);
|
||||
}
|
||||
else uDeviceID -= 1;
|
||||
|
||||
// Open the port and return any errors
|
||||
result = midiInOpen(&hMidiIn, uDeviceID, (DWORD)&midiInputCallback, (DWORD)NULL, CALLBACK_FUNCTION);
|
||||
if (result != MMSYSERR_NOERROR) {
|
||||
fprintf(stderr,"Cannot open MIDI Input Device %d!\n", uDeviceID);
|
||||
printf("Exiting MIDIIO Process.\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// Set up the circular buffer for the Midi Input Messages
|
||||
midiBuffer = new MIDIMESSAGE[MIDI_BUFFER_SIZE];
|
||||
readOffset = 0;
|
||||
writeOffset = 0;
|
||||
|
||||
midiInStart( hMidiIn );
|
||||
}
|
||||
|
||||
MIDIIO :: ~MIDIIO()
|
||||
{
|
||||
midiInReset( hMidiIn );
|
||||
midiInStop( hMidiIn );
|
||||
midiInClose( hMidiIn );
|
||||
delete [] midiBuffer;
|
||||
}
|
||||
|
||||
int MIDIIO :: nextMessage()
|
||||
{
|
||||
int status;
|
||||
int byte1;
|
||||
int byte2;
|
||||
MIDIMESSAGE lastEvent;
|
||||
static DWORD lastTime = 0;
|
||||
static DWORD newTime = 0;
|
||||
|
||||
if ( readOffset == writeOffset ) return 0;
|
||||
|
||||
lastEvent = midiBuffer[readOffset];
|
||||
|
||||
readOffset++;
|
||||
if ( readOffset >= MIDI_BUFFER_SIZE ) readOffset = 0;
|
||||
|
||||
status = (int) (lastEvent.data & 0xff);
|
||||
byte1 = (int) (lastEvent.data & 0xff00) >> 8;
|
||||
byte2 = (int) (lastEvent.data & 0xff0000) >> 16;
|
||||
channel = (int) (status & 0x0f);
|
||||
newTime = lastEvent.time;
|
||||
deltaTime = (float) (newTime - lastTime) * 0.001;
|
||||
lastTime = newTime;
|
||||
|
||||
if ((status == MIDI_PROGRAMCHANGE) ||
|
||||
(status == MIDI_CHANNELPRESSURE))
|
||||
{
|
||||
messageType = status;
|
||||
byteTwo = (float) byte1;
|
||||
}
|
||||
else if ((status == MIDI_NOTEON) || (status == MIDI_NOTEOFF) ||
|
||||
(status == MIDI_CONTROLCHANGE) || (status == MIDI_POLYKEYPRESSURE))
|
||||
{
|
||||
messageType = status;
|
||||
byteTwo = (float) byte1;
|
||||
byteThree = (float) byte2;
|
||||
}
|
||||
else if (status == MIDI_PITCHBEND)
|
||||
{
|
||||
messageType = status;
|
||||
byteTwo = (float) (byte1 * NORM_7);
|
||||
byteTwo += (float) byte2;
|
||||
}
|
||||
else
|
||||
{
|
||||
messageType = -1;
|
||||
}
|
||||
|
||||
return messageType;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void MIDIIO :: printMessage()
|
||||
{
|
||||
printf("type = %d, channel = %d, byte2 = %f, byte3 = %f\n",
|
||||
this->getType(), this->getChannel(), this->getByteTwo(),
|
||||
this->getByteThree());
|
||||
}
|
||||
|
||||
int MIDIIO :: getType()
|
||||
{
|
||||
return messageType;
|
||||
}
|
||||
|
||||
int MIDIIO :: getChannel()
|
||||
{
|
||||
return channel;
|
||||
}
|
||||
|
||||
MY_FLOAT MIDIIO :: getByteTwo()
|
||||
{
|
||||
return byteTwo;
|
||||
}
|
||||
|
||||
MY_FLOAT MIDIIO :: getByteThree()
|
||||
{
|
||||
return byteThree;
|
||||
}
|
||||
|
||||
MY_FLOAT MIDIIO :: getDeltaTime()
|
||||
{
|
||||
return deltaTime;
|
||||
}
|
||||
56
MIDIIO.h
56
MIDIIO.h
@@ -1,56 +0,0 @@
|
||||
/******************************************/
|
||||
/* MIDIIO.h */
|
||||
/* Realtime MIDI I/O Object for STK, */
|
||||
/* by Gary P. Scavone, 1998. */
|
||||
/* Based in part on code by Perry */
|
||||
/* Cook (SGI), Paul Leonard (Linux), */
|
||||
/* the RoseGarden team (Linux), and */
|
||||
/* Bill Putnam (Win95/NT). */
|
||||
/* */
|
||||
/* At the moment, this object only */
|
||||
/* handles MIDI Input, though MIDI */
|
||||
/* Output code can go here when someone */
|
||||
/* decides they need it (and writes it). */
|
||||
/* */
|
||||
/* This object opens a MIDI Input device */
|
||||
/* and parses MIDI data. Time stamp */
|
||||
/* info is converted to deltaTime. */
|
||||
/* MIDI data is stored as MY_FLOAT to */
|
||||
/* conform with SKINI. */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__MIDIIO_h)
|
||||
#define __MIDIIO_h
|
||||
|
||||
#include "Object.h"
|
||||
|
||||
class MIDIIO : public Object
|
||||
{
|
||||
protected:
|
||||
int messageType;
|
||||
int channel;
|
||||
float byteTwo;
|
||||
float byteThree;
|
||||
MY_FLOAT deltaTime;
|
||||
public:
|
||||
MIDIIO();
|
||||
~MIDIIO();
|
||||
void printMessage();
|
||||
int nextMessage();
|
||||
int getType();
|
||||
int getChannel();
|
||||
MY_FLOAT getByteTwo();
|
||||
MY_FLOAT getByteThree();
|
||||
MY_FLOAT getDeltaTime();
|
||||
};
|
||||
|
||||
#if (defined(__WINDS_REALTIME_) || defined(__WINMM_REALTIME_) )
|
||||
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h>
|
||||
|
||||
static void CALLBACK midiInputCallback( HMIDIOUT hmin, UINT inputStatus,
|
||||
DWORD instancePtr, DWORD midiMessage, DWORD timestamp);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
69
Makefile
69
Makefile
@@ -1,69 +0,0 @@
|
||||
# STK98 Makefile - Global version for Unix systems which have GNU
|
||||
# Makefile utilities installed. If this Makefile does not work on
|
||||
# your system, try using the platform specific Makefiles (.sgi,
|
||||
# .next, and .linux).
|
||||
|
||||
OS = $(shell uname)
|
||||
|
||||
O_FILES = Object.o Envelope.o ADSR.o Noise.o SubNoise.o \
|
||||
RawWave.o RawShot.o RawLoop.o RawInterp.o \
|
||||
Modulatr.o Filter.o OneZero.o \
|
||||
OnePole.o TwoZero.o TwoPole.o DCBlock.o \
|
||||
BiQuad.o DLineA.o DLineL.o DLineN.o VoicMang.o \
|
||||
FormSwep.o BowTabl.o JetTabl.o ReedTabl.o \
|
||||
LipFilt.o Modal4.o FM4Op.o FM4Alg3.o FM4Alg4.o \
|
||||
FM4Alg5.o FM4Alg6.o FM4Alg8.o Plucked2.o \
|
||||
SamplFlt.o Sampler.o SKINI11.o Simple.o \
|
||||
SingWave.o VoicForm.o FMVoices.o swapstuf.o \
|
||||
\
|
||||
Instrmnt.o Marimba.o Vibraphn.o AgogoBel.o Shakers.o \
|
||||
Plucked.o Mandolin.o Clarinet.o Flute.o Moog1.o \
|
||||
Brass.o Bowed.o Rhodey.o Wurley.o TubeBell.o \
|
||||
HeavyMtl.o PercFlut.o BeeThree.o DrumSynt.o \
|
||||
\
|
||||
WvOut.o SndWvOut.o WavWvOut.o MatWvOut.o \
|
||||
Reverb.o PRCRev.o JCRev.o NRev.o
|
||||
|
||||
RM = /bin/rm
|
||||
|
||||
ifeq ($(OS),NEXTSTEP) # These are for NeXT
|
||||
CC = cc -arch m68k -arch i386 -Wall
|
||||
INSTR = syntmono
|
||||
endif
|
||||
|
||||
ifeq ($(OS),IRIX) # These are for SGI
|
||||
INSTR = MD2SKINI syntmono
|
||||
CC = CC -O # -g -fullwarn -D__SGI_CC__
|
||||
O_FILES += RTWvOut.o RTSoundIO.o MIDIIO.o
|
||||
LIBRARY = -L/usr/sgitcl/lib -laudio -lmd -lm
|
||||
endif
|
||||
|
||||
ifeq ($(OS),Linux) # These are for Linux
|
||||
INSTR = syntmono MD2SKINI
|
||||
CC = gcc -O3 # -g -pg -O3
|
||||
O_FILES += RTWvOut.o RTSoundIO.o MIDIIO.o
|
||||
LIBRARY = -lpthread -lm
|
||||
# LIBRARY = /lib/libpthread.so.0 -lm
|
||||
endif
|
||||
|
||||
.SUFFIXES: .cpp
|
||||
.cpp.o: Object.h
|
||||
$(CC) -c $*.cpp
|
||||
|
||||
all: $(INSTR)
|
||||
|
||||
syntmono: syntmono.cpp $(O_FILES)
|
||||
$(CC) $(INCLUDE) -o syntmono syntmono.cpp $(O_FILES) $(LIBRARY)
|
||||
|
||||
MD2SKINI: MD2SKINI.cpp $(O_FILES)
|
||||
$(CC) -o MD2SKINI MD2SKINI.cpp $(O_FILES) $(LIBRARY)
|
||||
|
||||
clean :
|
||||
rm *.o
|
||||
rm $(INSTR)
|
||||
|
||||
cleanIns :
|
||||
rm $(INSTR)
|
||||
|
||||
strip :
|
||||
strip $(INSTR)
|
||||
@@ -1,47 +0,0 @@
|
||||
# STK98 Makefile - NeXTStep solo version
|
||||
|
||||
O_FILES = Object.o Envelope.o ADSR.o Noise.o SubNoise.o \
|
||||
RawWave.o RawShot.o RawLoop.o RawInterp.o \
|
||||
Modulatr.o Filter.o OneZero.o \
|
||||
OnePole.o TwoZero.o TwoPole.o DCBlock.o \
|
||||
BiQuad.o DLineA.o DLineL.o DLineN.o VoicMang.o \
|
||||
FormSwep.o BowTabl.o JetTabl.o ReedTabl.o \
|
||||
LipFilt.o Modal4.o FM4Op.o FM4Alg3.o FM4Alg4.o \
|
||||
FM4Alg5.o FM4Alg6.o FM4Alg8.o Plucked2.o \
|
||||
SamplFlt.o Sampler.o SKINI11.o Simple.o \
|
||||
SingWave.o VoicForm.o FMVoices.o swapstuf.o \
|
||||
\
|
||||
Instrmnt.o Marimba.o Vibraphn.o AgogoBel.o Shakers.o \
|
||||
Plucked.o Mandolin.o Clarinet.o Flute.o Moog1.o \
|
||||
Brass.o Bowed.o Rhodey.o Wurley.o TubeBell.o \
|
||||
HeavyMtl.o PercFlut.o BeeThree.o DrumSynt.o \
|
||||
\
|
||||
WvOut.o SndWvOut.o WavWvOut.o MatWvOut.o \
|
||||
Reverb.o PRCRev.o JCRev.o NRev.o
|
||||
|
||||
RM = /bin/rm
|
||||
|
||||
CC = cc -arch m68k -arch i386 -Wall
|
||||
INSTR = syntmono
|
||||
|
||||
.SUFFIXES: .cpp
|
||||
.cpp.o: Object.h
|
||||
$(CC) -c $*.cpp
|
||||
|
||||
all: $(INSTR)
|
||||
|
||||
syntmono: syntmono.cpp $(O_FILES)
|
||||
$(CC) $(INCLUDE) -o syntmono syntmono.cpp $(O_FILES) $(LIBRARY)
|
||||
|
||||
MD2SKINI: MD2SKINI.cpp $(O_FILES)
|
||||
$(CC) -o MD2SKINI MD2SKINI.cpp $(O_FILES) $(LIBRARY)
|
||||
|
||||
clean :
|
||||
rm *.o
|
||||
rm $(INSTR)
|
||||
|
||||
cleanIns :
|
||||
rm $(INSTR)
|
||||
|
||||
strip :
|
||||
strip $(INSTR)
|
||||
68
Makefile.all
68
Makefile.all
@@ -1,68 +0,0 @@
|
||||
# STK98 Makefile - Global version for Unix systems which have GNU
|
||||
# Makefile utilities installed. If this Makefile does not work on
|
||||
# your system, try using the platform specific Makefiles (.sgi,
|
||||
# .next, and .linux).
|
||||
|
||||
OS = $(shell uname)
|
||||
|
||||
O_FILES = Object.o Envelope.o ADSR.o Noise.o SubNoise.o \
|
||||
RawWave.o RawWvIn.o RawLoop.o \
|
||||
Modulatr.o Filter.o OneZero.o \
|
||||
OnePole.o TwoZero.o TwoPole.o DCBlock.o \
|
||||
BiQuad.o DLineA.o DLineL.o DLineN.o VoicMang.o \
|
||||
FormSwep.o BowTabl.o JetTabl.o ReedTabl.o \
|
||||
LipFilt.o Modal4.o FM4Op.o FM4Alg3.o FM4Alg4.o \
|
||||
FM4Alg5.o FM4Alg6.o FM4Alg8.o Plucked2.o \
|
||||
SamplFlt.o Sampler.o SKINI11.o Simple.o \
|
||||
SingWave.o VoicForm.o FMVoices.o swapstuf.o \
|
||||
\
|
||||
Instrmnt.o Marimba.o Vibraphn.o AgogoBel.o Shakers.o \
|
||||
Plucked.o Mandolin.o Clarinet.o Flute.o Moog1.o \
|
||||
Brass.o Bowed.o Rhodey.o Wurley.o TubeBell.o \
|
||||
HeavyMtl.o PercFlut.o BeeThree.o DrumSynt.o \
|
||||
\
|
||||
WvOut.o SndWvOut.o WavWvOut.o MatWvOut.o \
|
||||
Reverb.o PRCRev.o JCRev.o NRev.o
|
||||
|
||||
RM = /bin/rm
|
||||
|
||||
ifeq ($(OS),NEXTSTEP) # These are for NeXT
|
||||
CC = cc -arch m68k -arch i386 -Wall
|
||||
INSTR = syntmono
|
||||
endif
|
||||
|
||||
ifeq ($(OS),IRIX) # These are for SGI
|
||||
INSTR = MD2SKINI syntmono
|
||||
CC = CC -O # -g -fullwarn -D__SGI_CC__
|
||||
O_FILES += RTWvOut.o RTSoundIO.o MIDIIO.o
|
||||
LIBRARY = -L/usr/sgitcl/lib -laudio -lmd -lm
|
||||
endif
|
||||
|
||||
ifeq ($(OS),Linux) # These are for Linux
|
||||
INSTR = syntmono MD2SKINI
|
||||
CC = gcc -O3 # -g -pg -O3
|
||||
O_FILES += RTWvOut.o RTSoundIO.o MIDIIO.o
|
||||
LIBRARY = -lpthread -lm
|
||||
endif
|
||||
|
||||
.SUFFIXES: .cpp
|
||||
.cpp.o: Object.h
|
||||
$(CC) -c $*.cpp
|
||||
|
||||
all: $(INSTR)
|
||||
|
||||
syntmono: syntmono.cpp $(O_FILES)
|
||||
$(CC) $(INCLUDE) -o syntmono syntmono.cpp $(O_FILES) $(LIBRARY)
|
||||
|
||||
MD2SKINI: MD2SKINI.cpp $(O_FILES)
|
||||
$(CC) -o MD2SKINI MD2SKINI.cpp $(O_FILES) $(LIBRARY)
|
||||
|
||||
clean :
|
||||
rm *.o
|
||||
rm $(INSTR)
|
||||
|
||||
cleanIns :
|
||||
rm $(INSTR)
|
||||
|
||||
strip :
|
||||
strip $(INSTR)
|
||||
41
Makefile.in
Normal file
41
Makefile.in
Normal file
@@ -0,0 +1,41 @@
|
||||
### Do not edit -- Generated by 'configure --with-whatever' from Makefile.in
|
||||
|
||||
RM = /bin/rm
|
||||
|
||||
REALTIME = @realtime@
|
||||
|
||||
all :
|
||||
cd src && $(MAKE)
|
||||
cd projects/demo && $(MAKE) libdemo
|
||||
ifeq ($(REALTIME),yes)
|
||||
cd projects/effects && $(MAKE) libeffects
|
||||
cd projects/ragamatic && $(MAKE) libragamat
|
||||
cd projects/eguitar && $(MAKE) libeguitar
|
||||
endif
|
||||
cd projects/examples && $(MAKE) -f libMakefile
|
||||
|
||||
clean :
|
||||
$(RM) -f *~
|
||||
cd src && $(MAKE) clean
|
||||
cd projects/demo && $(MAKE) clean
|
||||
ifeq ($(REALTIME),yes)
|
||||
cd projects/effects && $(MAKE) clean
|
||||
cd projects/ragamatic && $(MAKE) clean
|
||||
cd projects/eguitar && $(MAKE) clean
|
||||
endif
|
||||
cd projects/examples && $(MAKE) clean
|
||||
|
||||
distclean: clean
|
||||
$(RM) -rf config.log config.status autom4te.cache Makefile
|
||||
cd src && $(MAKE) distclean
|
||||
cd projects/demo && $(MAKE) distclean
|
||||
ifeq ($(REALTIME),yes)
|
||||
cd projects/effects && $(MAKE) distclean
|
||||
cd projects/ragamatic && $(MAKE) distclean
|
||||
cd projects/eguitar && $(MAKE) distclean
|
||||
endif
|
||||
cd projects/examples && $(MAKE) distclean
|
||||
|
||||
install:
|
||||
$(MAKE) -C src install
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
# STK98 Makefile - Linux solo version
|
||||
|
||||
O_FILES = Object.o Envelope.o ADSR.o Noise.o SubNoise.o \
|
||||
RawWave.o RawShot.o RawLoop.o RawInterp.o \
|
||||
Modulatr.o Filter.o OneZero.o \
|
||||
OnePole.o TwoZero.o TwoPole.o DCBlock.o \
|
||||
BiQuad.o DLineA.o DLineL.o DLineN.o VoicMang.o \
|
||||
FormSwep.o BowTabl.o JetTabl.o ReedTabl.o \
|
||||
LipFilt.o Modal4.o FM4Op.o FM4Alg3.o FM4Alg4.o \
|
||||
FM4Alg5.o FM4Alg6.o FM4Alg8.o Plucked2.o \
|
||||
SamplFlt.o Sampler.o SKINI11.o Simple.o \
|
||||
SingWave.o VoicForm.o FMVoices.o swapstuf.o \
|
||||
\
|
||||
Instrmnt.o Marimba.o Vibraphn.o AgogoBel.o Shakers.o \
|
||||
Plucked.o Mandolin.o Clarinet.o Flute.o Moog1.o \
|
||||
Brass.o Bowed.o Rhodey.o Wurley.o TubeBell.o \
|
||||
HeavyMtl.o PercFlut.o BeeThree.o DrumSynt.o \
|
||||
\
|
||||
WvOut.o SndWvOut.o WavWvOut.o MatWvOut.o \
|
||||
Reverb.o PRCRev.o JCRev.o NRev.o \
|
||||
RTWvOut.o RTSoundIO.o MIDIIO.o
|
||||
|
||||
RM = /bin/rm
|
||||
|
||||
INSTR = syntmono MD2SKINI
|
||||
CC = gcc -O3 # -g -pg -O3
|
||||
LIBRARY = -lpthread -lm
|
||||
|
||||
.SUFFIXES: .cpp
|
||||
.cpp.o: Object.h
|
||||
$(CC) -c $*.cpp
|
||||
|
||||
all: $(INSTR)
|
||||
|
||||
syntmono: syntmono.cpp $(O_FILES)
|
||||
$(CC) $(INCLUDE) -o syntmono syntmono.cpp $(O_FILES) $(LIBRARY)
|
||||
|
||||
MD2SKINI: MD2SKINI.cpp $(O_FILES)
|
||||
$(CC) -o MD2SKINI MD2SKINI.cpp $(O_FILES) $(LIBRARY)
|
||||
|
||||
clean :
|
||||
rm *.o
|
||||
rm $(INSTR)
|
||||
|
||||
cleanIns :
|
||||
rm $(INSTR)
|
||||
|
||||
strip :
|
||||
strip $(INSTR)
|
||||
49
Makefile.sgi
49
Makefile.sgi
@@ -1,49 +0,0 @@
|
||||
# STK98 Makefile - SGI solo version
|
||||
|
||||
O_FILES = Object.o Envelope.o ADSR.o Noise.o SubNoise.o \
|
||||
RawWave.o RawShot.o RawLoop.o RawInterp.o \
|
||||
Modulatr.o Filter.o OneZero.o \
|
||||
OnePole.o TwoZero.o TwoPole.o DCBlock.o \
|
||||
BiQuad.o DLineA.o DLineL.o DLineN.o VoicMang.o \
|
||||
FormSwep.o BowTabl.o JetTabl.o ReedTabl.o \
|
||||
LipFilt.o Modal4.o FM4Op.o FM4Alg3.o FM4Alg4.o \
|
||||
FM4Alg5.o FM4Alg6.o FM4Alg8.o Plucked2.o \
|
||||
SamplFlt.o Sampler.o SKINI11.o Simple.o \
|
||||
SingWave.o VoicForm.o FMVoices.o swapstuf.o \
|
||||
\
|
||||
Instrmnt.o Marimba.o Vibraphn.o AgogoBel.o Shakers.o \
|
||||
Plucked.o Mandolin.o Clarinet.o Flute.o Moog1.o \
|
||||
Brass.o Bowed.o Rhodey.o Wurley.o TubeBell.o \
|
||||
HeavyMtl.o PercFlut.o BeeThree.o DrumSynt.o \
|
||||
\
|
||||
WvOut.o SndWvOut.o WavWvOut.o MatWvOut.o \
|
||||
Reverb.o PRCRev.o JCRev.o NRev.o \
|
||||
RTWvOut.o RTSoundIO.o MIDIIO.o
|
||||
|
||||
RM = /bin/rm
|
||||
|
||||
INSTR = MD2SKINI syntmono
|
||||
CC = CC -O # -g -fullwarn -D__SGI_CC__
|
||||
LIBRARY = -L/usr/sgitcl/lib -laudio -lmd -lm
|
||||
|
||||
.SUFFIXES: .cpp
|
||||
.cpp.o: Object.h
|
||||
$(CC) -c $*.cpp
|
||||
|
||||
all: $(INSTR)
|
||||
|
||||
syntmono: syntmono.cpp $(O_FILES)
|
||||
$(CC) $(INCLUDE) -o syntmono syntmono.cpp $(O_FILES) $(LIBRARY)
|
||||
|
||||
MD2SKINI: MD2SKINI.cpp $(O_FILES)
|
||||
$(CC) -o MD2SKINI MD2SKINI.cpp $(O_FILES) $(LIBRARY)
|
||||
|
||||
clean :
|
||||
rm *.o
|
||||
rm $(INSTR)
|
||||
|
||||
cleanIns :
|
||||
rm $(INSTR)
|
||||
|
||||
strip :
|
||||
strip $(INSTR)
|
||||
143
Mandolin.cpp
143
Mandolin.cpp
@@ -1,143 +0,0 @@
|
||||
/********************************************/
|
||||
/* Commuted Mandolin Subclass of enhanced */
|
||||
/* dual plucked-string model */
|
||||
/* by Perry Cook, 1995-96 */
|
||||
/* Controls: CONTROL1 = bodySize */
|
||||
/* CONTROL2 = pluckPosition */
|
||||
/* CONTROL3 = loopGain */
|
||||
/* MOD_WHEEL= deTuning */
|
||||
/* */
|
||||
/* Note: Commuted Synthesis, as with many */
|
||||
/* other WaveGuide techniques, is covered */
|
||||
/* by patents, granted, pending, and/or */
|
||||
/* applied-for. Many are assigned to the */
|
||||
/* Board of Trustees, Stanford University. */
|
||||
/* For information, contact the Office of */
|
||||
/* Technology Licensing, Stanford U. */
|
||||
/********************************************/
|
||||
|
||||
#include "Mandolin.h"
|
||||
#include "SKINI11.msg"
|
||||
|
||||
Mandolin :: Mandolin(MY_FLOAT lowestFreq) : Plucked2(lowestFreq)
|
||||
{
|
||||
int i;
|
||||
|
||||
soundfile[0] = new RawInterp("rawwaves/mand1.raw");
|
||||
soundfile[1] = new RawInterp("rawwaves/mand2.raw");
|
||||
soundfile[2] = new RawInterp("rawwaves/mand3.raw");
|
||||
soundfile[3] = new RawInterp("rawwaves/mand4.raw");
|
||||
soundfile[4] = new RawInterp("rawwaves/mand5.raw");
|
||||
soundfile[5] = new RawInterp("rawwaves/mand6.raw");
|
||||
soundfile[6] = new RawInterp("rawwaves/mand7.raw");
|
||||
soundfile[7] = new RawInterp("rawwaves/mand8.raw");
|
||||
soundfile[8] = new RawInterp("rawwaves/mand9.raw");
|
||||
soundfile[9] = new RawInterp("rawwaves/mand10.raw");
|
||||
soundfile[10] = new RawInterp("rawwaves/mand11.raw");
|
||||
soundfile[11] = new RawInterp("rawwaves/mand12.raw");
|
||||
for (i=0;i<12;i++) {
|
||||
// soundfile[i]->normalize((MY_FLOAT) 0.1); /* Empirical hack here */
|
||||
soundfile[i]->setLooping(0);
|
||||
}
|
||||
directBody = 1.0;
|
||||
mic = 0;
|
||||
dampTime = 0;
|
||||
waveDone = 1;
|
||||
}
|
||||
|
||||
Mandolin :: ~Mandolin()
|
||||
{
|
||||
}
|
||||
|
||||
void Mandolin :: pluck(MY_FLOAT amplitude)
|
||||
{ /* this function gets interesting here, */
|
||||
/* because pluck may be longer than */
|
||||
/* string length, so we just reset the */
|
||||
/* soundfile and add in the pluck in */
|
||||
/* the tick method. */
|
||||
soundfile[mic]->reset();
|
||||
pluckAmp = amplitude;
|
||||
/* Set Pick Position which puts zeroes at pos*length */
|
||||
combDelay->setDelay((MY_FLOAT) 0.5 * pluckPos * lastLength);
|
||||
dampTime = (long) lastLength; /* See tick method below */
|
||||
waveDone = 0;
|
||||
}
|
||||
|
||||
void Mandolin :: pluck(MY_FLOAT amplitude, MY_FLOAT position)
|
||||
{
|
||||
pluckPos = position; /* pluck position is zeroes at pos*length */
|
||||
this->pluck(amplitude);
|
||||
}
|
||||
|
||||
void Mandolin :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
||||
{
|
||||
this->setFreq(freq);
|
||||
this->pluck(amp);
|
||||
#if defined(_debug_)
|
||||
printf("Mandolin : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Mandolin :: setBodySize(MY_FLOAT size)
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<12;i++) {
|
||||
soundfile[i]->setRate(size);
|
||||
}
|
||||
}
|
||||
|
||||
MY_FLOAT Mandolin :: tick()
|
||||
{
|
||||
MY_FLOAT temp = (MY_FLOAT) 0;
|
||||
if (!waveDone) {
|
||||
waveDone = soundfile[mic]->informTick(); /* as long as it goes . . . */
|
||||
temp = soundfile[mic]->lastOut() * pluckAmp; /* scaled pluck excitation */
|
||||
temp = temp - combDelay->tick(temp); /* with comb filtering */
|
||||
}
|
||||
if (dampTime>=0) { /* Damping hack to help avoid */
|
||||
dampTime -= 1; /* overflow on replucking */
|
||||
lastOutput = delayLine->tick( /* Calculate 1st delay */
|
||||
filter->tick( /* filterered reflection */
|
||||
temp + /* plus pluck excitation */
|
||||
(delayLine->lastOut() * (MY_FLOAT) 0.7)));
|
||||
lastOutput += delayLine2->tick( /* and 2nd delay */
|
||||
filter2->tick( /* just like the 1st */
|
||||
temp +
|
||||
(delayLine2->lastOut() * (MY_FLOAT) 0.7))); /* that's the whole thing!! */
|
||||
}
|
||||
else { /* No damping hack after 1 period */
|
||||
lastOutput = delayLine->tick( /* Calculate 1st delay */
|
||||
filter->tick( /* filtered reflection */
|
||||
temp + /* plus pluck excitation */
|
||||
(delayLine->lastOut() * loopGain)));
|
||||
lastOutput += delayLine2->tick( /* and 2nd delay */
|
||||
filter2->tick( /* just like the 1st */
|
||||
temp +
|
||||
(delayLine2->lastOut() * loopGain)));
|
||||
}
|
||||
lastOutput *= (MY_FLOAT) 0.3 / 32768.0;
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
void Mandolin :: controlChange(int number, MY_FLOAT value)
|
||||
{
|
||||
#if defined(_debug_)
|
||||
printf("Mandolin : ControlChange: Number=%i Value=%f\n",number,value);
|
||||
#endif
|
||||
if (number == __SK_BodySize_)
|
||||
this->setBodySize(value * (MY_FLOAT) NORM_7 * (MY_FLOAT) 2.0);
|
||||
else if (number == __SK_PickPosition_)
|
||||
this->setPluckPos(value * (MY_FLOAT) NORM_7);
|
||||
else if (number == __SK_StringDamping_)
|
||||
this->setBaseLoopGain((MY_FLOAT) 0.97 + (value * (MY_FLOAT) NORM_7 * (MY_FLOAT) 0.03));
|
||||
else if (number == __SK_StringDetune_)
|
||||
this->setDetune((MY_FLOAT) 1.0 - (value * (MY_FLOAT) NORM_7 * (MY_FLOAT) 0.1));
|
||||
else if (number == __SK_AfterTouch_)
|
||||
this->pluck(value * (MY_FLOAT) NORM_7);
|
||||
else if (number == 411) {
|
||||
mic = (int) value % 12;
|
||||
}
|
||||
else {
|
||||
printf("Mandolin : Undefined Control Number!! %i\n",number);
|
||||
}
|
||||
}
|
||||
44
Mandolin.h
44
Mandolin.h
@@ -1,44 +0,0 @@
|
||||
/********************************************/
|
||||
/* Commuted Mandolin Subclass of enhanced */
|
||||
/* dual plucked-string model */
|
||||
/* by Perry Cook, 1995-96 */
|
||||
/* Controls: CONTROL1 = bodySize */
|
||||
/* CONTROL2 = pluckPosition */
|
||||
/* CONTROL3 = loopGain */
|
||||
/* MOD_WHEEL= deTuning */
|
||||
/* */
|
||||
/* Note: Commuted Synthesis, as with many */
|
||||
/* other WaveGuide techniques, is covered */
|
||||
/* by patents, granted, pending, and/or */
|
||||
/* applied-for. All are assigned to the */
|
||||
/* Board of Trustees, Stanford University. */
|
||||
/* For information, contact the Office of */
|
||||
/* Technology Licensing, Stanford U. */
|
||||
/********************************************/
|
||||
|
||||
#if !defined(__Mandolin_h)
|
||||
#define __Mandolin_h
|
||||
|
||||
#include "Plucked2.h"
|
||||
#include "RawInterp.h"
|
||||
|
||||
class Mandolin : public Plucked2
|
||||
{
|
||||
protected:
|
||||
RawInterp *soundfile[12];
|
||||
MY_FLOAT directBody;
|
||||
int mic;
|
||||
long dampTime;
|
||||
int waveDone;
|
||||
public:
|
||||
Mandolin(MY_FLOAT lowestFreq);
|
||||
virtual ~Mandolin();
|
||||
void pluck(MY_FLOAT amplitude);
|
||||
void pluck(MY_FLOAT amplitude,MY_FLOAT position);
|
||||
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
|
||||
void setBodySize(MY_FLOAT size);
|
||||
virtual void controlChange(int number, MY_FLOAT value);
|
||||
virtual MY_FLOAT tick();
|
||||
};
|
||||
|
||||
#endif
|
||||
113
Marimba.cpp
113
Marimba.cpp
@@ -1,113 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Marimba SubClass of Modal4 Instrument, */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* */
|
||||
/* Controls: CONTROL1 = stickHardness */
|
||||
/* CONTROL2 = strikePosition*/
|
||||
/* CONTROL3 = vibFreq */
|
||||
/* MOD_WHEEL= vibAmt */
|
||||
/*******************************************/
|
||||
|
||||
#include "Marimba.h"
|
||||
#include "SKINI11.msg"
|
||||
|
||||
Marimba :: Marimba() : Modal4()
|
||||
{
|
||||
wave = new RawInterp("rawwaves/marmstk1.raw");
|
||||
wave->normalize();
|
||||
wave->setRate((MY_FLOAT) 0.5); /* normal stick */
|
||||
this->setRatioAndReson(0, (MY_FLOAT) 1.00,(MY_FLOAT) 0.9996); /* Set all 132.0 */
|
||||
this->setRatioAndReson(1, (MY_FLOAT) 3.99,(MY_FLOAT) 0.9994); /* of our 523.0 */
|
||||
this->setRatioAndReson(2,(MY_FLOAT) 10.65,(MY_FLOAT) 0.9994); /* default 1405.0 */
|
||||
this->setRatioAndReson(3,-(MY_FLOAT) 2443.0,(MY_FLOAT) 0.999); /* resonances 2443.0 */
|
||||
this->setFiltGain(0,(MY_FLOAT) 0.04); /* and */
|
||||
this->setFiltGain(1,(MY_FLOAT) 0.01); /* gains */
|
||||
this->setFiltGain(2,(MY_FLOAT) 0.01); /* for each */
|
||||
this->setFiltGain(3,(MY_FLOAT) 0.008); /* resonance */
|
||||
directGain = (MY_FLOAT) 0.1;
|
||||
multiStrike = 0;
|
||||
}
|
||||
|
||||
Marimba :: ~Marimba()
|
||||
{
|
||||
delete wave;
|
||||
}
|
||||
|
||||
void Marimba :: setStickHardness(MY_FLOAT hardness)
|
||||
{
|
||||
stickHardness = hardness;
|
||||
wave->setRate((MY_FLOAT) (0.25 * (MY_FLOAT) pow(4.0,stickHardness)));
|
||||
masterGain = (MY_FLOAT) 0.1 + ((MY_FLOAT) 1.8 * stickHardness);
|
||||
}
|
||||
|
||||
void Marimba :: setStrikePosition(MY_FLOAT position)
|
||||
{
|
||||
MY_FLOAT temp,temp2;
|
||||
temp2 = position * PI;
|
||||
strikePosition = position; /* Hack only first three modes */
|
||||
temp = (MY_FLOAT) sin(temp2);
|
||||
this->setFiltGain(0,(MY_FLOAT) 0.12 * temp); /* 1st mode function of pos. */
|
||||
temp = (MY_FLOAT) sin(0.05 + (3.9 * temp2));
|
||||
this->setFiltGain(1,(MY_FLOAT) -0.03 * temp); /* 2nd mode function of pos. */
|
||||
temp = (MY_FLOAT) sin(-0.05 + (11 * temp2));
|
||||
this->setFiltGain(2,(MY_FLOAT) 0.11 * temp); /* 3rd mode function of pos. */
|
||||
}
|
||||
|
||||
void Marimba :: setModulationSpeed(MY_FLOAT mSpeed)
|
||||
{
|
||||
/* don't bother here, marimba decay so fast, mod doesn't make sense */
|
||||
}
|
||||
|
||||
void Marimba :: setModulationDepth(MY_FLOAT mDepth)
|
||||
{
|
||||
}
|
||||
|
||||
void Marimba :: strike(MY_FLOAT amplitude)
|
||||
{
|
||||
int temp;
|
||||
temp = rand() >> 10;
|
||||
if (temp < 2) {
|
||||
multiStrike = 1;
|
||||
#if defined(_debug_)
|
||||
printf("striking twice here!!\n");
|
||||
#endif
|
||||
}
|
||||
else if (temp < 1) {
|
||||
multiStrike = 2;
|
||||
#if defined(_debug_)
|
||||
printf("striking three times here!!!\n");
|
||||
#endif
|
||||
}
|
||||
else multiStrike = 0;
|
||||
Modal4::strike(amplitude);
|
||||
}
|
||||
|
||||
void Marimba :: controlChange(int number, MY_FLOAT value)
|
||||
{
|
||||
#if defined(_debug_)
|
||||
printf("Marimba : ControlChange: Number=%i Value=%f\n",number,value);
|
||||
#endif
|
||||
if (number == __SK_StickHardness_)
|
||||
this->setStickHardness(value * NORM_7);
|
||||
else if (number == __SK_StrikePosition_)
|
||||
this->setStrikePosition(value * NORM_7);
|
||||
else if (number == __SK_ModFrequency_)
|
||||
vibr->setFreq((value * NORM_7 * (MY_FLOAT) 12.0));
|
||||
else if (number == __SK_ModWheel_)
|
||||
vibrGain = (value * NORM_7);
|
||||
else if (number == __SK_AfterTouch_Cont_)
|
||||
this->strike(value * NORM_7);
|
||||
else {
|
||||
printf("Marimba : Undefined Control Number!!\n");
|
||||
}
|
||||
}
|
||||
|
||||
MY_FLOAT Marimba :: tick()
|
||||
{
|
||||
if (multiStrike>0)
|
||||
if (wave->isFinished()) {
|
||||
wave->reset();
|
||||
multiStrike -= 1;
|
||||
}
|
||||
return Modal4::tick();
|
||||
}
|
||||
32
Marimba.h
32
Marimba.h
@@ -1,32 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Marimba SubClass of Modal4 Instrument, */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* */
|
||||
/* Controls: CONTROL1 = stickHardness */
|
||||
/* CONTROL2 = strikePosition*/
|
||||
/* CONTROL3 = vibFreq */
|
||||
/* MOD_WHEEL= vibAmt */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__Marimba_h)
|
||||
#define __Marimba_h
|
||||
|
||||
#include "Modal4.h"
|
||||
|
||||
class Marimba : public Modal4
|
||||
{
|
||||
private:
|
||||
int multiStrike;
|
||||
public:
|
||||
Marimba();
|
||||
~Marimba();
|
||||
void setStickHardness(MY_FLOAT hardness);
|
||||
void setStrikePosition(MY_FLOAT position);
|
||||
void setModulationSpeed(MY_FLOAT mSpeed);
|
||||
void setModulationDepth(MY_FLOAT mDepth);
|
||||
virtual void strike(MY_FLOAT amplitude);
|
||||
virtual void controlChange(int number, MY_FLOAT value);
|
||||
virtual MY_FLOAT tick();
|
||||
};
|
||||
|
||||
#endif
|
||||
214
MatWvOut.cpp
214
MatWvOut.cpp
@@ -1,214 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Matlab MAT File Output Class, */
|
||||
/* by Gary P. Scavone, 1998. */
|
||||
/* This object creates a Matlab MAT-file */
|
||||
/* structure and fills it with buffers of */
|
||||
/* samples (doubles). */
|
||||
/* */
|
||||
/* The Matlab MAT-file format is not */
|
||||
/* available to the general public. I */
|
||||
/* spent several days reverse-engineering */
|
||||
/* the file format to create this class. */
|
||||
/* I couldn't figure out what a few of */
|
||||
/* the header fields correspond to, but */
|
||||
/* for the purposes of STK, this */
|
||||
/* shouldn't create any problems. */
|
||||
/*******************************************/
|
||||
|
||||
#include "MatWvOut.h"
|
||||
|
||||
/******** Matlab Matfile Header Struct *******/
|
||||
struct matheaderform {
|
||||
char heading[124];
|
||||
short a[2];
|
||||
long b[10];
|
||||
/* There's more, but it's of variable length */
|
||||
};
|
||||
|
||||
FILE *openMatFile(int chans,char *fileName) {
|
||||
struct matheaderform hdr;
|
||||
FILE *fd;
|
||||
char tempName[128];
|
||||
int i, namelen;
|
||||
long longtmp, headsize;
|
||||
|
||||
strcpy(hdr.heading,"MATLAB 5.0 MAT-file, Generated by STK98. This file format was hacked by Gary P. Scavone, CCRMA, Stanford University, 1998.");
|
||||
|
||||
for (i=strlen(hdr.heading);i<124;i++) hdr.heading[i] = ' ';
|
||||
|
||||
hdr.a[0] = (short) 256;
|
||||
hdr.a[1] = (short) 'M';
|
||||
hdr.a[1] <<= 8;
|
||||
hdr.a[1] += 'I';
|
||||
hdr.b[0] = (long) 14;
|
||||
hdr.b[1] = (long) 0; /* Size of file after this point to end (in bytes) */
|
||||
hdr.b[2] = (long) 6;
|
||||
hdr.b[3] = (long) 8;
|
||||
hdr.b[4] = (long) 6;
|
||||
hdr.b[5] = (long) 0;
|
||||
hdr.b[6] = (long) 5;
|
||||
hdr.b[7] = (long) 8;
|
||||
hdr.b[8] = (long) chans; /* This is the number of rows */
|
||||
hdr.b[9] = (long) 0; /* This is the number of columns */
|
||||
|
||||
strcpy(tempName,fileName);
|
||||
strcat(tempName,".mat");
|
||||
|
||||
fd = fopen(tempName,"w+b");
|
||||
if (!fd) {
|
||||
printf("Couldn't create matfile %s !!!!!!!!\n",fileName);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
printf("Creating matfile %s.\n", tempName);
|
||||
fwrite(&hdr,sizeof(char),168,fd); /* Write the fixed portion of the header */
|
||||
|
||||
/* The next 4 bytes can be viewed as two shorts, but they are byteswapped
|
||||
as a long. The first short value seems to always be one; the second
|
||||
short will be the length of the variable name IF IT IS <= 4; if the
|
||||
variable name length is >4, this short is zero and the length is put
|
||||
in the next 4 bytes. The variable name length is limited to 31
|
||||
characters (32 with a '\n'). The actual variable name then follows.
|
||||
The variable name is "zero-padded" out to the following minimum
|
||||
lengths (in bits): 4, 8, 16, 24, 32.
|
||||
*/
|
||||
namelen = strlen(fileName);
|
||||
if (namelen > 31) { /* Check length of variable name (file name) */
|
||||
fprintf(stderr, "File name too long ... should be 31 characters or less.\n");
|
||||
fclose(fd);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (namelen > 4) {
|
||||
longtmp = 1;
|
||||
fwrite(&longtmp,sizeof(long),1,fd);
|
||||
fwrite(&namelen,sizeof(long),1,fd);
|
||||
headsize = 44 + namelen;
|
||||
} else {
|
||||
longtmp = namelen;
|
||||
longtmp <<= 16;
|
||||
longtmp += 1;
|
||||
fwrite(&longtmp,sizeof(long),1,fd);
|
||||
headsize = 40 + namelen;
|
||||
}
|
||||
|
||||
fwrite(fileName,sizeof(char),namelen,fd); /* Write the variable (file) name */
|
||||
if (namelen < 5)
|
||||
longtmp = 4 - namelen;
|
||||
else if (namelen < 9)
|
||||
longtmp = 8 - namelen;
|
||||
else if (namelen < 17)
|
||||
longtmp = 16 - namelen;
|
||||
else if (namelen < 25)
|
||||
longtmp = 24 - namelen;
|
||||
else longtmp = 32 - namelen;
|
||||
|
||||
headsize += longtmp + 8; /* Add length (8) of following bytes */
|
||||
fseek(fd,longtmp,SEEK_CUR);
|
||||
|
||||
longtmp = 9;
|
||||
fwrite(&longtmp,sizeof(long),1,fd);
|
||||
longtmp = 0; /* Size of data in bytes (8 per sample) */
|
||||
fwrite(&longtmp,sizeof(long),1,fd);
|
||||
|
||||
fseek(fd,132,SEEK_SET);
|
||||
fwrite(&headsize,sizeof(long),1,fd); /* Write header size ... will update at end */
|
||||
fseek(fd,0,SEEK_END);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
MatWvOut :: MatWvOut(char *fileName)
|
||||
{
|
||||
chans = 1;
|
||||
pan = 0.5;
|
||||
fd = openMatFile(chans,fileName);
|
||||
counter = 0;
|
||||
totalCount = 0;
|
||||
}
|
||||
|
||||
MatWvOut :: MatWvOut(int channels, char *fileName)
|
||||
{
|
||||
chans = channels;
|
||||
pan = 0.5;
|
||||
fd = openMatFile(chans,fileName);
|
||||
counter = 0;
|
||||
totalCount = 0;
|
||||
}
|
||||
|
||||
MatWvOut :: ~MatWvOut()
|
||||
{
|
||||
double temp;
|
||||
long headsize, temp1;
|
||||
|
||||
fwrite(data,sizeof(double),counter,fd);
|
||||
temp = (double) totalCount * ONE_OVER_SRATE;
|
||||
printf("%f Seconds Computed\n",temp);
|
||||
fseek(fd,164,SEEK_SET);
|
||||
fwrite(&totalCount,sizeof(long),1,fd); /* Write number of columns */
|
||||
fseek(fd,132,SEEK_SET);
|
||||
fread(&headsize,sizeof(long),1,fd);
|
||||
temp1 = headsize;
|
||||
headsize += (long) (totalCount * 8 * 2);
|
||||
fseek(fd,132,SEEK_SET);
|
||||
fwrite(&headsize,sizeof(long),1,fd); /* Write file size (minus some header info) */
|
||||
fseek(fd,temp1+128,SEEK_SET);
|
||||
temp1 = totalCount * 8 * 2;
|
||||
fwrite(&temp1,sizeof(long),1,fd); /* Write data size (in bytes) */
|
||||
fclose(fd);
|
||||
}
|
||||
|
||||
long MatWvOut :: getCounter()
|
||||
{
|
||||
return totalCount;
|
||||
}
|
||||
|
||||
MY_FLOAT MatWvOut :: getTime()
|
||||
{
|
||||
return (MY_FLOAT) totalCount * ONE_OVER_SRATE;
|
||||
}
|
||||
|
||||
void MatWvOut :: tick(MY_FLOAT sample)
|
||||
{
|
||||
if (chans==1) {
|
||||
data[counter++] = (double) (sample);
|
||||
}
|
||||
else {
|
||||
data[counter++] = (double) (sample * (1.0 - pan));
|
||||
data[counter++] = (double) (sample * pan);
|
||||
}
|
||||
totalCount += 1;
|
||||
if (counter == MAT_BUFFER_SIZE) {
|
||||
fwrite(data,sizeof(double),MAT_BUFFER_SIZE,fd);
|
||||
counter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void MatWvOut :: tick(MY_FLOAT lsamp, MY_FLOAT rsamp)
|
||||
{
|
||||
if (chans==1) {
|
||||
data[counter++] = (double) (lsamp + rsamp);
|
||||
}
|
||||
else {
|
||||
data[counter++] = (double) (lsamp);
|
||||
data[counter++] = (double) (rsamp);
|
||||
}
|
||||
totalCount += 1;
|
||||
if (counter == MAT_BUFFER_SIZE) {
|
||||
fwrite(data,sizeof(double),MAT_BUFFER_SIZE,fd);
|
||||
counter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void MatWvOut :: setMonoPan(MY_FLOAT aPan)
|
||||
{
|
||||
pan = aPan;
|
||||
if (aPan < 0.0) {
|
||||
pan = 0.0;
|
||||
printf("Pan < 0.0, correcting to 0.0\n");
|
||||
}
|
||||
if (aPan > 1.0) {
|
||||
pan = 1.0;
|
||||
printf("Pan > 1.0, correcting to 1.0\n");
|
||||
}
|
||||
}
|
||||
46
MatWvOut.h
46
MatWvOut.h
@@ -1,46 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Matlab MAT File Output Class, */
|
||||
/* by Gary P. Scavone, 1998. */
|
||||
/* This object creates a Matlab MAT-file */
|
||||
/* structure and fills it with buffers of */
|
||||
/* samples (doubles). */
|
||||
/* */
|
||||
/* The Matlab MAT-file format is not */
|
||||
/* available to the general public. I */
|
||||
/* spent several days reverse-engineering */
|
||||
/* the file format to create this class. */
|
||||
/* I couldn't figure out what a few of */
|
||||
/* the header fields correspond to, but */
|
||||
/* for the purposes of STK, this */
|
||||
/* shouldn't create any problems. */
|
||||
/*******************************************/
|
||||
|
||||
#include "Object.h"
|
||||
#include "WvOut.h"
|
||||
|
||||
#if !defined(__MatWvOut_h)
|
||||
#define __MatWvOut_h
|
||||
|
||||
#define MAT_BUFFER_SIZE 1024
|
||||
|
||||
class MatWvOut : public WvOut
|
||||
{
|
||||
protected:
|
||||
FILE *fd;
|
||||
double data[MAT_BUFFER_SIZE]; /* not MY_FLOAT because MAT uses doubles */
|
||||
long counter;
|
||||
long totalCount;
|
||||
int chans;
|
||||
MY_FLOAT pan;
|
||||
public:
|
||||
MatWvOut(char *infileName);
|
||||
MatWvOut(int channels, char *infileName);
|
||||
~MatWvOut();
|
||||
long getCounter();
|
||||
MY_FLOAT getTime();
|
||||
void setMonoPan(MY_FLOAT aPan);
|
||||
void tick(MY_FLOAT sample);
|
||||
void tick(MY_FLOAT lsamp, MY_FLOAT rsamp);
|
||||
};
|
||||
|
||||
#endif // defined(__MatWvOut_h)
|
||||
186
Modal4.cpp
186
Modal4.cpp
@@ -1,186 +0,0 @@
|
||||
/*******************************************/
|
||||
/* 4 Resonance Modal Synthesis Instrument */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* This instrument contains an excitation */
|
||||
/* wavetable, an envelope, and four reso- */
|
||||
/* nances (Non-Sweeping BiQuad Filters). */
|
||||
/*******************************************/
|
||||
|
||||
#include "Modal4.h"
|
||||
|
||||
Modal4 :: Modal4()
|
||||
{
|
||||
envelope = new Envelope;
|
||||
/* We don't make the excitation wave here yet, */
|
||||
/* because we don't know what it's going to be. */
|
||||
filters[0] = new BiQuad;
|
||||
filters[1] = new BiQuad;
|
||||
filters[2] = new BiQuad;
|
||||
filters[3] = new BiQuad;
|
||||
onepole = new OnePole;
|
||||
|
||||
vibr = new RawLoop("rawwaves/sinewave.raw");
|
||||
vibr->normalize();
|
||||
vibr->setFreq((MY_FLOAT) 6.0);
|
||||
vibrGain = (MY_FLOAT) 0.05;
|
||||
|
||||
directGain = (MY_FLOAT) 0.0;
|
||||
masterGain = (MY_FLOAT) 1.0;
|
||||
baseFreq = (MY_FLOAT) 440.0;
|
||||
this->setRatioAndReson(0,(MY_FLOAT) 1.00,(MY_FLOAT) 0.9997); /* Set some */
|
||||
this->setRatioAndReson(1,(MY_FLOAT) 1.30,(MY_FLOAT) 0.9997); /* silly */
|
||||
this->setRatioAndReson(2,(MY_FLOAT) 1.77,(MY_FLOAT) 0.9997); /* default */
|
||||
this->setRatioAndReson(3,(MY_FLOAT) 2.37,(MY_FLOAT) 0.9997); /* values here */
|
||||
this->setFiltGain(0,(MY_FLOAT) 0.01);
|
||||
this->setFiltGain(1,(MY_FLOAT) 0.01);
|
||||
this->setFiltGain(2,(MY_FLOAT) 0.01);
|
||||
this->setFiltGain(3,(MY_FLOAT) 0.01);
|
||||
this->clear();
|
||||
filters[0]->setEqualGainZeroes();
|
||||
filters[1]->setEqualGainZeroes();
|
||||
filters[2]->setEqualGainZeroes();
|
||||
filters[3]->setEqualGainZeroes();
|
||||
stickHardness = (MY_FLOAT) 0.5;
|
||||
strikePosition = (MY_FLOAT) 0.561;
|
||||
}
|
||||
|
||||
Modal4 :: ~Modal4()
|
||||
{
|
||||
delete envelope;
|
||||
delete filters[0];
|
||||
delete filters[1];
|
||||
delete filters[2];
|
||||
delete filters[3];
|
||||
delete onepole;
|
||||
delete vibr;
|
||||
}
|
||||
|
||||
void Modal4 :: clear()
|
||||
{
|
||||
onepole->clear();
|
||||
filters[0]->clear();
|
||||
filters[1]->clear();
|
||||
filters[2]->clear();
|
||||
filters[3]->clear();
|
||||
}
|
||||
|
||||
void Modal4 :: setFreq(MY_FLOAT frequency)
|
||||
{
|
||||
baseFreq = frequency;
|
||||
this->setRatioAndReson(0,ratios[0],resons[0]);
|
||||
this->setRatioAndReson(1,ratios[1],resons[1]);
|
||||
this->setRatioAndReson(2,ratios[2],resons[2]);
|
||||
this->setRatioAndReson(3,ratios[3],resons[3]);
|
||||
}
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
void Modal4 :: setRatioAndReson(int whichOne, MY_FLOAT ratio,MY_FLOAT reson)
|
||||
{
|
||||
MY_FLOAT temp;
|
||||
if (ratio*baseFreq < SRATE_OVER_TWO) {
|
||||
ratios[whichOne] = ratio;
|
||||
}
|
||||
else {
|
||||
temp = ratio;
|
||||
while (temp*baseFreq > SRATE_OVER_TWO) temp *= (MY_FLOAT) 0.5;
|
||||
ratios[whichOne] = temp;
|
||||
#if defined(_debug_)
|
||||
printf("Modal4 : Aliasing would occur here, correcting.\n");
|
||||
#endif
|
||||
}
|
||||
resons[whichOne] = reson;
|
||||
if (ratio<0)
|
||||
temp = -ratio;
|
||||
else
|
||||
temp = ratio*baseFreq;
|
||||
filters[whichOne]->setFreqAndReson(temp,reson);
|
||||
}
|
||||
|
||||
void Modal4 :: setMasterGain(MY_FLOAT aGain)
|
||||
{
|
||||
masterGain = aGain;
|
||||
}
|
||||
|
||||
void Modal4 :: setDirectGain(MY_FLOAT aGain)
|
||||
{
|
||||
directGain = aGain;
|
||||
}
|
||||
|
||||
void Modal4 :: setFiltGain(int whichOne, MY_FLOAT gain)
|
||||
{
|
||||
filters[whichOne]->setGain(gain);
|
||||
}
|
||||
|
||||
void Modal4 :: strike(MY_FLOAT amplitude)
|
||||
{
|
||||
int i;
|
||||
MY_FLOAT temp;
|
||||
envelope->setRate((MY_FLOAT) 1.0);
|
||||
envelope->setTarget(amplitude);
|
||||
onepole->setPole((MY_FLOAT) 1.0 - amplitude);
|
||||
envelope->tick();
|
||||
wave->reset();
|
||||
for (i=0;i<4;i++) {
|
||||
if (ratios[i] < 0)
|
||||
temp = -ratios[i];
|
||||
else
|
||||
temp = ratios[i] * baseFreq;
|
||||
filters[i]->setFreqAndReson(temp,resons[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void Modal4 :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
||||
{
|
||||
this->strike(amp);
|
||||
this->setFreq(freq);
|
||||
#if defined(_debug_)
|
||||
printf("Modal4 : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Modal4 :: noteOff(MY_FLOAT amp) /* This calls damp, but inverts the */
|
||||
{ /* meaning of amplitude. */
|
||||
this->damp((MY_FLOAT) 1.0 - (amp * (MY_FLOAT) 0.03)); /* (high amplitude means fast damping) */
|
||||
#if defined(_debug_)
|
||||
printf("Modal4 : NoteOff: Amp=%lf\n",amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Modal4 :: damp(MY_FLOAT amplitude)
|
||||
{
|
||||
int i;
|
||||
MY_FLOAT temp;
|
||||
for (i=0;i<4;i++) {
|
||||
if (ratios[i] < 0)
|
||||
temp = -ratios[i];
|
||||
else
|
||||
temp = ratios[i] * baseFreq;
|
||||
filters[i]->setFreqAndReson(temp,resons[i]*amplitude);
|
||||
}
|
||||
}
|
||||
|
||||
void Modal4 :: controlChange(int number, MY_FLOAT value)
|
||||
{
|
||||
}
|
||||
|
||||
MY_FLOAT Modal4 :: tick()
|
||||
{
|
||||
MY_FLOAT temp,temp2;
|
||||
temp = masterGain * onepole->tick(wave->tick() * envelope->tick());
|
||||
temp2 = filters[0]->tick(temp);
|
||||
temp2 += filters[1]->tick(temp);
|
||||
temp2 += filters[2]->tick(temp);
|
||||
temp2 += filters[3]->tick(temp);
|
||||
temp2 = temp2 - (temp2 * directGain);
|
||||
temp2 += directGain * temp;
|
||||
|
||||
if (vibrGain != 0.0) {
|
||||
temp = (MY_FLOAT) 1.0 + (vibr->tick() * vibrGain); /* Calculate AM */
|
||||
temp2 = temp * temp2; /* and apply to master out */
|
||||
}
|
||||
|
||||
lastOutput = temp2 * (MY_FLOAT) 2.0;
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
52
Modal4.h
52
Modal4.h
@@ -1,52 +0,0 @@
|
||||
/*******************************************/
|
||||
/* 4 Resonance Modal Synthesis Instrument */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* This instrument contains an excitation */
|
||||
/* wavetable, an envelope, and four reso- */
|
||||
/* nances (Non-Sweeping BiQuad Filters). */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__Modal4_h)
|
||||
#define __Modal4_h
|
||||
|
||||
#include "Instrmnt.h"
|
||||
#include "Envelope.h"
|
||||
#include "RawInterp.h"
|
||||
#include "RawLoop.h"
|
||||
#include "BiQuad.h"
|
||||
#include "OnePole.h"
|
||||
|
||||
class Modal4 : public Instrmnt
|
||||
{
|
||||
protected:
|
||||
Envelope *envelope;
|
||||
RawInterp *wave;
|
||||
BiQuad *filters[4];
|
||||
OnePole *onepole;
|
||||
RawLoop *vibr;
|
||||
MY_FLOAT vibrGain;
|
||||
MY_FLOAT masterGain;
|
||||
MY_FLOAT directGain;
|
||||
MY_FLOAT stickHardness;
|
||||
MY_FLOAT strikePosition;
|
||||
MY_FLOAT baseFreq;
|
||||
MY_FLOAT ratios[4];
|
||||
MY_FLOAT resons[4];
|
||||
public:
|
||||
Modal4();
|
||||
virtual ~Modal4();
|
||||
void clear();
|
||||
virtual void setFreq(MY_FLOAT frequency);
|
||||
void setRatioAndReson(int whichOne, MY_FLOAT ratio, MY_FLOAT reson);
|
||||
void setMasterGain(MY_FLOAT aGain);
|
||||
void setDirectGain(MY_FLOAT aGain);
|
||||
void setFiltGain(int whichOne, MY_FLOAT gain);
|
||||
virtual void strike(MY_FLOAT amplitude);
|
||||
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
|
||||
virtual void noteOff(MY_FLOAT amp);
|
||||
void damp(MY_FLOAT amplitude);
|
||||
virtual void controlChange(int number, MY_FLOAT value);
|
||||
virtual MY_FLOAT tick();
|
||||
};
|
||||
|
||||
#endif
|
||||
83
Modulatr.cpp
83
Modulatr.cpp
@@ -1,83 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Modulator Class, Perry R. Cook, 1995-96*/
|
||||
/* This Object combines random and */
|
||||
/* periodic modulations to give a nice */
|
||||
/* natural human modulation function. */
|
||||
/*******************************************/
|
||||
|
||||
#define POLE_POS (MY_FLOAT) 0.999
|
||||
#define RND_SCALE (MY_FLOAT) 10.0
|
||||
|
||||
#include "Modulatr.h"
|
||||
|
||||
Modulatr :: Modulatr()
|
||||
{
|
||||
vibwave = new RawLoop("rawwaves/sinewave.raw");
|
||||
vibwave->normalize();
|
||||
vibwave->setFreq((MY_FLOAT) 6.0);
|
||||
vibAmt = (MY_FLOAT) 0.04;
|
||||
noise = new SubNoise(330);
|
||||
rndAmt = (MY_FLOAT) 0.005;
|
||||
onepole = new OnePole;
|
||||
onepole->setPole(POLE_POS);
|
||||
onepole->setGain(rndAmt * RND_SCALE);
|
||||
}
|
||||
|
||||
Modulatr :: ~Modulatr()
|
||||
{
|
||||
delete vibwave;
|
||||
delete noise;
|
||||
delete onepole;
|
||||
}
|
||||
|
||||
void Modulatr :: reset()
|
||||
{
|
||||
lastOutput = (MY_FLOAT) 0.0;
|
||||
}
|
||||
|
||||
void Modulatr :: setVibFreq(MY_FLOAT vibFreq)
|
||||
{
|
||||
vibwave->setFreq(vibFreq);
|
||||
}
|
||||
|
||||
void Modulatr :: setVibAmt(MY_FLOAT vibAmount)
|
||||
{
|
||||
vibAmt = vibAmount;
|
||||
}
|
||||
|
||||
void Modulatr :: setRndAmt(MY_FLOAT rndAmount)
|
||||
{
|
||||
rndAmt = rndAmount;
|
||||
onepole->setGain(RND_SCALE * rndAmt);
|
||||
}
|
||||
|
||||
MY_FLOAT Modulatr :: tick()
|
||||
{
|
||||
lastOutput = vibAmt * vibwave->tick(); /* Compute periodic and */
|
||||
lastOutput += onepole->tick(noise->tick()); /* random modulations */
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
MY_FLOAT Modulatr :: lastOut()
|
||||
{
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
/************ Test Main Program *****************/
|
||||
/*
|
||||
void main()
|
||||
{
|
||||
Modulatr testMod;
|
||||
FILE *fd;
|
||||
short data;
|
||||
long i;
|
||||
|
||||
fd = fopen("test.raw","wb");
|
||||
|
||||
for (i=0;i<20000;i++) {
|
||||
data = testMod.tick() * 32000.0;
|
||||
fwrite(&data,2,1,fd);
|
||||
}
|
||||
fclose(fd);
|
||||
}
|
||||
*/
|
||||
36
Modulatr.h
36
Modulatr.h
@@ -1,36 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Modulator Class, Perry R. Cook, 1995-96*/
|
||||
/* This Object combines random and */
|
||||
/* periodic modulations to give a nice */
|
||||
/* natural human modulation function. */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__Modulatr_h)
|
||||
#define __Modulatr_h
|
||||
|
||||
#include "Object.h"
|
||||
#include "RawLoop.h"
|
||||
#include "SubNoise.h"
|
||||
#include "OnePole.h"
|
||||
|
||||
class Modulatr : public Object
|
||||
{
|
||||
protected:
|
||||
RawLoop *vibwave;
|
||||
SubNoise *noise;
|
||||
OnePole *onepole;
|
||||
MY_FLOAT vibAmt;
|
||||
MY_FLOAT rndAmt;
|
||||
MY_FLOAT lastOutput;
|
||||
public:
|
||||
Modulatr();
|
||||
~Modulatr();
|
||||
void reset();
|
||||
void setVibFreq(MY_FLOAT vibFreq);
|
||||
void setVibAmt(MY_FLOAT vibAmount);
|
||||
void setRndAmt(MY_FLOAT rndAmount);
|
||||
MY_FLOAT tick();
|
||||
MY_FLOAT lastOut();
|
||||
};
|
||||
|
||||
#endif
|
||||
107
Moog1.cpp
107
Moog1.cpp
@@ -1,107 +0,0 @@
|
||||
/******************************************/
|
||||
/* Test Sampler Subclass of */
|
||||
/* Sampling Synthesizer Class */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* */
|
||||
/* Controls: CONTROL1 = filterQ */
|
||||
/* CONTROL2 = filterRate */
|
||||
/* CONTROL3 = vibFreq */
|
||||
/* MOD_WHEEL= vibAmt */
|
||||
/******************************************/
|
||||
|
||||
#include "Moog1.h"
|
||||
#include "SKINI11.msg"
|
||||
|
||||
Moog1 :: Moog1() : SamplFlt()
|
||||
{
|
||||
attacks[0] = new RawInterp("rawwaves/mandpluk.raw");
|
||||
loops[0] = new RawLoop("rawwaves/impuls20.raw");
|
||||
loops[1] = new RawLoop("rawwaves/sinewave.raw"); /* Steal one for vibrato */
|
||||
attacks[0]->normalize();
|
||||
loops[0]->normalize();
|
||||
loops[1]->normalize();
|
||||
loops[1]->setFreq((MY_FLOAT) 6.122);
|
||||
adsr->setAllTimes((MY_FLOAT) 0.001,(MY_FLOAT) 1.5,(MY_FLOAT) 0.6,(MY_FLOAT) 0.250);
|
||||
filterQ = (MY_FLOAT) 0.85;
|
||||
filterRate = (MY_FLOAT) 0.0001;
|
||||
modDepth = (MY_FLOAT) 0.0;
|
||||
}
|
||||
|
||||
Moog1 :: ~Moog1()
|
||||
{
|
||||
delete attacks[0];
|
||||
delete loops[0];
|
||||
delete loops[1];
|
||||
}
|
||||
|
||||
void Moog1 :: setFreq(MY_FLOAT frequency)
|
||||
{
|
||||
baseFreq = frequency;
|
||||
attacks[0]->setFreq(baseFreq * (MY_FLOAT) 0.01);
|
||||
loops[0]->setFreq(baseFreq);
|
||||
}
|
||||
|
||||
void Moog1 :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
||||
{
|
||||
MY_FLOAT temp;
|
||||
|
||||
this->setFreq(freq);
|
||||
this->keyOn();
|
||||
attackGain = amp * (MY_FLOAT) 0.5;
|
||||
loopGain = amp;
|
||||
|
||||
temp = filterQ + (MY_FLOAT) 0.05;
|
||||
filters[0]->setStates((MY_FLOAT) 2000.0,temp,(MY_FLOAT) 2.0 * ((MY_FLOAT) 1.0 - temp));
|
||||
filters[1]->setStates((MY_FLOAT) 2000.0,temp,(MY_FLOAT) 2.0 * ((MY_FLOAT) 1.0 - temp));
|
||||
temp = filterQ + (MY_FLOAT) 0.099;
|
||||
filters[0]->setTargets((MY_FLOAT) freq,temp,(MY_FLOAT) 2.0 * ((MY_FLOAT) 1.0 - temp));
|
||||
filters[1]->setTargets((MY_FLOAT) freq,temp,(MY_FLOAT) 2.0 * ((MY_FLOAT) 1.0 - temp));
|
||||
filters[0]->setSweepRate(filterRate * (MY_FLOAT) 22050.0 / SRATE);
|
||||
filters[1]->setSweepRate(filterRate * (MY_FLOAT) 22050.0 / SRATE);
|
||||
#if defined(_debug_)
|
||||
printf("Moog1 : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Moog1 :: setModulationSpeed(MY_FLOAT mSpeed)
|
||||
{
|
||||
loops[1]->setFreq(mSpeed);
|
||||
}
|
||||
|
||||
void Moog1 :: setModulationDepth(MY_FLOAT mDepth)
|
||||
{
|
||||
modDepth = mDepth * (MY_FLOAT) 0.5;
|
||||
}
|
||||
|
||||
void Moog1 :: controlChange(int number, MY_FLOAT value)
|
||||
{
|
||||
#if defined(_debug_)
|
||||
printf("Moog1 : ControlChange: Number=%i Value=%f\n",number,value);
|
||||
#endif
|
||||
if (number == __SK_FilterQ_)
|
||||
filterQ = (MY_FLOAT) 0.80 + ((MY_FLOAT) 0.1 * value * NORM_7);
|
||||
else if (number == __SK_FilterSweepRate_)
|
||||
filterRate = (value * NORM_7 * (MY_FLOAT) 0.0002);
|
||||
else if (number == __SK_ModFrequency_)
|
||||
this->setModulationSpeed(value * NORM_7 * (MY_FLOAT) 12.0);
|
||||
else if (number == __SK_ModWheel_)
|
||||
this->setModulationDepth(value * NORM_7);
|
||||
else if (number == __SK_AfterTouch_Cont_)
|
||||
adsr->setTarget(value * NORM_7);
|
||||
else {
|
||||
printf("Moog1 : Undefined Control Number!!\n");
|
||||
}
|
||||
}
|
||||
|
||||
MY_FLOAT Moog1 :: tick()
|
||||
{
|
||||
MY_FLOAT temp;
|
||||
|
||||
if (modDepth!=0.0) {
|
||||
temp = loops[1]->tick() * modDepth;
|
||||
loops[0]->setFreq(baseFreq * ((MY_FLOAT) 1.0 + temp));
|
||||
}
|
||||
lastOutput = SamplFlt :: tick();
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
34
Moog1.h
34
Moog1.h
@@ -1,34 +0,0 @@
|
||||
/******************************************/
|
||||
/* Moog1 Subclass of */
|
||||
/* Sampling Synthesizer Class */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* */
|
||||
/* Controls: CONTROL1 = filterQ */
|
||||
/* CONTROL2 = filterRate */
|
||||
/* CONTROL3 = vibFreq */
|
||||
/* MOD_WHEEL= vibAmt */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__Moog1_h)
|
||||
#define __Moog1_h
|
||||
|
||||
#include "SamplFlt.h"
|
||||
|
||||
class Moog1 : public SamplFlt
|
||||
{
|
||||
private:
|
||||
MY_FLOAT modDepth;
|
||||
MY_FLOAT filterQ;
|
||||
MY_FLOAT filterRate;
|
||||
public:
|
||||
Moog1();
|
||||
~Moog1();
|
||||
virtual void setFreq(MY_FLOAT frequency);
|
||||
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
|
||||
void setModulationSpeed(MY_FLOAT mSpeed);
|
||||
void setModulationDepth(MY_FLOAT mDepth);
|
||||
virtual void controlChange(int number, MY_FLOAT value);
|
||||
virtual MY_FLOAT tick();
|
||||
};
|
||||
|
||||
#endif
|
||||
138
NRev.cpp
138
NRev.cpp
@@ -1,138 +0,0 @@
|
||||
/******************************************/
|
||||
/* NRev Reverb Subclass */
|
||||
/* by Tim Stilson, 1998 */
|
||||
/* based on CLM NRev */
|
||||
/* Integrated into STK by Gary Scavone */
|
||||
/* */
|
||||
/* This is based on some of the famous */
|
||||
/* Stanford CCRMA reverbs (NRev, KipRev) */
|
||||
/* all based on the the Chowning/Moorer/ */
|
||||
/* Schroeder reverberators, which use */
|
||||
/* networks of simple allpass and comb */
|
||||
/* delay filters. This particular */
|
||||
/* arrangement consists of 6 comb */
|
||||
/* filters in parallel, followed by 3 */
|
||||
/* allpass filters, a lowpass filter, */
|
||||
/* and another allpass in series, */
|
||||
/* followed by two allpass filters in */
|
||||
/* parallel with corresponding right and */
|
||||
/* left outputs. */
|
||||
/******************************************/
|
||||
|
||||
#include "NRev.h"
|
||||
|
||||
NRev :: NRev(MY_FLOAT T60)
|
||||
{
|
||||
int lens[15]={1433,1601,1867,2053,2251,2399,347,113,37,59,53,43,37,29,19};
|
||||
double srscale= SRATE / 25641.0;
|
||||
int val;
|
||||
int i;
|
||||
|
||||
for (i=0; i<15; i++)
|
||||
{
|
||||
val = (int)floor(srscale*lens[i]);
|
||||
if ((val & 1) == 0) val++;
|
||||
while (!this->isprime(val)) val+=2;
|
||||
lens[i]=val;
|
||||
}
|
||||
for (i=0; i<6; i++)
|
||||
{
|
||||
CdelayLine[i] = new DLineN((long) (lens[i]) + 2);
|
||||
CdelayLine[i]->setDelay((long) (lens[i]));
|
||||
combCoef[i] = pow(10,(-3 * lens[i] / (T60 * SRATE)));
|
||||
}
|
||||
for (i=0; i<8; i++)
|
||||
{
|
||||
APdelayLine[i] = new DLineN((long) (lens[i+6]) + 2);
|
||||
APdelayLine[i]->setDelay((long) (lens[i+6]));
|
||||
}
|
||||
|
||||
allPassCoeff = 0.7;
|
||||
effectMix = 0.3;
|
||||
this->clear();
|
||||
}
|
||||
|
||||
NRev :: ~NRev()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<6; i++) delete CdelayLine[i];
|
||||
for (i=0; i<8; i++) delete APdelayLine[i];
|
||||
}
|
||||
|
||||
void NRev :: clear()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<6; i++) CdelayLine[i]->clear();
|
||||
for (i=0; i<8; i++) APdelayLine[i]->clear();
|
||||
lastOutL = 0.0;
|
||||
lastOutR = 0.0;
|
||||
lpLastout = 0.0;
|
||||
}
|
||||
|
||||
void NRev :: setEffectMix(MY_FLOAT mix)
|
||||
{
|
||||
effectMix = mix;
|
||||
}
|
||||
|
||||
MY_FLOAT NRev :: lastOutput()
|
||||
{
|
||||
return (lastOutL + lastOutR) * 0.5;
|
||||
}
|
||||
|
||||
MY_FLOAT NRev :: lastOutputL()
|
||||
{
|
||||
return lastOutL;
|
||||
}
|
||||
|
||||
MY_FLOAT NRev :: lastOutputR()
|
||||
{
|
||||
return lastOutR;
|
||||
}
|
||||
|
||||
MY_FLOAT NRev :: tick(MY_FLOAT input)
|
||||
{
|
||||
MY_FLOAT temp,temp0,temp1,temp2,temp3;
|
||||
int i;
|
||||
|
||||
temp0 = 0.0;
|
||||
for (i=0; i<6; i++)
|
||||
{
|
||||
temp = input + (combCoef[i] * CdelayLine[i]->lastOut());
|
||||
temp0 += CdelayLine[i]->tick(temp);
|
||||
}
|
||||
for (i=0; i<3; i++)
|
||||
{
|
||||
temp = APdelayLine[i]->lastOut();
|
||||
temp1 = allPassCoeff * temp;
|
||||
temp1 += temp0;
|
||||
APdelayLine[i]->tick(temp1);
|
||||
temp0 = -(allPassCoeff * temp1) + temp;
|
||||
}
|
||||
lpLastout = 0.7*lpLastout + 0.3*temp0; // onepole LP filter
|
||||
temp = APdelayLine[3]->lastOut();
|
||||
temp1 = allPassCoeff * temp;
|
||||
temp1 += lpLastout;
|
||||
APdelayLine[3]->tick(temp1);
|
||||
temp1 = -(allPassCoeff * temp1) + temp;
|
||||
|
||||
temp = APdelayLine[4]->lastOut();
|
||||
temp2 = allPassCoeff * temp;
|
||||
temp2 += temp1;
|
||||
APdelayLine[4]->tick(temp2);
|
||||
lastOutL = effectMix*(-(allPassCoeff * temp2) + temp);
|
||||
|
||||
temp = APdelayLine[5]->lastOut();
|
||||
temp3 = allPassCoeff * temp;
|
||||
temp3 += temp1;
|
||||
APdelayLine[5]->tick(temp3);
|
||||
lastOutR = effectMix*(-(allPassCoeff * temp3) + temp);
|
||||
|
||||
temp = (1.0 - effectMix) * input;
|
||||
lastOutL += temp;
|
||||
lastOutR += temp;
|
||||
|
||||
return (lastOutL + lastOutR) * 0.5;
|
||||
|
||||
}
|
||||
52
NRev.h
52
NRev.h
@@ -1,52 +0,0 @@
|
||||
/******************************************/
|
||||
/* NRev Reverb Subclass */
|
||||
/* by Tim Stilson, 1998 */
|
||||
/* based on CLM NRev */
|
||||
/* Integrated into STK by Gary Scavone */
|
||||
/* */
|
||||
/* This is based on some of the famous */
|
||||
/* Stanford CCRMA reverbs (NRev, KipRev) */
|
||||
/* all based on the the Chowning/Moorer/ */
|
||||
/* Schroeder reverberators, which use */
|
||||
/* networks of simple allpass and comb */
|
||||
/* delay filters. This particular */
|
||||
/* arrangement consists of 6 comb */
|
||||
/* filters in parallel, followed by 3 */
|
||||
/* allpass filters, a lowpass filter, */
|
||||
/* and another allpass in series, */
|
||||
/* followed by two allpass filters in */
|
||||
/* parallel with corresponding right and */
|
||||
/* left outputs. */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__NRev_h)
|
||||
#define __NRev_h
|
||||
|
||||
#include "Object.h"
|
||||
#include "Reverb.h"
|
||||
#include "DLineN.h"
|
||||
|
||||
class NRev : public Reverb
|
||||
{
|
||||
protected:
|
||||
DLineN *APdelayLine[8];
|
||||
DLineN *CdelayLine[6];
|
||||
MY_FLOAT allPassCoeff;
|
||||
MY_FLOAT combCoef[6];
|
||||
MY_FLOAT lpLastout;
|
||||
MY_FLOAT lastOutL;
|
||||
MY_FLOAT lastOutR;
|
||||
MY_FLOAT effectMix;
|
||||
public:
|
||||
NRev(MY_FLOAT T60);
|
||||
~NRev();
|
||||
void clear();
|
||||
void setEffectMix(MY_FLOAT mix);
|
||||
MY_FLOAT lastOutput();
|
||||
MY_FLOAT lastOutputL();
|
||||
MY_FLOAT lastOutputR();
|
||||
MY_FLOAT tick(MY_FLOAT input);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
53
Noise.cpp
53
Noise.cpp
@@ -1,53 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Noise Generator Class, */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* White noise as often as you like. */
|
||||
/*******************************************/
|
||||
|
||||
#include "Noise.h"
|
||||
#ifdef __NeXT_
|
||||
#include <libc.h>
|
||||
#endif
|
||||
|
||||
#if defined(__OS_Win_) /* For Windows95 or NT */
|
||||
#define ONE_OVER_RANDLIMIT 0.00006103516
|
||||
#else /* This is for Linux, NeXT and SGI */
|
||||
#define ONE_OVER_RANDLIMIT 0.00000000093132258
|
||||
#endif
|
||||
|
||||
Noise :: Noise() : Object()
|
||||
{
|
||||
lastOutput = (MY_FLOAT) 0.0;
|
||||
}
|
||||
|
||||
Noise :: ~Noise()
|
||||
{
|
||||
}
|
||||
|
||||
MY_FLOAT Noise :: tick()
|
||||
{
|
||||
/* THIS ONE IS WIN95 */
|
||||
#if defined(__OS_Win_) /* For Windows95 or NT */
|
||||
lastOutput = (MY_FLOAT) (rand() - 16383);
|
||||
#else /* This is for Linux, NeXT and SGI */
|
||||
lastOutput = (MY_FLOAT) random() - 1073741823.0;
|
||||
#endif
|
||||
|
||||
lastOutput *= (MY_FLOAT) ONE_OVER_RANDLIMIT;
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
MY_FLOAT Noise :: lastOut()
|
||||
{
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
/************ Test Main ************************/
|
||||
/*
|
||||
void main()
|
||||
{
|
||||
long i;
|
||||
Noise test;
|
||||
for (i=0;i<20;i++) printf("%lf\n",test.tick());
|
||||
}
|
||||
*/
|
||||
23
Noise.h
23
Noise.h
@@ -1,23 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Noise Generator Class, */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* White noise as often as you like. */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__Noise_h)
|
||||
#define __Noise_h
|
||||
|
||||
#include "Object.h"
|
||||
|
||||
class Noise : public Object
|
||||
{
|
||||
protected:
|
||||
MY_FLOAT lastOutput;
|
||||
public:
|
||||
Noise();
|
||||
virtual ~Noise();
|
||||
MY_FLOAT tick();
|
||||
MY_FLOAT lastOut();
|
||||
};
|
||||
|
||||
#endif
|
||||
23
Object.cpp
23
Object.cpp
@@ -1,23 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Object Class, by Perry R. Cook, 1995-96*/
|
||||
/* This is mostly here for compatibility */
|
||||
/* with Objective C. We'll also stick */
|
||||
/* global defines here, so everyone will */
|
||||
/* see them. */
|
||||
/*******************************************/
|
||||
|
||||
#include "Object.h"
|
||||
// #include "byteswap.c"
|
||||
|
||||
/* This is just here for compatibility and convenience,
|
||||
so there's no need to do any real calculations.
|
||||
I do set up some redefinable variables here. */
|
||||
|
||||
Object :: Object()
|
||||
{
|
||||
}
|
||||
|
||||
Object :: ~Object()
|
||||
{
|
||||
}
|
||||
|
||||
134
Object.h
134
Object.h
@@ -1,134 +0,0 @@
|
||||
/*********************************************/
|
||||
/* Object Class, by Perry R. Cook, 1995-96 */
|
||||
/* This is mostly here for compatibility */
|
||||
/* with Objective C. We'll also stick */
|
||||
/* global defines here, so everyone will */
|
||||
/* see them. */
|
||||
/*********************************************/
|
||||
|
||||
#if !defined(__Object_h)
|
||||
#define __Object_h
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
class Object
|
||||
{
|
||||
public:
|
||||
protected:
|
||||
Object();
|
||||
virtual ~Object();
|
||||
};
|
||||
|
||||
/* Uncomment your OS type below! */
|
||||
|
||||
/* #define __OS_NeXT_ */
|
||||
#define __OS_IRIX_
|
||||
/* #define __OS_Linux_ */
|
||||
/* #define __OS_Win_ */
|
||||
|
||||
#if defined(__OS_NeXT_) /* For NeXTStep - Black or White Hardware */
|
||||
#define __NeXT_
|
||||
#elif defined(__OS_IRIX_) /* For SGI */
|
||||
#define __SGI_REALTIME_
|
||||
typedef int bool;
|
||||
#elif defined(__OS_Linux_) /* For Linux */
|
||||
#define __USS_REALTIME_
|
||||
#define __LITTLE_ENDIAN__
|
||||
#elif defined(__OS_Win_) /* For Windows95 or NT */
|
||||
#define __WINDS_REALTIME_ /* For Direct Sound API */
|
||||
/* #define __WINMM_REALTIME_ */ /* For Win MM API */
|
||||
#define __SOCKET
|
||||
#define __LITTLE_ENDIAN__
|
||||
#endif
|
||||
|
||||
/* Real-time output buffer size. If clicks are occuring in the
|
||||
* output sound stream, a larger buffer size may help. Larger
|
||||
* buffer sizes, however, produce more latency between input and
|
||||
* output.
|
||||
*/
|
||||
#define RT_BUFFER_SIZE 256
|
||||
|
||||
/* This sets the maximum number of simultaneous
|
||||
* (within a buffer) MIDI messages that can be
|
||||
* serviced before messages begin to be lost or
|
||||
* overwritten. It should be a function of
|
||||
* RT_BUFFER_SIZE
|
||||
*/
|
||||
#define MAX_IN_STRINGS 25
|
||||
|
||||
/* SRATE here is 44100, others are derived accordingly */
|
||||
/*
|
||||
#define SRATE (MY_FLOAT) 44100.0
|
||||
#define SRATE_OVER_TWO (MY_FLOAT) 22050.0
|
||||
#define ONE_OVER_SRATE (MY_FLOAT) 0.00002267573696
|
||||
#define RATE_NORM (MY_FLOAT) 0.5
|
||||
#define TWO_PI_OVER_SRATE (MY_FLOAT) 0.0001424758573
|
||||
*/
|
||||
/* SRATE here is 22050, others are derived accordingly */
|
||||
|
||||
#define SRATE (MY_FLOAT) 22050.0
|
||||
#define SRATE_OVER_TWO (MY_FLOAT) 11025.0
|
||||
#define ONE_OVER_SRATE (MY_FLOAT) 0.00004535147392
|
||||
#define RATE_NORM (MY_FLOAT) 1.0
|
||||
#define TWO_PI_OVER_SRATE (MY_FLOAT) 0.0002849517146
|
||||
|
||||
/* SRATE here is 16000, others are derived accordingly */
|
||||
/*
|
||||
#define SRATE (MY_FLOAT) 16000.0
|
||||
#define SRATE_OVER_TWO (MY_FLOAT) 8000.0
|
||||
#define ONE_OVER_SRATE (MY_FLOAT) 0.0000625
|
||||
#define RATE_NORM (MY_FLOAT) 1.375
|
||||
#define TWO_PI_OVER_SRATE (MY_FLOAT) 0.000392699
|
||||
*/
|
||||
/* SRATE here is 8k, others are derived accordingly */
|
||||
/*
|
||||
#define SRATE (MY_FLOAT) 8000.0
|
||||
#define SRATE_OVER_TWO (MY_FLOAT) 4000
|
||||
#define ONE_OVER_SRATE (MY_FLOAT) 0.00012500000000
|
||||
#define RATE_NORM (MY_FLOAT) 2.75625
|
||||
#define TWO_PI_OVER_SRATE (MY_FLOAT) 0.0002849517146
|
||||
*/
|
||||
|
||||
/* Yer Basic Trigonometric constants */
|
||||
#if !defined(PI)
|
||||
#define PI (MY_FLOAT) 3.14159265359
|
||||
#endif
|
||||
#define TWO_PI (MY_FLOAT) 6.28318530718
|
||||
#define ONE_OVER_TWO_PI (MY_FLOAT) 0.15915494309
|
||||
#define SQRT_TWO 1.414213562
|
||||
|
||||
/* States for Envelopes, etc. */
|
||||
|
||||
#define ATTACK 0
|
||||
#define DECAY 1
|
||||
#define SUSTAIN 2
|
||||
#define RELEASE 3
|
||||
|
||||
/* Machine dependent stuff, possibly useful for optimization.
|
||||
* For example, changing double to float here increasesf
|
||||
* performance (speed) by a whopping 4-6% on 486-flavor machines.
|
||||
* BUT!! a change from float to double here increases speed by
|
||||
* 30% or so on SGI machines.
|
||||
*/
|
||||
|
||||
#define MY_FLOAT double
|
||||
#define MY_FLOAT_SIZE 8
|
||||
|
||||
/*
|
||||
#define MY_FLOAT float
|
||||
#define MY_FLOAT_SIZE 4
|
||||
*/
|
||||
|
||||
/* Debugging define, causes massive printf's to come out.
|
||||
* Also enables timing calculations in WaveOut class, other stuff.
|
||||
*/
|
||||
|
||||
/* #define _debug_ 1 */
|
||||
|
||||
/* MIDI definitions */
|
||||
#define NORM_7 (MY_FLOAT) 0.0078125 /* this is 1/128 */
|
||||
|
||||
#endif
|
||||
81
OnePole.cpp
81
OnePole.cpp
@@ -1,81 +0,0 @@
|
||||
/*******************************************/
|
||||
/* One Pole Filter Class, */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* The parameter gain is an additional */
|
||||
/* gain parameter applied to the filter */
|
||||
/* on top of the normalization that takes */
|
||||
/* place automatically. So the net max */
|
||||
/* gain through the system equals the */
|
||||
/* value of gain. sgain is the combina- */
|
||||
/* tion of gain and the normalization */
|
||||
/* parameter, so if you set the poleCoeff */
|
||||
/* to alpha, sgain is always set to */
|
||||
/* gain * (1.0 - fabs(alpha)). */
|
||||
/*******************************************/
|
||||
|
||||
#include "OnePole.h"
|
||||
|
||||
OnePole :: OnePole() : Filter()
|
||||
{
|
||||
poleCoeff = (MY_FLOAT) 0.9;
|
||||
gain = (MY_FLOAT) 1.0;
|
||||
sgain = (MY_FLOAT) 0.1;
|
||||
outputs = (MY_FLOAT *) malloc(MY_FLOAT_SIZE);
|
||||
outputs[0] = (MY_FLOAT) 0.0;
|
||||
}
|
||||
|
||||
OnePole :: ~OnePole()
|
||||
{
|
||||
free(outputs);
|
||||
}
|
||||
|
||||
void OnePole :: clear()
|
||||
{
|
||||
outputs[0] = (MY_FLOAT) 0.0;
|
||||
lastOutput = (MY_FLOAT) 0.0;
|
||||
}
|
||||
|
||||
void OnePole :: setPole(MY_FLOAT aValue)
|
||||
{
|
||||
poleCoeff = aValue;
|
||||
if (poleCoeff > 0.0) /* Normalize gain to 1.0 max */
|
||||
sgain = gain * ((MY_FLOAT) 1.0 - poleCoeff);
|
||||
else
|
||||
sgain = gain * ((MY_FLOAT) 1.0 + poleCoeff);
|
||||
}
|
||||
|
||||
void OnePole :: setGain(MY_FLOAT aValue)
|
||||
{
|
||||
gain = aValue;
|
||||
if (poleCoeff > 0.0)
|
||||
sgain = gain * ((MY_FLOAT) 1.0 - poleCoeff); /* Normalize gain to 1.0 max */
|
||||
else
|
||||
sgain = gain * ((MY_FLOAT) 1.0 + poleCoeff);
|
||||
}
|
||||
|
||||
MY_FLOAT OnePole :: tick(MY_FLOAT sample) /* Perform Filter Operation */
|
||||
{
|
||||
outputs[0] = (sgain * sample) + (poleCoeff * outputs[0]);
|
||||
lastOutput = outputs[0];
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
/************ Test Main ************************/
|
||||
/*
|
||||
#include <stdio.h>
|
||||
|
||||
void main()
|
||||
{
|
||||
long i;
|
||||
OnePole test;
|
||||
test.setPole(0.99);
|
||||
for (i=0;i<150;i++) printf("%lf ",test.tick(1.0));
|
||||
printf("\n\n");
|
||||
|
||||
test.clear();
|
||||
test.setPole(0.9);
|
||||
test.setGain(2.0);
|
||||
for (i=0;i<150;i++) printf("%lf ",test.tick(0.5));
|
||||
printf("\n\n");
|
||||
}
|
||||
*/
|
||||
35
OnePole.h
35
OnePole.h
@@ -1,35 +0,0 @@
|
||||
/*******************************************/
|
||||
/* One Pole Filter Class, */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* The parameter gain is an additional */
|
||||
/* gain parameter applied to the filter */
|
||||
/* on top of the normalization that takes */
|
||||
/* place automatically. So the net max */
|
||||
/* gain through the system equals the */
|
||||
/* value of gain. sgain is the combina- */
|
||||
/* tion of gain and the normalization */
|
||||
/* parameter, so if you set the poleCoeff */
|
||||
/* to alpha, sgain is always set to */
|
||||
/* gain * (1.0 - fabs(alpha)). */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__OnePole_h)
|
||||
#define __OnePole_h
|
||||
|
||||
#include "Filter.h"
|
||||
|
||||
class OnePole : public Filter
|
||||
{
|
||||
protected:
|
||||
MY_FLOAT poleCoeff;
|
||||
MY_FLOAT sgain;
|
||||
public:
|
||||
OnePole();
|
||||
~OnePole();
|
||||
void clear();
|
||||
void setPole(MY_FLOAT aValue);
|
||||
void setGain(MY_FLOAT aValue);
|
||||
MY_FLOAT tick(MY_FLOAT sample);
|
||||
};
|
||||
|
||||
#endif
|
||||
64
OneZero.cpp
64
OneZero.cpp
@@ -1,64 +0,0 @@
|
||||
/*******************************************/
|
||||
/* One Zero Filter Class, */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* The parameter gain is an additional */
|
||||
/* gain parameter applied to the filter */
|
||||
/* on top of the normalization that takes */
|
||||
/* place automatically. So the net max */
|
||||
/* gain through the system equals the */
|
||||
/* value of gain. sgain is the combina- */
|
||||
/* tion of gain and the normalization */
|
||||
/* parameter, so if you set the poleCoeff */
|
||||
/* to alpha, sgain is always set to */
|
||||
/* gain / (1.0 - fabs(alpha)). */
|
||||
/*******************************************/
|
||||
|
||||
#include "OneZero.h"
|
||||
|
||||
OneZero :: OneZero()
|
||||
{
|
||||
gain = (MY_FLOAT) 1.0;
|
||||
zeroCoeff = (MY_FLOAT) 1.0;
|
||||
sgain = (MY_FLOAT) 0.5;
|
||||
inputs = (MY_FLOAT *) malloc(MY_FLOAT_SIZE);
|
||||
this->clear();
|
||||
}
|
||||
|
||||
OneZero :: ~OneZero()
|
||||
{
|
||||
free(inputs);
|
||||
}
|
||||
|
||||
void OneZero :: clear()
|
||||
{
|
||||
inputs[0] = (MY_FLOAT) 0.0;
|
||||
lastOutput = (MY_FLOAT) 0.0;
|
||||
}
|
||||
|
||||
void OneZero :: setGain(MY_FLOAT aValue)
|
||||
{
|
||||
gain = aValue;
|
||||
if (zeroCoeff > 0.0) /* Normalize gain to 1.0 max */
|
||||
sgain = gain / ((MY_FLOAT) 1.0 + zeroCoeff);
|
||||
else
|
||||
sgain = gain / ((MY_FLOAT) 1.0 - zeroCoeff);
|
||||
}
|
||||
|
||||
void OneZero :: setCoeff(MY_FLOAT aValue)
|
||||
{
|
||||
zeroCoeff = aValue;
|
||||
if (zeroCoeff > 0.0) /* Normalize gain to 1.0 max */
|
||||
sgain = gain / ((MY_FLOAT) 1.0 + zeroCoeff);
|
||||
else
|
||||
sgain = gain / ((MY_FLOAT) 1.0 - zeroCoeff);
|
||||
}
|
||||
|
||||
MY_FLOAT OneZero :: tick(MY_FLOAT sample) /* Perform Filter Operation */
|
||||
{
|
||||
MY_FLOAT temp;
|
||||
temp = sgain * sample;
|
||||
lastOutput = (inputs[0] * zeroCoeff) + temp;
|
||||
inputs[0] = temp;
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
35
OneZero.h
35
OneZero.h
@@ -1,35 +0,0 @@
|
||||
/*******************************************/
|
||||
/* One Zero Filter Class, */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* The parameter gain is an additional */
|
||||
/* gain parameter applied to the filter */
|
||||
/* on top of the normalization that takes */
|
||||
/* place automatically. So the net max */
|
||||
/* gain through the system equals the */
|
||||
/* value of gain. sgain is the combina- */
|
||||
/* tion of gain and the normalization */
|
||||
/* parameter, so if you set the poleCoeff */
|
||||
/* to alpha, sgain is always set to */
|
||||
/* gain / (1.0 - fabs(alpha)). */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__OneZero_h)
|
||||
#define __OneZero_h
|
||||
|
||||
#include "Filter.h"
|
||||
|
||||
class OneZero : public Filter
|
||||
{
|
||||
protected:
|
||||
MY_FLOAT zeroCoeff;
|
||||
MY_FLOAT sgain;
|
||||
public:
|
||||
OneZero();
|
||||
~OneZero();
|
||||
void clear();
|
||||
void setGain(MY_FLOAT aValue);
|
||||
void setCoeff(MY_FLOAT aValue);
|
||||
MY_FLOAT tick(MY_FLOAT sample);
|
||||
};
|
||||
|
||||
#endif
|
||||
113
PRCRev.cpp
113
PRCRev.cpp
@@ -1,113 +0,0 @@
|
||||
/*******************************************/
|
||||
/* PRCRev, a simple reverb unit */
|
||||
/* by Perry Cook, 1996. */
|
||||
/* Incorporated into the Reverb superclass */
|
||||
/* by Gary Scavone, 1998. */
|
||||
/* */
|
||||
/* This is based on some of the famous */
|
||||
/* Stanford CCRMA reverbs (NRev, KipRev) */
|
||||
/* all based on the the Chowning/Moorer/ */
|
||||
/* Schroeder reverberators, which use */
|
||||
/* networks of simple allpass and comb */
|
||||
/* delay filters. This particular */
|
||||
/* structure consists of 2 allpass units */
|
||||
/* in series followed by 2 comb filters in */
|
||||
/* parallel. */
|
||||
/*******************************************/
|
||||
|
||||
#include "PRCRev.h"
|
||||
|
||||
PRCRev :: PRCRev(MY_FLOAT T60)
|
||||
{
|
||||
int lens[4]={353,1097,1777,2137};
|
||||
double srscale = SRATE / 44100.0;
|
||||
int val, i;
|
||||
|
||||
if (SRATE < 44100.0) {
|
||||
for (i=0; i<4; i++) {
|
||||
val = (int) floor(srscale * lens[i]);
|
||||
if ((val & 1) == 0) val++;
|
||||
while (!this->isprime(val)) val += 2;
|
||||
lens[i] = val;
|
||||
}
|
||||
}
|
||||
for (i=0; i<2; i++)
|
||||
{
|
||||
APdelayLine[i] = new DLineN(lens[i] + 2);
|
||||
APdelayLine[i]->setDelay(lens[i]);
|
||||
CdelayLine[i] = new DLineN(lens[i+2] + 2);
|
||||
CdelayLine[i]->setDelay(lens[i+2]);
|
||||
combCoeff[i] = pow(10,(-3 * lens[i+2] / (T60 * SRATE)));
|
||||
}
|
||||
|
||||
allPassCoeff = (MY_FLOAT) 0.7;
|
||||
effectMix = (MY_FLOAT) 0.5;
|
||||
this->clear();
|
||||
}
|
||||
|
||||
PRCRev :: ~PRCRev()
|
||||
{
|
||||
delete APdelayLine[0];
|
||||
delete APdelayLine[1];
|
||||
delete CdelayLine[0];
|
||||
delete CdelayLine[1];
|
||||
}
|
||||
|
||||
void PRCRev :: clear()
|
||||
{
|
||||
APdelayLine[0]->clear();
|
||||
APdelayLine[1]->clear();
|
||||
CdelayLine[0]->clear();
|
||||
CdelayLine[1]->clear();
|
||||
lastOutL = (MY_FLOAT) 0.0;
|
||||
lastOutR = (MY_FLOAT) 0.0;
|
||||
}
|
||||
|
||||
void PRCRev :: setEffectMix(MY_FLOAT mix)
|
||||
{
|
||||
effectMix = mix;
|
||||
}
|
||||
|
||||
MY_FLOAT PRCRev :: lastOutput()
|
||||
{
|
||||
return (lastOutL + lastOutR) * (MY_FLOAT) 0.5;
|
||||
}
|
||||
|
||||
MY_FLOAT PRCRev :: lastOutputL()
|
||||
{
|
||||
return lastOutL;
|
||||
}
|
||||
|
||||
MY_FLOAT PRCRev :: lastOutputR()
|
||||
{
|
||||
return lastOutR;
|
||||
}
|
||||
|
||||
MY_FLOAT PRCRev :: tick(MY_FLOAT input)
|
||||
{
|
||||
MY_FLOAT temp,temp0,temp1,temp2,temp3;
|
||||
|
||||
temp = APdelayLine[0]->lastOut();
|
||||
temp0 = allPassCoeff * temp;
|
||||
temp0 += input;
|
||||
APdelayLine[0]->tick(temp0);
|
||||
temp0 = -(allPassCoeff * temp0) + temp;
|
||||
|
||||
temp = APdelayLine[1]->lastOut();
|
||||
temp1 = allPassCoeff * temp;
|
||||
temp1 += temp0;
|
||||
APdelayLine[1]->tick(temp1);
|
||||
temp1 = -(allPassCoeff * temp1) + temp;
|
||||
|
||||
temp2 = temp1 + (combCoeff[0] * CdelayLine[0]->lastOut());
|
||||
temp3 = temp1 + (combCoeff[1] * CdelayLine[1]->lastOut());
|
||||
|
||||
lastOutL = effectMix * (CdelayLine[0]->tick(temp2));
|
||||
lastOutR = effectMix * (CdelayLine[1]->tick(temp3));
|
||||
temp = (MY_FLOAT) (1.0 - effectMix) * input;
|
||||
lastOutL += temp;
|
||||
lastOutR += temp;
|
||||
|
||||
return (lastOutL + lastOutR) * (MY_FLOAT) 0.5;
|
||||
|
||||
}
|
||||
43
PRCRev.h
43
PRCRev.h
@@ -1,43 +0,0 @@
|
||||
/*******************************************/
|
||||
/* PRCRev, a simple reverb unit */
|
||||
/* by Perry Cook, 1996. */
|
||||
/* Incorporated into the Reverb superclass */
|
||||
/* by Gary Scavone, 1998. */
|
||||
/* */
|
||||
/* This is based on some of the famous */
|
||||
/* Stanford CCRMA reverbs (NRev, KipRev) */
|
||||
/* all based on the the Chowning/Moorer/ */
|
||||
/* Schroeder reverberators, which use */
|
||||
/* networks of simple allpass and comb */
|
||||
/* delay filters. */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__PRCRev_h)
|
||||
#define __PRCRev_h
|
||||
|
||||
#include "Reverb.h"
|
||||
#include "DLineN.h"
|
||||
|
||||
class PRCRev : public Reverb
|
||||
{
|
||||
protected:
|
||||
DLineN *APdelayLine[2];
|
||||
DLineN *CdelayLine[2];
|
||||
MY_FLOAT allPassCoeff;
|
||||
MY_FLOAT combCoeff[2];
|
||||
MY_FLOAT lastOutL;
|
||||
MY_FLOAT lastOutR;
|
||||
MY_FLOAT effectMix;
|
||||
public:
|
||||
PRCRev(MY_FLOAT T60);
|
||||
~PRCRev();
|
||||
void clear();
|
||||
void setEffectMix(MY_FLOAT mix);
|
||||
MY_FLOAT lastOutput();
|
||||
MY_FLOAT lastOutputL();
|
||||
MY_FLOAT lastOutputR();
|
||||
MY_FLOAT tick(MY_FLOAT input);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
54
PercFlut.cpp
54
PercFlut.cpp
@@ -1,54 +0,0 @@
|
||||
/******************************************/
|
||||
/* Percussive Flute Subclass */
|
||||
/* of Algorithm 4 (TX81Z) Subclass of */
|
||||
/* 4 Operator FM Synth */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/******************************************/
|
||||
|
||||
#include "PercFlut.h"
|
||||
|
||||
PercFlut :: PercFlut() : FM4Alg4()
|
||||
{
|
||||
this->loadWaves("rawwaves/sinewave.raw",
|
||||
"rawwaves/sinewave.raw",
|
||||
"rawwaves/sinewave.raw",
|
||||
"rawwaves/sinewave.raw");
|
||||
|
||||
this->setRatio(0,(MY_FLOAT) (1.50 * 1.000));
|
||||
this->setRatio(1,(MY_FLOAT) (3.00 * 0.995));
|
||||
this->setRatio(2,(MY_FLOAT) (2.99 * 1.005));
|
||||
this->setRatio(3,(MY_FLOAT) (6.00 * 0.997));
|
||||
gains[0] = __FM4Op_gains[99];
|
||||
gains[1] = __FM4Op_gains[71];
|
||||
gains[2] = __FM4Op_gains[93];
|
||||
gains[3] = __FM4Op_gains[85];
|
||||
adsr[0]->setAllTimes((MY_FLOAT) 0.05,(MY_FLOAT) 0.05,
|
||||
__FM4Op_susLevels[14],(MY_FLOAT) 0.05);
|
||||
adsr[1]->setAllTimes((MY_FLOAT) 0.02,(MY_FLOAT) 0.50,
|
||||
__FM4Op_susLevels[13],(MY_FLOAT) 0.5);
|
||||
adsr[2]->setAllTimes((MY_FLOAT) 0.02,(MY_FLOAT) 0.30,
|
||||
__FM4Op_susLevels[11],(MY_FLOAT) 0.05);
|
||||
adsr[3]->setAllTimes((MY_FLOAT) 0.02,(MY_FLOAT) 0.05,
|
||||
__FM4Op_susLevels[13],(MY_FLOAT) 0.01);
|
||||
twozero->setGain((MY_FLOAT) 0.0);
|
||||
modDepth = (MY_FLOAT) 0.005;
|
||||
}
|
||||
|
||||
void PercFlut :: setFreq(MY_FLOAT frequency)
|
||||
{
|
||||
baseFreq = frequency;
|
||||
}
|
||||
|
||||
void PercFlut :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
||||
{
|
||||
gains[0] = amp * __FM4Op_gains[99] * 0.5;
|
||||
gains[1] = amp * __FM4Op_gains[71] * 0.5;
|
||||
gains[2] = amp * __FM4Op_gains[93] * 0.5;
|
||||
gains[3] = amp * __FM4Op_gains[85] * 0.5;
|
||||
this->setFreq(freq);
|
||||
this->keyOn();
|
||||
#if defined(_debug_)
|
||||
printf("PercFlut : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
21
PercFlut.h
21
PercFlut.h
@@ -1,21 +0,0 @@
|
||||
/******************************************/
|
||||
/* Percussive Flute Subclass */
|
||||
/* of Algorithm 4 (TX81Z) Subclass of */
|
||||
/* 4 Operator FM Synth */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__PercFlut_h)
|
||||
#define __PercFlut_h
|
||||
|
||||
#include "FM4Alg4.h"
|
||||
|
||||
class PercFlut : public FM4Alg4
|
||||
{
|
||||
public:
|
||||
PercFlut();
|
||||
virtual void setFreq(MY_FLOAT frequency);
|
||||
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
|
||||
};
|
||||
|
||||
#endif
|
||||
83
Plucked.cpp
83
Plucked.cpp
@@ -1,83 +0,0 @@
|
||||
/******************************************/
|
||||
/* Karplus-Strong plucked string model */
|
||||
/* by Perry Cook, 1995-96 */
|
||||
/* */
|
||||
/* There exist at least two patents, */
|
||||
/* assigned to Stanford, bearing the */
|
||||
/* names of Karplus and/or Strong. */
|
||||
/******************************************/
|
||||
|
||||
#include "Plucked.h"
|
||||
|
||||
Plucked :: Plucked(MY_FLOAT lowestFreq)
|
||||
{
|
||||
length = (long) (SRATE / lowestFreq + 1);
|
||||
loopGain = (MY_FLOAT) 0.999;
|
||||
delayLine = new DLineA(length);
|
||||
loopFilt = new OneZero;
|
||||
pickFilt = new OnePole;
|
||||
noise = new Noise;
|
||||
this->clear();
|
||||
}
|
||||
|
||||
Plucked :: ~Plucked()
|
||||
{
|
||||
delete delayLine;
|
||||
delete loopFilt;
|
||||
delete pickFilt;
|
||||
delete noise;
|
||||
}
|
||||
|
||||
void Plucked :: clear()
|
||||
{
|
||||
delayLine->clear();
|
||||
loopFilt->clear();
|
||||
pickFilt->clear();
|
||||
}
|
||||
|
||||
void Plucked :: setFreq(MY_FLOAT frequency)
|
||||
{
|
||||
MY_FLOAT delay;
|
||||
delay = (SRATE / frequency) - (MY_FLOAT) 0.5; /* length - delays */
|
||||
delayLine->setDelay(delay);
|
||||
loopGain = (MY_FLOAT) 0.995 + (frequency * (MY_FLOAT) 0.000005);
|
||||
if (loopGain>1.0) loopGain = (MY_FLOAT) 0.99999;
|
||||
}
|
||||
|
||||
void Plucked :: pluck(MY_FLOAT amplitude)
|
||||
{
|
||||
long i;
|
||||
pickFilt->setPole((MY_FLOAT) 0.999 - (amplitude * (MY_FLOAT) 0.15));
|
||||
pickFilt->setGain(amplitude * (MY_FLOAT) 0.5);
|
||||
for (i=0;i<length;i++)
|
||||
delayLine->tick(delayLine->lastOut() * (MY_FLOAT) 0.6 /* fill delay with noise */
|
||||
+ pickFilt->tick(noise->tick())); /* additively with current */
|
||||
/* contents */
|
||||
}
|
||||
|
||||
void Plucked :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
||||
{
|
||||
this->setFreq(freq);
|
||||
this->pluck(amp);
|
||||
#if defined(_debug_)
|
||||
printf("Plucked : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Plucked :: noteOff(MY_FLOAT amp)
|
||||
{
|
||||
loopGain = (MY_FLOAT) 1.0 - amp;
|
||||
#if defined(_debug_)
|
||||
printf("Plucked : NoteOff: Amp=%lf\n",amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
MY_FLOAT Plucked :: tick()
|
||||
{
|
||||
/* check this out */
|
||||
/* here's the whole inner loop of the instrument!! */
|
||||
lastOutput = delayLine->tick(loopFilt->tick(delayLine->lastOut() * loopGain));
|
||||
lastOutput *= (MY_FLOAT) 3.0;
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
40
Plucked.h
40
Plucked.h
@@ -1,40 +0,0 @@
|
||||
/******************************************/
|
||||
/* Karplus-Strong plucked string model */
|
||||
/* by Perry Cook, 1995-96 */
|
||||
/* */
|
||||
/* There exist at least two patents, */
|
||||
/* assigned to Stanford, bearing the */
|
||||
/* names of Karplus and/or Strong. */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__Plucked_h)
|
||||
#define __Plucked_h
|
||||
|
||||
#include "Instrmnt.h"
|
||||
#include "DLineA.h"
|
||||
#include "OneZero.h"
|
||||
#include "OnePole.h"
|
||||
#include "Noise.h"
|
||||
|
||||
class Plucked : public Instrmnt
|
||||
{
|
||||
protected:
|
||||
DLineA *delayLine;
|
||||
OneZero *loopFilt;
|
||||
OnePole *pickFilt;
|
||||
Noise *noise;
|
||||
long length;
|
||||
MY_FLOAT loopGain;
|
||||
public:
|
||||
Plucked(MY_FLOAT lowestFreq);
|
||||
~Plucked();
|
||||
void clear();
|
||||
virtual void setFreq(MY_FLOAT frequency);
|
||||
void pluck(MY_FLOAT amplitude);
|
||||
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
|
||||
virtual void noteOff(MY_FLOAT amp);
|
||||
virtual MY_FLOAT tick();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
90
Plucked2.cpp
90
Plucked2.cpp
@@ -1,90 +0,0 @@
|
||||
/******************************************/
|
||||
/* Enhanced (Jaffe-Smith, Smith, others) */
|
||||
/* Karplus-Strong plucked model */
|
||||
/* by Perry Cook, 1995-96 */
|
||||
/* This is the super-class, with no */
|
||||
/* excitation specified. So this one by */
|
||||
/* itself doesn't make any sound. */
|
||||
/******************************************/
|
||||
|
||||
#include "Plucked2.h"
|
||||
|
||||
Plucked2 :: Plucked2(MY_FLOAT lowestFreq)
|
||||
{
|
||||
length = (long) (SRATE / lowestFreq + 1);
|
||||
baseLoopGain = (MY_FLOAT) 0.995;
|
||||
loopGain = (MY_FLOAT) 0.999;
|
||||
delayLine = new DLineA(length);
|
||||
delayLine2 = new DLineA(length);
|
||||
combDelay = new DLineL(length);
|
||||
filter = new OneZero;
|
||||
filter2 = new OneZero;
|
||||
pluckAmp = (MY_FLOAT) 0.3;
|
||||
pluckPos = (MY_FLOAT) 0.4;
|
||||
detuning = (MY_FLOAT) 0.995;
|
||||
lastFreq = lowestFreq * (MY_FLOAT) 2.0;
|
||||
lastLength = length * (MY_FLOAT) 0.5;
|
||||
}
|
||||
|
||||
Plucked2 :: ~Plucked2()
|
||||
{
|
||||
delete delayLine;
|
||||
delete delayLine2;
|
||||
delete combDelay;
|
||||
delete filter;
|
||||
delete filter2;
|
||||
}
|
||||
|
||||
void Plucked2 :: clear()
|
||||
{
|
||||
delayLine->clear();
|
||||
delayLine2->clear();
|
||||
combDelay->clear();
|
||||
filter->clear();
|
||||
filter2->clear();
|
||||
}
|
||||
|
||||
void Plucked2 :: setFreq(MY_FLOAT frequency)
|
||||
{
|
||||
lastFreq = frequency;
|
||||
lastLength = ((MY_FLOAT) SRATE / lastFreq); /* length - delays */
|
||||
delayLine->setDelay((lastLength / detuning) - (MY_FLOAT) 0.5);
|
||||
delayLine2->setDelay((lastLength * detuning) - (MY_FLOAT) 0.5);
|
||||
loopGain = baseLoopGain + (frequency * (MY_FLOAT) 0.000005);
|
||||
if (loopGain>1.0) loopGain = (MY_FLOAT) 0.99999;
|
||||
}
|
||||
|
||||
void Plucked2 :: setDetune(MY_FLOAT detune)
|
||||
{
|
||||
detuning = detune;
|
||||
delayLine->setDelay((lastLength / detuning) - (MY_FLOAT) 0.5);
|
||||
delayLine2->setDelay((lastLength * detuning) - (MY_FLOAT) 0.5);
|
||||
}
|
||||
|
||||
void Plucked2 :: setFreqAndDetune(MY_FLOAT frequency,MY_FLOAT detune)
|
||||
{
|
||||
lastFreq = frequency;
|
||||
detuning = detune;
|
||||
this->setFreq(frequency);
|
||||
}
|
||||
|
||||
void Plucked2 :: setPluckPos(MY_FLOAT position)
|
||||
{
|
||||
pluckPos = position;
|
||||
}
|
||||
|
||||
void Plucked2 :: setBaseLoopGain(MY_FLOAT aGain)
|
||||
{
|
||||
baseLoopGain = aGain;
|
||||
loopGain = baseLoopGain + (lastFreq * (MY_FLOAT) 0.000005);
|
||||
if (loopGain>1.0) loopGain = (MY_FLOAT) 0.99999;
|
||||
}
|
||||
|
||||
void Plucked2 :: noteOff(MY_FLOAT amp)
|
||||
{
|
||||
loopGain = ((MY_FLOAT) 1.0 - amp) * (MY_FLOAT) 0.5;
|
||||
#if defined(_debug_)
|
||||
printf("Plucked2 : NoteOff: Amp=%lf\n",amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
46
Plucked2.h
46
Plucked2.h
@@ -1,46 +0,0 @@
|
||||
/******************************************/
|
||||
/* Enhanced (Jaffe-Smith, Smith, others) */
|
||||
/* Karplus-Strong plucked model */
|
||||
/* by Perry Cook, 1995-96 */
|
||||
/* This is the super-class, with no */
|
||||
/* excitation specified. So this one by */
|
||||
/* itself doesn't make any sound. */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__Plucked2_h)
|
||||
#define __Plucked2_h
|
||||
|
||||
#include "Instrmnt.h"
|
||||
#include "DLineL.h"
|
||||
#include "DLineA.h"
|
||||
#include "OneZero.h"
|
||||
|
||||
class Plucked2 : public Instrmnt
|
||||
{
|
||||
protected:
|
||||
DLineA *delayLine;
|
||||
DLineA *delayLine2;
|
||||
DLineL *combDelay;
|
||||
OneZero *filter;
|
||||
OneZero *filter2;
|
||||
long length;
|
||||
MY_FLOAT loopGain;
|
||||
MY_FLOAT baseLoopGain;
|
||||
MY_FLOAT lastFreq;
|
||||
MY_FLOAT lastLength;
|
||||
MY_FLOAT detuning;
|
||||
MY_FLOAT pluckAmp;
|
||||
MY_FLOAT pluckPos;
|
||||
public:
|
||||
Plucked2(MY_FLOAT lowestFreq);
|
||||
virtual ~Plucked2();
|
||||
void clear();
|
||||
virtual void setFreq(MY_FLOAT frequency);
|
||||
void setDetune(MY_FLOAT detune);
|
||||
void setFreqAndDetune(MY_FLOAT frequency, MY_FLOAT detune);
|
||||
void setPluckPos(MY_FLOAT position);
|
||||
void setBaseLoopGain(MY_FLOAT aGain);
|
||||
virtual void noteOff(MY_FLOAT amp);
|
||||
};
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user