43 Commits

Author SHA1 Message Date
Gary Scavone
18730391e8 Release 4.4.4 tarball 2013-09-29 23:51:11 +02:00
Stephen Sinclair
899303d7c4 Merge 4.4.4 into releases 2013-09-29 23:50:23 +02:00
Gary Scavone
f13d5bb3cd Release 4.4.3 tarball 2013-09-29 23:49:37 +02:00
Stephen Sinclair
cfdfe7736a Merge 4.4.3 into releases 2013-09-29 23:49:08 +02:00
Gary Scavone
7fcf920d3e Release 4.4.2 tarball 2013-09-29 23:48:48 +02:00
Stephen Sinclair
c37de52787 Merge 4.4.2 into releases 2013-09-29 23:48:01 +02:00
Gary Scavone
5a8a65870f Release 4.4.1 tarball 2013-09-29 23:47:43 +02:00
Stephen Sinclair
9af41126cb Merge 4.4.1 into releases 2013-09-29 23:46:44 +02:00
Gary Scavone
d2ed001eb5 Release 4.4.0 tarball 2013-09-29 23:44:33 +02:00
Stephen Sinclair
3706458166 Merge 4.4.0 into releases 2013-09-29 23:42:55 +02:00
Gary Scavone
c92cf7468d Release 4.3.1 tarball 2013-09-29 23:42:39 +02:00
Stephen Sinclair
e54b0cefab Merge 4.3.1 into releases 2013-09-29 23:42:10 +02:00
Gary Scavone
1a8403e203 Release 4.3.0 tarball 2013-09-29 23:41:50 +02:00
Stephen Sinclair
554a74374b Merge 4.3.0 into releases 2013-09-29 23:41:15 +02:00
Gary Scavone
21b93795e7 Release 4.2.1 tarball 2013-09-29 23:40:35 +02:00
Stephen Sinclair
11cf5faa0a Merge 4.2.1 into releases 2013-09-29 23:40:06 +02:00
Gary Scavone
de344668dd Release 4.2.0 tarball 2013-09-29 23:39:37 +02:00
Stephen Sinclair
fe20fe92a2 Merge 4.2.0 into releases 2013-09-29 23:38:59 +02:00
Gary Scavone
e11bff2fe8 Release 4.1.3 tarball 2013-09-29 23:38:16 +02:00
Stephen Sinclair
503ed3cc9f Merge 4.1.3 into releases 2013-09-29 23:37:48 +02:00
Gary Scavone
5d63b50e85 Release 4.1.2 tarball 2013-09-29 23:37:27 +02:00
Stephen Sinclair
d12ef806ac Merge 4.1.2 into releases 2013-09-29 23:37:02 +02:00
Gary Scavone
ffce5357c6 Release 4.1.1 tarball 2013-09-29 23:36:33 +02:00
Stephen Sinclair
b39c0bb101 Merge 4.1.1 into releases 2013-09-29 23:35:55 +02:00
Gary Scavone
f25eb5c3d7 Release 4.1 tarball 2013-09-29 23:35:44 +02:00
Stephen Sinclair
71e5c027fb Merge 4.1 into releases 2013-09-29 23:34:55 +02:00
Gary Scavone
43dcd5775a Release 4.0 tarball 2013-09-29 23:33:56 +02:00
Gary Scavone
fc877b87bf Version 4.4.4 2013-09-29 23:22:28 +02:00
Gary Scavone
0aec39260a Version 4.4.3 2013-09-29 23:21:29 +02:00
Gary Scavone
baca57040b Version 4.4.2 2013-09-29 23:15:24 +02:00
Gary Scavone
b6a2202011 Version 4.4.1 2013-09-29 23:14:45 +02:00
Gary Scavone
eccd8c9981 Version 4.4.0 2013-09-29 23:11:39 +02:00
Gary Scavone
d199342e86 Version 4.3.1 2013-09-29 23:07:08 +02:00
Gary Scavone
27d9b79dc7 Version 4.3.0 2013-09-29 23:07:00 +02:00
Gary Scavone
2cbce2d8bd Version 4.2.1 2013-09-29 23:06:23 +02:00
Gary Scavone
a6381b9d38 Version 4.2.0 2013-09-29 23:06:14 +02:00
Gary Scavone
cf06b7598b Version 4.1.3 2013-09-29 23:06:05 +02:00
Gary Scavone
586b0add5f Version 4.1.2 2013-09-29 23:05:20 +02:00
Gary Scavone
6e0d1955a8 Version 4.1.1 2013-09-29 23:05:09 +02:00
Gary Scavone
2f09fcd019 Version 4.1 2013-09-29 23:04:59 +02:00
Gary Scavone
81475b04c5 Version 4.0 2013-09-29 23:04:45 +02:00
Gary Scavone
3f126af4e5 Version 3.2 2013-09-29 22:42:55 +02:00
Gary Scavone
4b6500d3de Version 3.1 2013-09-29 22:42:17 +02:00
1220 changed files with 152944 additions and 22640 deletions

View File

@@ -1,145 +0,0 @@
STK: A ToolKit of Audio Synthesis Classes and Instruments in C++
Version 3.0
By Perry R. Cook, 1995-99
and Gary P. Scavone, 1997-99.
STK Classes, Version 3.0
Please read README.txt for more information.
<--------Building Blocks---------->|<----------------Instruments------------------>
SourcSink Filters Reverb Non-Lin Modal & FM Physical Sampling PhISM
Formant
Object-----------------------------------Instrmnt----------.
| | | | | | |
Envelope| Filter Reverb BowTabl | .----------------------------------------.
| | | | JetTabl | | | | | | | | |
ADSR | OneZero PRCRev ReedTabl| Modal4 | FM4Op---.| | | | Shakers
| OnePole JCRev | | | | || | | | |
._____| TwoZero NRev .____| Marimba | FM4Alg3 || Plucked Sampler | Maraca
| | TwoPole | Vibraphn| | || Clarinet | | Sekere
Noise | DCBlock LipFilt AgogoBel| HeavyMtl|| Brass SamplFlt| Cabasa
| | BiQuad | || Flute | | Bamboo
SubNoise| DlineL .____| .____|| Bowed Moog1 | Water Drops
| DLineA | | || BowedBar | Tambourine
._____| DLineN VoicForm FM4Alg4 ||____. | SleighBells
| | FormSwep | | | | Guiro
WvIn | PoleZero PercFlut| Plucked2 | Wrench
| |____. | | | Coke Can
WavWvIn | | .____| Mandolin .____| Sticks
SndWvIn | TablLook | | | Crunch
RawWvIn | FM4Alg5 | DrumSynt Sand Paper
MatWvIn | | |
RTWvIn | Rhodey |
| Wurley |
._____| TubeBell |
| | .____|
Modulatr| | |
| FM4Alg6 |
._____| | |
| | FMVoices|
SingWave|_____. |
| | .____|
._____| WvOut |
| | | FM4Alg8
VoicMang| WavWvOut |
| SndWvOut BeeThree
| RTWvOut
| MatWvOut
._____| RawWvOut
|
MIDIIO
********** INSTRUMENTS AND ALGORITHMS **************
Each Class will be listed either with all UGs it uses,
or the <<Algorithm>> of which it is a flavor.
All inherit from Instrmnt, which inherits from Object.
Plucked.cpp Basic Plucked String DLineA,OneZero,OnePole,Noise
Plucked2.cpp Not So Basic Pluck DLineL,DlineA,OneZero
Mandolin.cpp My Own Mandolin <<flavor of Plucked2>>
Bowed.cpp Not Hideous Bowed String DlineL,BowTabl,OnePole,BiQuad,RawWave,ADSR
Brass.cpp Not So Bad Brass Inst. DLineA,LipFilt,DCBlock,ADSR,RawWvIn
Clarinet.cpp Pretty Good Clarinet DLineL,ReedTabl,OneZero,Envelope,Noise,RawWvIn
Flute.cpp Pretty Good Flute JetTabl,DLineL,OnePole,DCBlock,Noise,ADSR,RawWvIn
BowedBar.cpp Pretty Good Bowed Bar DLineN,BowTabl,ADSR,BiQuad
Modal4.cpp 4 Resonances Envelope,RawWvIn,RawWvIn,BiQuad,OnePole
Marimba.cpp <<flavor of MODAL4>>
Vibraphn.cpp <<flavor of MODAL4>>
Agogobel.cpp <<flavor of MODAL4>>
FM4Op.cpp 4 Operator FM Master ADSR,RawWvIn,TwoZero
FM4Alg3.cpp 3 Cascade w/ FB Mod. <<flavor of FM4OP>>
FM4Alg4.cpp Like Alg3 but diff. <<flavor of FM4OP>>
FM4Alg5.cpp 2 Parallel Simple FMs <<flavor of FM4OP>>
FM4Alg6.cpp 3 Carr. with 1 Mod. <<flavor of FM4OP>>
FM4Alg8.cpp 4 Osc. Additive <<flavor of FM4OP>>
HeavyMtl.cpp Distorted Synth <<flavor of FM4Alg3>>
PercFlut.cpp Perc. Flute <<flavor of FM4Alg4>>
Rhodey.cpp Rhodes-Like Elec. Piano <<flavor of FM4Alg5>>
Wurley.cpp Wurlitz. Elec. Piano <<flavor of FM4Alg5>>
TubeBell.cpp Classic FM Bell <<flavor of FM4Alg5>>
FMVoices.cpp 3-Formant Voice Synth. <<flavor of FM4Alg6>>
BeeThree.cpp Cheezy Organ for Paul <<flavor of FM4Alg8>>
Sampler.cpp Sampling Synth. 4 each ADSR, RawWvIn (att), RawWvIn (loop), OnePole
SamplFlt.cpp Sampler with Swept Filter <<flavor of Sampler>>
Moog1.cpp Swept filter flavor of <<flavor of SamplFlt>>
VoicForm.cpp Source/Filter Voice Envelope,Noise,SingWave,FormSwep,OnePole,OneZero
DrumSynt.cpp Drum Synthesizer bunch of RawWvIn, and OnePole
Shakers.cpp Stochastic Event Models
*********** BASIC UNIT GENERATORS **************
Master Object: Object.cpp For compatibility with Objective C
Source&Sink: Envelope.cpp Linearly Goes to Target by Rate, + noteOn/Off
ADSR.cpp ADSR Flavor of Envelope
Noise.cpp Random Number Generator
SubNoise.cpp Random Numbers each N samples
Inputs: TablLook.cpp Lookup Table (assumes given data in big-endian format)
WvIn.cpp Input Master Class (Looping, One-Shot,
Interpolating, Non-Interpolating)
RawWvIn.cpp STK Raw-file Input
SndWvIn.cpp .snd Input Class
WavWvIn.cpp .wav Input Class
MatWvIn.cpp Matlab MAT-file Input Class
RTWvIn.cpp Realtime Input Class
Outputs: WvOut.cpp Output Master Class
RawWvOut.cpp STK Raw-file Output Class
SndWvOut.cpp .snd Output Class
WavWvOut.cpp .wav Output Class
RTWvOut.cpp Realtime Output Class
MatWvOut.cpp Matlab MaT-file Output Class
MIDI: MIDIIO.cpp MIDI I/O Class
Filters: Filter.cpp Filter Master Class
OneZero.cpp One Zero Filter
OnePole.cpp One Pole Filter
PoleZero.cpp One Pole/One Zero Filter
DCBlock.cpp DC Blocking 1Pole/1Zero Filter
TwoZero.cpp Two Zero Filter
TwoPole.cpp Two Pole Filter
BiQuad.cpp 2Pole/2Zero Filter
FormSwep.cpp Sweepable 2Pole filter, go to target by rate
DLineL.cpp Linearly Interpolating Delay Line
DLineA.cpp AllPass Interpolating Delay Line
DLineN.cpp Non Interpolating Delay Line
Reverb: Reverb.cpp Reverb Master Class
PRCRev.cpp 2 series allpass units, 2 parallel comb filters
JCRev.cpp 3 series allpass units, 4 parallel comb filters
NRev.cpp 6 parallel comb filters, 3 series allpass units, ...
NonLin&Lookup: JetTabl.cpp Cubic Jet NonLinearity
BowTabl.cpp 1/x^3-like Bow NonLinearity
ReedTabl.cpp 1 break point Reed NonLinearity
LipFilt.cpp Pressure Controlled BiQuad with NonLin
Derived: Modulatr.cpp Per. and Rnd. Vibrato: RawWave, SubNoise, OnePole
SingWave.cpp Looping Wavetable with: Modulatr, Envelope

42
INSTALL Normal file
View File

@@ -0,0 +1,42 @@
The Synthesis ToolKit in C++ (STK)
By Perry R. Cook and Gary P. Scavone, 1995-2012.
The Synthesis ToolKit in C++ can be used in a variety of ways, depending on your particular needs. Some people simmply 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.
To configure and compile (on Unix systems and MinGW):
1. Unpack the STK distribution (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)
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
For Windows Users:
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.

30
Makefile.in Normal file
View File

@@ -0,0 +1,30 @@
### Do not edit -- Generated by 'configure --with-whatever' from Makefile.in
RM = /bin/rm
all :
cd src && $(MAKE)
cd projects/demo && $(MAKE) libdemo
cd projects/effects && $(MAKE) libeffects
cd projects/ragamatic && $(MAKE) libragamat
cd projects/eguitar && $(MAKE) libeguitar
cd projects/examples && $(MAKE) -f libMakefile
clean :
$(RM) -f *~
cd src && $(MAKE) clean
cd projects/demo && $(MAKE) clean
cd projects/effects && $(MAKE) clean
cd projects/ragamatic && $(MAKE) clean
cd projects/eguitar && $(MAKE) clean
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
cd projects/effects && $(MAKE) distclean
cd projects/ragamatic && $(MAKE) distclean
cd projects/eguitar && $(MAKE) distclean
cd projects/examples && $(MAKE) distclean

217
README Normal file
View File

@@ -0,0 +1,217 @@
The Synthesis ToolKit in C++ (STK)
By Perry R. Cook and Gary P. Scavone, 1995-2012.
This distribution of the Synthesis ToolKit in C++ (STK) contains the following:
include: STK class header files
src: STK class source files
rawwaves: STK audio files (1-channel, 16-bit, big-endian)
doc: STK documentation
projects: example STK projects and programs
Please read the Legal and Ethical notes near the bottom of this document.
For compiling and installing STK, see the INSTALL file in this directory.
OVERVIEW:
The Synthesis ToolKit in C++ (STK) is a set of open source audio
signal processing and algorithmic synthesis classes written in the C++
programming language. STK was designed to facilitate rapid
development of music synthesis and audio processing software, with an
emphasis on cross-platform functionality, realtime control, ease of
use, and educational example code. The Synthesis ToolKit is extremely
portable (most classes are platform-independent C++ code), and it's
completely user-extensible (all source included, no unusual libraries,
and no hidden drivers). We like to think that this increases the
chances that our programs will still work in another 5-10 years. STK
currently runs with "realtime" support (audio and MIDI) on Linux,
Macintosh OS X, and Windows computer platforms. Generic, non-realtime
support has been tested under NeXTStep, Sun, and other platforms and
should work with any standard C++ compiler.
The only classes of the Synthesis ToolKit that are platform-dependent
concern sockets, threads, mutexes, and real-time audio and MIDI input
and output. The interface for MIDI input and the simple Tcl/Tk
graphical user interfaces (GUIs) provided is the same, so it's easy to
experiment in real time using either the GUIs or MIDI. The Synthesis
ToolKit can generate simultaneous SND (AU), WAV, AIFF, and MAT-file
output soundfile formats (as well as realtime sound output), so you
can view your results using one of a large variety of sound/signal
analysis tools already available (e.g. Snd, Cool Edit, Matlab).
The Synthesis Toolkit is not one particular program. Rather, it is a
set of C++ classes that you can use to create your own programs. A
few example applications are provided to demonstrate some of the ways
to use the classes. If you have specific needs, you will probably
have to either modify the example programs or write a new program
altogether. Further, the example programs don't have a fancy GUI
wrapper. If you feel the need to have a "drag and drop" graphical
patching GUI, you probably don't want to use the ToolKit. Spending
hundreds of hours making platform-dependent graphics code would go
against one of the fundamental design goals of the ToolKit - platform
independence.
For those instances where a simple GUI with sliders and buttons is
helpful, we use Tcl/Tk (http://dev.scriptics.com) which is freely
distributed for all the supported ToolKit platforms. A number of
Tcl/Tk GUI scripts are distributed with the ToolKit release. For
control, the Synthesis Toolkit uses raw MIDI (on supported platforms),
and SKINI (Synthesis ToolKit Instrument Network Interface, a MIDI-like
text message synthesis control format).
SYSTEM REQUIREMENTS:
See the individual README's (eg. README-linux) in the /doc directory
for platform specific information and system requirements. In
general, you will use the configure script to create Makefiles on unix
platforms (and MinGW) or the VC++ workspace files to compile the
example programs. To use the Tcl/Tk GUIs, you will need Tcl/Tk
version 8.0 or higher.
WHAT'S NEW (AND NOT SO NEW):
Despite being available in one form or another since 1996, we still
consider STK to be alpha software. We attempt to maintain backward
compatability but changes are sometimes made in an effort to improve
the overall design or performance of the software. Please read the
"Release Notes" in the /doc directory to see what has changed since
the last release.
A new StkFrames class has been created to facilitate the handling and
passing of multichannel, vectorized audio data. All STK classes have
been updated to include tick() functions that accept StkFrames
arguments.
The control message handling scheme has been simplified greatly
through the use of the Messager class. It is now possible to have
access to simultaneous piped, socketed, and/or MIDI input control
messages. In most cases, this should eliminate the use of the
Md2Skini program.
Realtime audio input capabilities were added to STK with release 3.0,
though the behavior of such is very hardware dependent. Under Linux
and Macintosh OS-X, audio input and output are possible with very low
latency. Using the Windoze DirectSound API, minimum dependable output
sound latency seems to be around 20 milliseconds or so, while input
sound latency is generally higher. Performance with the ASIO audio
API on Windoze provides much better performance.
As mentioned above, it is possible to record the audio ouput of an STK
program to .snd, .wav, .raw, .aif, and .mat (Matlab MAT-file) output
file types. Though somewhat obsolete, the program Md2Skini can be
used to write SKINI scorefiles from realtime MIDI input. Finally, STK
should compile with non-realtime functionality on any platform with a
generic C++ compiler.
For those who wish to make a library from the core STK classes, the
configure script generates a Makefile in the src directory that will
accomplish that.
DISCLAIMER:
You probably already guessed this, but just to be sure, we don't
guarantee anything works. :-) It's free ... what do you expect? If
you find a bug, please let us know and we'll try to correct it. You
can also make suggestions, but again, no guarantees. Send email to
the mail list.
LEGAL AND ETHICAL:
This software was designed and created to be made publicly available
for free, primarily for academic purposes, so if you use it, pass it
on with this documentation, and for free.
If you make a million dollars with it, it would be nice if you would
share. If you make compositions with it, put us in the program notes.
Some of the concepts are covered by various patents, some known to us
and likely others which are unknown. Many of the ones known to us are
administered by the Stanford Office of Technology and Licensing.
The good news is that large hunks of the techniques used here are
public domain. To avoid subtle legal issues, we'll not state what's
freely useable here, but we'll try to note within the various classes
where certain things are likely to be protected by patents.
LICENSE:
STK WWW site: http://ccrma.stanford.edu/software/stk/
The Synthesis ToolKit in C++ (STK)
Copyright (c) 1995-2012 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.
FURTHER READING:
For complete documentation on this ToolKit, the classes, etc., see the
doc directory of the distribution or surf to
http://ccrma.stanford.edu/software/stk/. Also check the platform
specific README's for specific system requirements.
PERRY'S NOTES FROM THE ORIGINAL DISTRIBUTION:
This whole world was created with no particular hardware in mind.
These examples are intended to be tutorial in nature, as a platform
for the continuation of my research, and as a possible starting point
for a software synthesis system. The basic motivation was to create
the necessary unit generators to do the synthesis, processing, and
control that I want to do and teach about. Little thought for
optimization was given and therefore improvements, especially speed
enhancements, should be possible with these classes. It was written
with some basic concepts in mind about how to let compilers optimize.
Your question at this point might be, "But Perry, with CMix, CMusic,
CSound, CShells, CMonkeys, etc. already cluttering the landscape, why
a new set of stupid C functions for music synthesis and processing?"
The answers lie below.
1) I needed to port many of the things I've done into something which is generic enough to port further to different machines.
2) I really plan to document this stuff, so that you don't have to be me to figure out what's going on. (I'll probably be sorry I said this in a couple of years, when even I can't figure out what I was thinking.)
3) The classic difficulties most people have in trying to implement physical models are:
A) They have trouble understanding the papers, and/or in turning the theory into practice.
B) The Physical Model instruments are a pain to get to oscillate, and coming up with stable and meaningful parameter values is required to get the models to work at all.
This set of C++ unit generators and instruments might help to diminish the scores of emails I get asking what to do with those block diagrams I put in my papers.
4) I wanted to try some new stuff with modal synthesis, and implement some classic FM patches as well.
5) I wanted to reimplement, and newly implement more of the intelligent and physical performer models I've talked about in some of my papers. But I wanted to do it in a portable way, and in such a way that I can hook up modules quickly. I also wanted to make these instruments connectable to such player objects, so folks like Brad Garton who really think a lot about the players can connect them to my instruments, a lot about which I think.
6) More rationalizations to follow . . .

View File

@@ -1,17 +0,0 @@
STK: A ToolKit of Audio Synthesis Classes and Instruments in C++
Version 3.0
By Perry R. Cook, 1995-99
and Gary P. Scavone, 1997-99.
Please read the file README.txt for more general STK information.
STK for Linux is currently using the OSS sound and MIDI API. The free version of OSS will probably work, though it doesn't work with as many soundcards as the commercial version (which costs about $20).
STK should compile without much trouble under Linux. Since all Linux distributions typically include the GNU makefile utilities, you should be able to use the default Makefile. Typing "make" will initiate the compilation process.
NOTE REGARDING PTHREADS:
The only issue which seems to crop up on different versions of Linux concerns threads. I am using the MIT pthreads API. Under RedHat Linux 4.x, I had to specifically include <pthread/mit/pthread.h> (the default pthread library didn't work). However, under RedHat Linux 5.0 and higher, the default works and the <pthread/mit/> path doesn't exist. I've decided to assume the default works. If you get errors with regard to pthreads when you compile, you'll have to search your system for the MIT pthread distribution and change the appropriate include statements in MIDIIO.cpp, MD2SKINI.cpp, and threads.cpp.

View File

@@ -1,11 +0,0 @@
STK: A ToolKit of Audio Synthesis Classes and Instruments in C++
Version 3.0
By Perry R. Cook, 1995-99
and Gary P. Scavone, 1997-99.
Please read the file README.txt for more general STK information.
It seems that SGI systems are not distributed with the GNU Makefile utilities. The default Make utility has very limited functionality, so your safest bet is to download the GNU Makefile utilities from the Internet and use STK's default Makefile. If this is not possible, try using Makefile.sgi (make -f Makefile.sgi).
Aside from the Makefile issues, STK should compile and run on SGI platforms without any problems.

View File

@@ -1,66 +0,0 @@
STK: A ToolKit of Audio Synthesis Classes and Instruments in C++
Version 3.0
By Perry R. Cook, 1995-99
and Gary P. Scavone, 1997-99.
Please read the file README.txt for more general STK information.
DirectX and WindowsNT Issues:
-----------------------------
The newly offered STK realtime sound input capabilities under Windoze are only supported using the DirectSoundCapture API. The latency is pretty horrendous, but what do you expect? Also, there is a good chance you don't have DirectSoundCapture support on your computer. You should download the DirectX 6.0 (or higher) runtime libraries from Microsoft's WWW site (http://www.microsoft.com/directx/download.asp) in order to run the pre-compiled STK executables for Windoze. HOWEVER, there is no DirectSoundCapture support for WindowsNT at this time ... you'll have to wait for Windows 2000. If you wish to compile STK under WindowsNT (without realtime audio input support), you'll have to uncomment the __WINMM_API_ flag (and comment out the __WINDS_API flag) in Object.h and recompile the source code.
Realtime sound output under Windoze is supported using either the DirectSound (dsound.lib) API or the old WinMM (winmm.lib) API. The DirectSound version appears to well out-perform the older API. All new versions of Win95/98/NT come with the DirectSound library, but early versions did not. If you have trouble running the distributed executables (compiled for DirectSound API), then you probably don't have DirectSound installed on your system. You can download the necessary DirectSound stuff from Microsoft's WWW pages (http://www.microsoft.com/directx/download.asp). If all else fails, you should be able to compile using the winmm.lib routines ... more latency, but at least it will work.
Realtime MIDI input is supported using the winmm.lib API.
Visual C++ workspaces have been created for the various STK projects. Everything has already been configured for you. The intermediate .obj files will be written to either the "Release" or "Debug" directories, but the executable files will be written to the main project directories (where they need to be for proper execution). If you should somehow lose or hose the VC++ workspace file (STK.dsw), then you will have to do a LOT of configuring to recreate it ... it's probably easier just to download the distribution again from our WWW sites. Anyway, for your benefit and mine, here is a list of things that need to be added to the various "Project Settings":
1. Under General: Set "Output files:" to <blank> (this will put the executable in the main project directory.
2. Under C/C++ > Code Generation: Set "Use run-time library:" to Multithreaded.
3. Under Link > General: Add winmm.lib, dsound.lib, and Wsock32.lib to the end of the Object/library modules list.
4. Add all the necessary files to the project.
NOTE: For some of my personal STK files, I've had trouble compiling in VC++ with the "Optimize Speed" optimization setting (in Project Settings -> C/C++ -> Optimizations:). The files compile, but don't work the way they should when executed. These same files, however, have worked when compiled with the "Default" optimization setting. I've heard that there are bugs with some of these optimization settings.
Remember that items 1-3 above need to be done for each project and for each configuration. There might be an easy way to make global changes, but I couldn't figure it out.
To use the Tcl/Tk GUIs, you will have to install Tcl/Tk. I got version 8.0 and it works very well (and installed easily). The distribution is available on the WWW and is free.
In order for socketing to work, it is necessary to have the TCP protocol installed on your computer. This can be done from the "Network" control panel.
Finally, to use it all -
PLAY SKINI SCOREFILES IN REALTIME:
syntmono Clarinet -r < scores/streetsf.ski
USE TCL/TK GUIs FOR REALTIME CONTROL:
1. Open a DOS console window and start syntmono (eg. syntmono Clarinet -r -is).
2. Double click on a Tcl/Tk file in TCLSpecs (eg. TCLPhys.tcl) from the Windows Explorer to start the GUI. Select the "communications" menu item and "Socket" and make the connection.
3. Start moving the sliders to control the instrument.
USE REALTIME MIDI INPUT FOR CONTROL:
1. Open a DOS console window and start syntmono (eg. syntmono Clarinet -r -is).
2. Open another DOS console window and start MD2SKINI in the following way:
MD2SKINI -s <optional hostname>
This assumes you already have MIDI setup correctly for your computer.
WINDOWS NT ONLY:
Realtime piping seems to work under WindowsNT in much the same way as on Unix platforms. Thus, it is possible to pipe realtime control data to syntmono under WindowsNT as well.

View File

@@ -1,123 +0,0 @@
STK: A ToolKit of Audio Synthesis Classes and Instruments in C++
Version 3.0
By Perry R. Cook, 1995-99
and Gary P. Scavone, 1997-99.
Please read the Legal and Ethical notes near the bottom of this document.
OVERVIEW:
STK is a set of audio signal processing C++ classes and instruments for music synthesis. You can use these classes to create programs which make cool sounds using a variety of synthesis techniques. This is not a terribly novel concept, except that STK is very portable (it's mostly platform-independent C and C++ code) AND it's completely user-extensible. So, the code you write using STK actually has some chance of working in another 5-10 years. STK currently runs on SGI (Irix), Linux, NeXTStep, and Windows computer platforms. Oh, and it's free for non-commercial use. The only parts of STK that are platform-dependent concern real-time sound and MIDI input and output ... but we've taken care of that for you. The interface for MIDI input and the simple Tcl/Tk graphical user interfaces (GUIs) provided is the same, so it's easy to voice and experiment in real time using either the GUIs or MIDI.
STK isn't one particular program. Rather, STK is a set of C++ classes that you can use to create your own programs. We've provided a few example applications that demonstrate some of the ways that you could use these classes. But if you have specific needs you will probably have to either modify the example programs or write a new program altogether. Further, the example programs don't have a fancy GUI wrapper. If you feel the need to have a "drag and drop" GUI, you probably don't want to use STK. Spending hundreds of hours making platform-dependent GUI code would go against one of the fundamental design goals of STK - platform independence. STK can generate simultaneous .snd, .wav, and .mat output soundfile formats (beside realtime sound output), so you can view your results using one of the numerous sound/signal analysis tools already available over the WWW (e.g. Snd, Cool Edit, Matlab). For those instances where a simple GUI with sliders and buttons is helpful, we use Tcl/Tk (which is freely distributed for all the STK supported platforms). A number of Tcl/Tk GUI scripts are distributed with the STK release.
SYSTEM REQUIREMENTS:
See the individual README's (eg. README-linux) for platform specific information and system requirements. In general, you will use either the provided Makefiles (Unix platforms) or the VC++ workspace files to compile the example programs. To use the Tcl/Tk GUIs, you will need Tcl/Tk version 8.0 or higher.
WHAT'S NEW:
STK has undergone several key revisions, changes, and additions since its last release in 1998. Despite being available in one form or another since 1996, we still consider STK to be alpha software. Thus, backward compatability has not been a priority. Please read the ReleaseNotes to see what has changed since the last release.
Realtime audio input capabilities have now been added to STK, though the behavior of such is very hardware dependent. Under Linux and Irix, audio input and output are possible with very low latency. Using the Windoze DirectSound API, minimum dependable output sound latency seems to be around 15 milliseconds, while input sound latency is on the order of several hundred milliseconds! It is also possible to generate simultaneous .snd, .wav, .raw, and .mat (Matlab MAT-file) output file types, as well as SKINI scorefiles using MD2SKINI. Finally, STK should compile with non-realtime functionality on any platform with a generic C++ compiler.
Socketing capabilities have been extended in this release to function under Unix platforms, as well as Windoze platforms. Further, the socket server thread has been updated to accept multiple simultaneous socket connections. Thus, it is now possible to have several different socket clients sending SKINI control messages to the server at the same time. Under Linux and Irix, it is also possible to pipe GUI messages through MD2SKINI, enabling both MIDI and GUI control via piping at the same time.
GETTING STARTED:
A number of example executables are provided with this distribution. The effects directory contains a program that demonstrates realtime duplex mode (simultaneous audio input and output) operation, as well as several simple delay-line based effects algorithms. The MUS151 directory contains a simple two-oscillator program that can be used to demonstrate psychoacoustic masking effects. The syntmono directory offers a program for monophonic STK instrument playback and manipulation. Syntmono is the primary STK synthesis server and is used to demonstrate all the current STK instruments. MD2SKINI is an executable (currently compiles from the syntmono project) which takes raw MIDI input, converts it to SKINI format, and outputs the result to stdout or any socket host and port ID. Control data (in the form of SKINI messages) can be fed to syntmono through three principal means - SKINI scorefiles, MD2SKINI output, and Tcl/Tk GUIs. A variety of SKINI scorefiles are distributed with STK and can be found in the "scores" directory of the syntmono project.
Unless you downloaded the distribution with precompiled Windoze binaries, it is necessary to first compile the sources. Under Linux or Irix, simply typing "make" in any of the particular project directories will begin the compilation process. If your Unix system does not have the GNU Makefile utilities, you will have to use one of the platform specific Makefiles (eg. make -f Makefile.sgi). To compile the projects under Windoze, you should use the VC++ project files provided with the STK distribution.
SYNTMONO:
Syntmono is the primary STK synthesis server and is used to demonstrate all the current STK instruments. Syntmono can take realtime control (SKINI) input via pipes or sockets, or it can be fed SKINI scorefile (non-realtime) input. Syntmono can output data in realtime, .wav, .snd, .mat (Matlab MAT-file), and/or .raw formats. Assuming you have successfully compiled the syntmono executable, a scorefile can be redirected to syntmono and the output heard in realtime in the following way:
syntmono Clarinet -r < scores/streetsf.ski
The "-r" flag specifies the realtime output option. Typing syntmono without arguments will provide a brief description of the instruments possible and the various input/output option flags. Tcl/Tk GUIs are provided in the "tcl" directory of each project, though you will have to install Tcl/Tk version 8.0 or higher on your system to use them (older versions of Tcl/Tk under Linux seem to be more forgiving than under IRIX). Realtime SKINI control data (via MD2SKINI or GUIs) can be piped to syntmono on Unix platforms and WinNT in the following way:
MD2SKINI | syntmono Clarinet -r -ip
or
wish < TCLSpecs/TCLPhys.tcl | syntmono Clarinet -r -ip
The "-ip" flag specifies piped realtime input. It is not possible to use realtime pipes under Windoze95/98, so socket communication must be used instead. For socket communication, it is necessary to first start the syntmono socket server using the "-is" flag (socketed realtime input). For the time being, a default (hardwired) socket port of 2001 is being used by syntmono. After syntmono is running (and waiting for a socket client connection), either MD2SKINI or a Tcl/Tk GUI can be started. When using the GUI, it is necessary to invoke the "communications" menu item and select "socket" to establish the connection. The same procedure is also possible on Unix platforms.
DISCLAIMER:
You probably already guessed this, but just to be sure, we don't guarantee anything works. :-) It's free ... what do you expect? If you find a bug, please let us know and we'll try to correct it. You can also make suggestions, but again, no guarantees. Send email to prc@cs.princeton.edu and gary@ccrma.stanford.edu.
LEGAL AND ETHICAL:
This software was designed and created to be made publicly available for free, primarily for academic purposes, so if you use it, pass it on with this documentation, and for free.
If you make a million dollars with it, give us some. If you make compositions with it, put us in the program notes.
Some of the concepts are covered by various patents, some known to us and likely others which are unknown. Many of the ones known to us are administered by the Stanford Office of Technology and Licensing.
The good news is that large hunks of the techniques used here are public domain. To avoid subtle legal issues, we'll not state what's freely useable here, but we'll try to note within the various classes where certain things are likely to be protected by patents.
FURTHER READING:
For more documentation on this ToolKit, the classes, etc., read the file HIERARCH.txt and the individual class definitions. Also check the platform specific README's for specific system requirements.
PERRY'S NOTES FROM THE ORIGINAL DISTRIBUTION:
This whole world was created with no particular hardware in mind. These examples are intended to be tutorial in nature, as a platform for the continuation of my research, and as a possible starting point for a software synthesis system. The basic motivation was to create the necessary unit generators to do the synthesis, processing, and control that I want to do and teach about. Little thought for optimization was given (see Object.cpp), and therefore improvements, especially speed enhancements, should be possible with these classes. It was written with some basic concepts in mind about how to let compilers optimize.
Your question at this point might be, "But Perry, with CMix, CMusic, CSound, CShells, CMonkeys, etc. already cluttering the landscape, why a new set of stupid C functions for music synthesis and processing?" The answers lie below.
1) I needed to port many of the things I've done
into something which is generic enough to port
further to different machines.
2) I really plan to document this stuff, so that
you don't have to be me to figure out what's
going on. (I'll probably be sorry I said this
in a couple of years, when even I can't figure
out what I was thinking.)
3) The classic difficulties most people have in
trying to implement physical models are:
A) They have trouble understanding the papers,
and/or in turning the theory into practice.
B) The Physical Model instruments are a pain to get
to oscillate, and coming up with stable and
meaningful parameter values is required to
get the models to work at all.
This set of C++ unit generators and instruments
might help to diminish the scores of emails I
get asking what to do with those block diagrams
I put in my papers.
4) I wanted to try some new stuff with modal synthesis,
and implement some classic FM patches as well.
5) I wanted to reimplement, and newly implement
more of the intelligent and physical performer
models I've talked about in some of my papers.
But I wanted to do it in a portable way, and in
such a way that I can hook up modules quickly.
I also wanted to make these instruments connectable
to such player objects, so folks like Brad Garton
who really think a lot about the players can connect
them to my instruments, a lot about which I think.
6) More rationalizations to follow . . .

View File

@@ -1,60 +0,0 @@
STK: A ToolKit of Audio Synthesis Classes and Instruments in C++
Release 3.0
By Perry R. Cook, 1995-99
and Gary P. Scavone, 1997-99
v3.0
- new #define flags for OS and realtime dependencies (this will probably cause problems for most everyone, but it was necessary to make future ports easier)
- fixed Linux MIDI input bug
- fixed MIDI status masking problem in Windows
- OS type defines now in Makefile
- new RAWWAVE_PATH define in Object.h
- syntmono pulled out to separate directory and cleaned up
- socketing capabilities under Unix, as well as Windoze
- multiple simultaneous socket client connections to STK servers now possible
- MD2SKINI now can merge MIDI and piped messages under Irix and Linux (for TCL->MD2SKINI->syntmono control)
- defined INT16 and INT32 types and fixed various WvIn and WvOut classes
- updated MatWvIn and MatWvOut for new MAT-file documentation from Matlab
- new demo GUI
- minor fixes to FM behavior
- added record/duplex capabilities to RTSoundIO (Linux, SGI, and Windoze)
- fixed bugs in WavWvOut and MatWvOut header specifications
- added RawWvOut class
- new WvIn class with RawWvIn, SndWvIn, WavWvIn, MatWvIn, and RTWvIn subclasses
- removed RawWave, RawShot, RawInterp, and RawLoop classes (supplanted by RawWvIn)
- multi-channel data support in WvIn and WvOut classes using MY_MULTI data type (pointer to MY_FLOAT) and the methods mtick() and mlastOutput()
- now writing to primary buffer under Windoze when allowed by hardware
- cleaned up Object.h a bit
- pulled various utility and thread functions out of syntmono.cpp (to aid readability of the code)
v2.02:
- 16 November 1998
- created RawWave abstract class, with subclasses of RawLoop (looping rawwave oscillator), RawShot (non-looping, non-interpolating rawwave player ... used to be RawWvIn), and RawInterp (looping or non-looping, interpolating rawwave player ... used to be RawWave).
- modified DrumSynt to correctly handle sample rates different than 22050 Hz.
- modified syntmono parsing vs. tick routine so that some ticking occurs between each message. When multiple messages are waiting to be processed, the time between message updates is inversely proportional to the number of messages in the buffer.
- fixed DirectSound playback bug in Win distribution. Sound was being played at 8-bit, 22 kHz in all cases. Playback is now 16-bit and dependent on SRATE.
- fixed bug in MD2SKINI which prevented some NoteOff statements from being output.
v2.01:
- 27 July 1998
- Corrected extraneous ^M line return characters that were incompatible with SGI.
v2.0:
- 20 July 1998
- The first true release by Gary, with unified capabilities across SGI, Linux, and Win platforms. See WWW pages (http://www-ccrma.stanford.edu/CCRMA/Software/STK/) for more info.
v1.1:
- More linux support and other changes that happened so long ago that I can't remember anymore. Never officially released.
v1.0:
- Linux support added with the help of Tim Stilson. Never officially released.
v0.8:
- One of (if not THE) original distributions for SGI, NeXTStep, and basic Win support. I think this came out in 1996.

View File

@@ -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());
}
*/

View File

@@ -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

View File

@@ -1,79 +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()
{
// Concatenate the STK RAWWAVE_PATH to the rawwave file
char file[128];
strcpy(file, RAWWAVE_PATH);
wave = new RawWvIn(strcat(file,"rawwaves/britestk.raw"), "oneshot");
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");
}
}

View File

@@ -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

View File

@@ -1,81 +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()
{
// Concatenate the STK RAWWAVE_PATH to the rawwave file
char file1[128];
char file2[128];
char file3[128];
char file4[128];
strcpy(file1, RAWWAVE_PATH);
strcpy(file2, RAWWAVE_PATH);
strcpy(file3, RAWWAVE_PATH);
strcpy(file4, RAWWAVE_PATH);
this->loadWaves(strcat(file1,"rawwaves/sinewave.raw"),
strcat(file2,"rawwaves/sinewave.raw"),
strcat(file3,"rawwaves/sinewave.raw"),
strcat(file4,"rawwaves/fwavblnk.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
}

View File

@@ -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

View File

@@ -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 * sizeof(MY_FLOAT));
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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -1,26 +0,0 @@
/***********************************************/
/* Simple Bow Table Object, after Smith */
/* by Perry R. Cook, 1995-96 */
/***********************************************/
#if !defined(__BowTabl_h)
#define __BowTabl_h
#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();
};
#endif

View File

@@ -1,166 +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;
// Concatenate the STK RAWWAVE_PATH to the rawwave file
char file[128];
strcpy(file, RAWWAVE_PATH);
vibr = new RawWvIn(strcat(file,"rawwaves/sinewave.raw"),"looping");
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");
}
}

View File

@@ -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 "RawWvIn.h"
#include "ADSR.h"
class Bowed : public Instrmnt
{
protected:
DLineL *neckDelay;
DLineL *bridgeDelay;
BowTabl *bowTabl;
OnePole *reflFilt;
BiQuad *bodyFilt;
RawWvIn *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

View File

@@ -1,318 +0,0 @@
/*********************************************/
/* Bowed Bar model */
/* by Georg Essl, 1999 */
/* For details refer to: */
/* G.Essl, P.R.Cook: "Banded Waveguides: */
/* Towards Physical Modelling of Bar */
/* Percussion Instruments", ICMC'99 */
/*********************************************/
#include "BowedBar.h"
#include "SKINI11.msg"
#include "Noise.h"
/* Number of banded waveguide modes */
int NR_MODES=4;
/* Contructor */
BowedBar :: BowedBar(MY_FLOAT lowestFreq)
{
long i;
pluck_ = 1;
modes[0] = (MY_FLOAT) 1.0;
modes[1] = (MY_FLOAT) 2.756;
modes[2] = (MY_FLOAT) 5.404;
modes[3] = (MY_FLOAT) 8.933;
for (i=0;i<4;i++) {
gains[i] = (MY_FLOAT) pow(0.9,(double) i);
}
bowTabl = new BowTabl;
adsr = new ADSR;
bandpass_ = new BiQuad[NR_MODES];
bowTabl->setSlope((MY_FLOAT) 3.0);
adsr->setAllTimes((MY_FLOAT) 0.02,(MY_FLOAT) 0.005,(MY_FLOAT) 0.9,(MY_FLOAT) 0.01);
freq = SRATE / 100;
length = 100;
bowPos = 0;
lastBowPos = 0;
for(i = 0; i<NR_MODES; i++)
{
delay[i].setDelay((int)(length/modes[i]));
delay[i].clear();
bandpass_[i].clear();
Zs[i][1] = 0.0;
Zs[i][2] = 0.0;
filtOut[i] = 0.0;
filtIn[i] = 0.0;
}
R = (MY_FLOAT) 0.97;
GAIN = (MY_FLOAT) 0.999;
slope = (MY_FLOAT) 3.0;
tuneBandPasses();
}
BowedBar :: ~BowedBar()
{
delete bowTabl;
delete adsr;
}
void BowedBar :: clear()
{
long i;
for(i = 0; i<NR_MODES; i++)
{
delay[i].clear();
bandpass_[i].clear();
Zs[i][1] = 0.0;
Zs[i][2] = 0.0;
filtOut[i] = 0.0;
filtIn[i] = 0.0;
}
}
void BowedBar :: setFreq(MY_FLOAT frequency)
{
int i;
freq = frequency;
if(freq > 1568.0) freq = 1568.0;
length = (int)(SRATE/freq);
NR_MODES = 4;
for(i = 0; i<NR_MODES; i++)
{
if((int)(length/modes[i]) > 4)
delay[i].setDelay((int)(length/modes[i]));
else {
NR_MODES = i;
break;
}
/* FIX THIS BETTER!!!!! */
delay[i].clear();
bandpass_[i].clear();
Zs[i][1] = 0.0;
Zs[i][2] = 0.0;
filtOut[i] = 0.0;
filtIn[i] = 0.0;
}
tuneBandPasses();
}
void BowedBar :: setStrikePosition(MY_FLOAT position)
{
MY_FLOAT temp2;
temp2 = position * PI;
gains[0] = fabs(sin(temp2 / 2) * pow(0.9,0));
gains[1] = fabs(sin(temp2) * pow(0.9,1));
gains[2] = fabs(sin(temp2 * 3 / 2) * pow(0.9,2));
gains[3] = fabs(sin(temp2 * 2) * pow(0.9,3));
}
void BowedBar :: tuneBandPasses()
{
long i;
for(i=0; i<NR_MODES; i++)
{
R = 1 - 6.28318530718 * freq * modes[i] / SRATE / 2.0;
bandpass_[i].setFreqAndReson(freq * modes[i], R);
bandpass_[i].setEqualGainZeroes();
bandpass_[i].setGain((1.0-R*R)/2.0);
filtGain[i] = (MY_FLOAT) (1.0 - (R*R))/2.0;
coeffs[i][1] = -R * R;
coeffs[i][0] = 2.0 * R * cos(6.28318530718 * freq * modes[i] / SRATE);
delay[i].clear(); //(rand()) - 16384;
}
}
void BowedBar :: startBowing(MY_FLOAT amplitude, MY_FLOAT rate)
{
adsr->setRate(rate);
adsr->keyOn();
maxVelocity = (MY_FLOAT) 0.03 + ((MY_FLOAT) 0.2 * amplitude);
maxVelocity = (MY_FLOAT) 0.03 + ((MY_FLOAT) 0.5 * amplitude);
}
void BowedBar :: stopBowing(MY_FLOAT rate)
{
adsr->setRate(rate);
adsr->keyOff();
}
void BowedBar :: pluck(MY_FLOAT amplitude)
{
long i,j;
int pluckLen;
MY_FLOAT temp;
Noise noise;
pluckLen = (int)(length/modes[NR_MODES-1]);
for (j=1;j<pluckLen/2;j++) {
temp = amplitude*2.0*noise.tick();
for(i=0; i<NR_MODES; i++)
delay[i].tick(temp*j/pluckLen*gains[i]);
}
for (j=pluckLen/2;j>0;j--) {
temp = amplitude*2.0*noise.tick();
for(i=0; i<NR_MODES; i++)
delay[i].tick(temp*j/pluckLen*gains[i]);
}
}
void BowedBar :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
{
if(!pluck_) {
for(int i=0; i<NR_MODES ; i++)
bandpass_[i].clear();
this->startBowing(amp,amp * (MY_FLOAT) 0.001);
this->setFreq(freq);
pluck_ = 0;
#if defined(_debug_)
printf("BowedBar : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
#endif
}
else {
for(int i=0; i<NR_MODES ; i++)
bandpass_[i].clear();
this->setFreq(freq);
this->pluck(amp);
pluck_ = 1;
}
}
void BowedBar :: noteOff(MY_FLOAT amp)
{
if(!pluck_) {
this->stopBowing(((MY_FLOAT) 1.0 - amp) * (MY_FLOAT) 0.005);
}
#if defined(_debug_)
printf("BowedBar : NoteOff: Amp=%lf\n",amp);
#endif
}
MY_FLOAT BowedBar :: tick()
{
long k;
MY_FLOAT input;
MY_FLOAT data;
data = 0.0;
input = 0.0;
if(integration_const_ == 0.0)
velinput = 0.0;
else
velinput = integration_const_ * velinput;
for(k=0; k<NR_MODES; k++)
{
velinput += GAIN * delay[k].lastOut();
}
if(trackVel) {
bowvel *= 0.9995;
bowvel += bowTarg;
bowTarg *= 0.995;
}
else
{
bowvel = adsr->tick()*maxVelocity;
}
if(pluck_)
{
input = 0.0;
}
else
{
input = bowvel - velinput;
input = input * bowTabl->lookup(input);
input = input/(MY_FLOAT)NR_MODES;
}
for(k=0; k<NR_MODES; k++)
{
bandpass_[k].tick(input*gains[k] + GAIN * delay[k].lastOut());
delay[k].tick(bandpass_[k].lastOut());
data += bandpass_[k].lastOut();
}
lastOutput = data * 4.0;
return lastOutput;
}
void BowedBar :: controlChange(int number, MY_FLOAT value)
{
#if defined(_debug_)
printf("BowedBar : ControlChange: Number=%i Value=%f\n",number,value);
#endif
if (number == __SK_BowPressure_)
{
bowTabl->setSlope((MY_FLOAT) 10.0 - ((MY_FLOAT) 9.0 * value * NORM_7));
slope = (MY_FLOAT) 10.0 - ((MY_FLOAT) 9.0 * value * NORM_7);
}
else if (number == __SK_BowPosition_)
{
this->setStrikePosition(value*NORM_7);
}
else if (number == __SK_Balance_) {
bowPos = value * NORM_7;
bowTarg += 0.02 * (bowPos - lastBowPos);
lastBowPos = bowPos;
adsr->setTarget(bowPos);
}
else if (number == __SK_AfterTouch_Cont_)
{
bowPos = value * NORM_7;
bowTarg += 0.02 * (bowPos - lastBowPos);
lastBowPos = bowPos;
adsr->setTarget(bowPos);
}
else if (number == __SK_ModWheel_)
{
GAIN = 0.809 + (0.2 * (value * NORM_7));
}
else if(number == __SK_ModFrequency_)
{
integration_const_ = value * NORM_7;
}
else if(number == __SK_Sustain_) {
if(value < 65)
pluck_ = 1;
else
pluck_ = 0;
}
else if(number == __SK_Portamento_) {
if(value < 65)
trackVel = 0;
else
trackVel = 1;
}
else {
printf("BowedBar : Undefined Control Number!!\n");
}
}

View File

@@ -1,62 +0,0 @@
/*********************************************/
/* Bowed Bar model */
/* by Georg Essl, 1999 */
/* For details refer to: */
/* G.Essl, P.R.Cook: "Banded Waveguides: */
/* Towards Physical Modelling of Bar */
/* Percussion Instruments", ICMC'99 */
/*********************************************/
#if !defined(__BowedBar_h)
#define __BowedBar_h
#include "Instrmnt.h"
#include "DLineN.h"
#include "BowTabl.h"
#include "ADSR.h"
#include "BiQuad.h"
class BowedBar : public Instrmnt
{
protected:
BowTabl *bowTabl;
ADSR *adsr;
BiQuad *bandpass_;
MY_FLOAT maxVelocity;
MY_FLOAT modes[4];
DLineN delay[4];
float Zs[4][2];
MY_FLOAT coeffs[4][2];
float filtOut[4];
float filtIn[4];
MY_FLOAT filtGain[4];
MY_FLOAT freq;
int length;
MY_FLOAT R;
MY_FLOAT GAIN;
MY_FLOAT gains[4];
MY_FLOAT slope;
MY_FLOAT velinput;
MY_FLOAT integration_const_;
int trackVel;
MY_FLOAT bowvel, bowTarg, bowPos, lastBowPos;
int pluck_;
public:
BowedBar(MY_FLOAT lowestFreq=16);
~BowedBar();
void tuneBandPasses();
void clear();
void startBowing(MY_FLOAT amplitude,MY_FLOAT rate);
void stopBowing(MY_FLOAT rate);
void pluck(MY_FLOAT amp);
void setStrikePosition(MY_FLOAT position);
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
virtual void noteOff(MY_FLOAT amp);
virtual void setFreq(MY_FLOAT frequency);
virtual void controlChange(int number, MY_FLOAT value);
virtual MY_FLOAT tick();
};
#endif

View File

@@ -1,135 +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);
// Concatenate the STK RAWWAVE_PATH to the rawwave file
char file[128];
strcpy(file, RAWWAVE_PATH);
vibr = new RawWvIn(strcat(file,"rawwaves/sinewave.raw"),"looping");
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");
}
}

View File

@@ -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 "RawWvIn.h"
class Brass: public Instrmnt
{
protected:
DLineA *delayLine;
LipFilt *lipFilter;
DCBlock *dcBlock;
ADSR *adsr;
RawWvIn *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

View File

@@ -1,130 +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;
// Concatenate the STK RAWWAVE_PATH to the rawwave file
char file[128];
strcpy(file, RAWWAVE_PATH);
vibr = new RawWvIn(strcat(file,"rawwaves/sinewave.raw"),"looping");
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");
}
}

View File

@@ -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 "RawWvIn.h"
class Clarinet : public Instrmnt
{
protected:
DLineL *delayLine;
ReedTabl *reedTable;
OneZero *filter;
Envelope *envelope;
Noise *noise;
RawWvIn *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

View File

@@ -1,40 +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(sizeof(MY_FLOAT));
outputs = (MY_FLOAT *) malloc(sizeof(MY_FLOAT));
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;
}

View File

@@ -1,26 +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

View File

@@ -1,107 +0,0 @@
/*******************************************/
/* AllPass Interpolating Delay Line */
/* Object by Perry R. Cook 1995-96. */
/* Revised by Gary P. Scavone, 1999. */
/* */
/* 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 i;
// Default max delay length set to 2047.
length = 2048;
inputs = (MY_FLOAT *) malloc(length * sizeof(MY_FLOAT));
for (i=0;i<length;i++) inputs[i] = (MY_FLOAT) 0;
this->clear();
inPoint = 0;
outPoint = length >> 1;
}
DLineA :: DLineA(long max_length)
{
long i;
length = max_length;
inputs = (MY_FLOAT *) malloc(length * sizeof(MY_FLOAT));
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 outPointer;
if (lag > length-1) { // if delay is too big,
printf("DLineA: Delay length too big.\n");
printf("Setting to maximum length of %ld.\n",length-1);
outPointer = inPoint - 18.0; // force delay to max_length
}
else if (lag < 0.1) {
printf("DLineA: Delays < 0.1 not possible with current structure.\n");
printf("Setting delay length to 0.1.\n");
outPointer = inPoint + 0.8999999999;
}
else
outPointer = inPoint - lag + 1.0; // outPoint chases inpoint
if (outPointer < 0)
outPointer += length; // modulo table length
outPoint = (long) outPointer; // Integer part of delay
alpha = 1.0 + outPoint - outPointer; // fractional part of delay
if (alpha == 0.0) { // exact integer delay
outPoint -= 1;
if (outPoint < 0) outPoint += length;
}
if (alpha<0.1) { // Hack to avoid pole/zero
outPoint += 1; // cancellation. Keeps allpass
if (outPoint >= length) outPoint -= length;
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
}

View File

@@ -1,43 +0,0 @@
/*******************************************/
/* AllPass Interpolating Delay Line */
/* Object by Perry R. Cook 1995-96. */
/* Revised by Gary P. Scavone, 1999. */
/* */
/* 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();
DLineA(long max_length);
~DLineA();
void clear();
void setDelay(MY_FLOAT length);
MY_FLOAT tick(MY_FLOAT sample);
};
#endif

View File

@@ -1,77 +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()
{
// Default max delay length set to 2047.
length = 2048;
inputs = (MY_FLOAT *) malloc(length * sizeof(MY_FLOAT));
this->clear();
inPoint = 0;
outPoint = length >> 1;
}
DLineL :: DLineL(long max_length)
{
length = max_length;
inputs = (MY_FLOAT *) malloc(length * sizeof(MY_FLOAT));
this->clear();
inPoint = 0;
outPoint = 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 outPointer;
if (lag > length-1) { // if delay is too big,
printf("DLineL: Delay length too big.\n");
printf("Setting to maximum length of %ld.\n",length-1);
outPointer = inPoint + 1; // force delay to max_length
}
else
outPointer = inPoint - lag; // read chases write
while (outPointer<0)
outPointer += length; // modulo maximum length
outPoint = (long) outPointer; // integer part
alpha = outPointer - 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;
}

View File

@@ -1,34 +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();
DLineL(long max_length);
~DLineL();
void clear();
void setDelay(MY_FLOAT length);
MY_FLOAT tick(MY_FLOAT sample);
};
#endif

View File

@@ -1,70 +0,0 @@
/*******************************************/
/* Non-Interpolating Delay Line */
/* Object by Perry R. Cook 1995-96. */
/* Revised by Gary Scavone, 1999. */
/* */
/* This one uses either a delay line of */
/* maximum length specified on creation */
/* or a default length of 2048 samples. */
/* A non-interpolating delay line is */
/* typically used in non-time varying */
/* (reverb) applications. */
/*******************************************/
#include "DLineN.h"
DLineN :: DLineN()
{
// Default max delay length set to 2047.
length = 2048;
inputs = (MY_FLOAT *) malloc(length * sizeof(MY_FLOAT));
this->clear();
inPoint = 0;
outPoint = length >> 1;
}
DLineN :: DLineN(long max_length)
{
// Writing before reading allows delays from 0 to length-1.
// Thus, if we want to allow a delay of max_length, we need
// a delay-line of length = max_length+1.
length = max_length+1;
inputs = (MY_FLOAT *) malloc(length * sizeof(MY_FLOAT));
this->clear();
inPoint = 0;
outPoint = length >> 1;
}
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)
{
if (lag > length-1) { // if delay is too big,
printf("DLineN: Delay length too big ... setting to maximum length of %ld.\n",length-1);
outPoint = inPoint + 1; // force delay to max_length
}
else
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++]; // Read out next value
if (outPoint>=length) // Check for end condition
outPoint -= length;
return lastOutput;
}

View File

@@ -1,35 +0,0 @@
/*******************************************/
/* Non-Interpolating Delay Line */
/* Object by Perry R. Cook 1995-96. */
/* Revised by Gary Scavone, 1999. */
/* */
/* This one uses either a delay line of */
/* maximum length specified on creation */
/* or a default length of 2048 samples. */
/* A non-interpolating delay line is */
/* typically used in non-time varying */
/* (reverb) applications. */
/*******************************************/
#if !defined(__DLineN_h)
#define __DLineN_h
#include "Filter.h"
class DLineN : public Filter
{
protected:
long inPoint;
long outPoint;
long length;
public:
DLineN();
DLineN(long max_length);
~DLineN();
void clear();
void setDelay(MY_FLOAT length);
MY_FLOAT tick(MY_FLOAT sample);
};
#endif

View File

@@ -1,184 +0,0 @@
/*******************************************/
/* Master Class for Drum Synthesizer */
/* by Perry R. Cook, 1995-96 */
/* */
/* This instrument contains a bunch of */
/* RawWvIn 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 */
/* no interpolation is used. Otherwise, */
/* the rawwave data is appropriately */
/* interpolated for the current SRATE. */
/* You can specify the maximum Polyphony */
/* (maximum number of simultaneous voices)*/
/* in a #define in the .h file. */
/* */
/* Modified for RawWvIn class */
/* by Gary P. Scavone (4/99) */
/*******************************************/
#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];
RawWvIn *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 */
// Concatenate the STK RAWWAVE_PATH to the rawwave file
strcpy(tempString, RAWWAVE_PATH);
strcat(tempString,"rawwaves/");
strcat(tempString,waveNames[genMIDIMap[noteNum]]);
waves[numSounding-1] = new RawWvIn(tempString, "oneshot");
if (SRATE != 22050) {
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
}
void DrumSynt :: noteOff(MY_FLOAT amp)
{ /* Set all sounding wave filter gains low */
int i = 0;
while(i<numSounding) {
filters[i]->setGain(amp*0.01);
i++;
}
}
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;
}

View File

@@ -1,47 +0,0 @@
/*******************************************/
/* Master Class for Drum Synthesizer */
/* by Perry R. Cook, 1995-96 */
/* */
/* This instrument contains a bunch of */
/* RawWvIn 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 */
/* no interpolation is used. Otherwise, */
/* the rawwave data is appropriately */
/* interpolated for the current SRATE. */
/* You can specify the maximum Polyphony */
/* (maximum number of simultaneous voices)*/
/* in a #define in the .h file. */
/* */
/* Modified for RawWvIn class */
/* by Gary P. Scavone (4/99) */
/*******************************************/
#if !defined(__DrumSynt_h)
#define __DrumSynt_h
#include "Instrmnt.h"
#include "RawWvIn.h"
#include "OnePole.h"
#define DRUM_NUMWAVES 11
#define DRUM_POLYPHONY 4
class DrumSynt : public Instrmnt
{
protected:
RawWvIn *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);
void noteOff(MY_FLOAT amp);
virtual MY_FLOAT tick();
};
#endif

View File

@@ -1,122 +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());
}
*/

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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)
{
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -1,184 +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;
// Concatenate the STK RAWWAVE_PATH to the rawwave file
char file[128];
strcpy(file, RAWWAVE_PATH);
vibWave = new RawWvIn(strcat(file,"rawwaves/sinewave.raw"),"looping");
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 RawWvIn(wave1,"looping");
waves[1] = new RawWvIn(wave2,"looping");
waves[2] = new RawWvIn(wave3,"looping");
waves[3] = new RawWvIn(wave4,"looping");
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_) /* Control Change 2 */
this->setControl1(value * NORM_7);
else if (number == __SK_FootControl_) /* Control Change 4 */
this->setControl2(value * NORM_7);
else if (number == __SK_ModFrequency_) /* Control Change 11 */
this->setModulationSpeed(value * NORM_7 * (MY_FLOAT) 12.0); /* 0 to 12 Hz */
else if (number == __SK_ModWheel_) /* Control Change 1 */
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");
}
}

View File

@@ -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 "RawWvIn.h"
#include "TwoZero.h"
class FM4Op : public Instrmnt
{
protected:
ADSR *adsr[4];
RawWvIn *waves[4];
RawWvIn *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

View File

@@ -1,136 +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()
{
// Concatenate the STK RAWWAVE_PATH to the rawwave file
char file1[128];
char file2[128];
char file3[128];
char file4[128];
strcpy(file1, RAWWAVE_PATH);
strcpy(file2, RAWWAVE_PATH);
strcpy(file3, RAWWAVE_PATH);
strcpy(file4, RAWWAVE_PATH);
this->loadWaves(strcat(file1,"rawwaves/sinewave.raw"),
strcat(file2,"rawwaves/sinewave.raw"),
strcat(file3,"rawwaves/sinewave.raw"),
strcat(file4,"rawwaves/fwavblnk.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 < 32) {
tempi2 = currentVowel;
temp2 = (MY_FLOAT) 0.9;
}
else if (currentVowel < 64) {
tempi2 = currentVowel - 32;
temp2 = (MY_FLOAT) 1.0;
}
else if (currentVowel < 96) {
tempi2 = currentVowel - 64;
temp2 = (MY_FLOAT) 1.1;
}
else if (currentVowel <= 128) {
tempi2 = currentVowel - 96;
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;
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");
}
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -1,178 +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;
// Concatenate the STK RAWWAVE_PATH to the rawwave file
char file[128];
strcpy(file, RAWWAVE_PATH);
vibr = new RawWvIn(strcat(file,"rawwaves/sinewave.raw"),"looping");
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();
}
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");
}
}

View File

@@ -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 "RawWvIn.h"
class Flute : public Instrmnt
{
protected:
DLineL *jetDelay;
DLineL *boreDelay;
JetTabl *jetTable;
OnePole *filter;
DCBlock *dcBlock;
Noise *noise;
ADSR *adsr;
RawWvIn *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

View File

@@ -1,139 +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 * sizeof(MY_FLOAT));
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;
}

View File

@@ -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

View File

@@ -1,68 +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()
{
char file1[128];
char file2[128];
char file3[128];
char file4[128];
strcpy(file1, RAWWAVE_PATH);
strcpy(file2, RAWWAVE_PATH);
strcpy(file3, RAWWAVE_PATH);
strcpy(file4, RAWWAVE_PATH);
this->loadWaves(strcat(file1,"rawwaves/sinewave.raw"),
strcat(file2,"rawwaves/sinewave.raw"),
strcat(file3,"rawwaves/sinewave.raw"),
strcat(file4,"rawwaves/fwavblnk.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
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -1,26 +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. */
/**********************************************/
#if !defined(__JetTabl_h)
#define __JetTabl_h
#include "Object.h"
class JetTabl : public Object
{
protected:
MY_FLOAT lastOutput;
public:
JetTabl();
~JetTabl();
MY_FLOAT lookup(MY_FLOAT deltaP);
MY_FLOAT lastOut();
};
#endif

View File

@@ -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;
}

View File

@@ -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();
};

View File

@@ -1,411 +0,0 @@
/*******************************************/
/* Simple Realtime MIDI to SKINI Parser */
/* Gary P. Scavone, February 1998. */
/* Revised for sockets, May & June 1998. */
/* SKINI/MIDI merge added August 1999. */
/* */
/* This object takes MIDI from the input */
/* stream (via the MIDIIO class), */
/* parses it, and turns it into SKINI */
/* messages. */
/*******************************************/
#include "MIDIIO.h"
#include "SKINI11.msg"
#if defined(__STK_REALTIME_)
int outAHere = 0;
// Do OS dependent declarations and includes
#if defined(__OS_IRIX_)
#include <sys/types.h>
#include <sys/prctl.h>
#include <signal.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
pid_t exit_thread;
#elif defined(__OS_Linux_)
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
pthread_t exit_thread;
#elif defined(__OS_Win_)
#include <process.h>
#include <winsock.h>
unsigned long exit_thread;
#endif
// The thread function definition protocols are slightly
// different under Irix, Linux, and Windoze.
#if defined(__OS_IRIX_)
void monitorStdin(void *)
#elif defined(__OS_Linux_)
void *monitorStdin(void *)
#elif defined(__OS_Win_)
void monitorStdin(void *)
#endif
{
char inputString[128];
printf("Type 'Exit<cr>' to quit.\n");
while (!outAHere) {
fgets(inputString, 128, stdin);
if (inputString[3] == 't' && inputString[1] == 'x'
&& inputString[2] == 'i' && inputString[0] == 'E') {
outAHere = 1;
}
else {
printf(inputString);
fflush(stdout);
}
}
}
void errorf(void) {
printf("useage: MD2SKINI <flag(s)>\n\n");
printf(" With no arguments, MD2SKINI converts MIDI input to SKINI\n");
printf(" format and sends the output directly to stdout.\n");
printf(" With flag = -s <hostname>, the output is sent over a socket\n");
printf(" connection to the optional hostname (default = localhost).\n");
printf(" With flag = -f <filename>, the output stream is simultaneously\n");
printf(" written to the file specified by the optional <filename>\n");
printf(" (default = test.ski).\n\n");
exit(0);
}
void main(int argc,char *argv[])
{
long j, i = 1;
MY_FLOAT byte2, byte3;
int channel;
int firstMessage = 1;
int writeFileOut = 0;
FILE *fileOut;
MIDIIO *controller;
char hostName[256];
char fileName[256];
int useSocket = 0;
int theSocket;
struct sockaddr_in saServer;
if (argc>5) {
errorf();
}
// Parse the command-line arguments.
while (i < argc) {
if (argv[i][0] == '-') {
switch(argv[i][1]) {
case 's':
if ((i+1 < argc) && argv[i+1][0] != '-') {
i++;
strcpy(hostName,argv[i]);
}
else strcpy(hostName,"localhost");
useSocket = 1;
break;
case 'f':
if ((i+1 < argc) && argv[i+1][0] != '-') {
i++;
strcpy(fileName,argv[i]);
if (strstr(fileName,".ski") == NULL) strcat(fileName,".ski");
}
else strcpy(fileName,"test.ski");
fileOut = fopen(fileName,"wb");
writeFileOut = 1;
break;
default:
errorf();
break;
}
}
else errorf();
i++;
}
MY_FLOAT dt=0.0;
controller = new MIDIIO();
// If using sockets, setup the client socket
if (useSocket) {
#if defined(__OS_Win_) // Stupid Windoze only stuff
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD(1,1);
WSAStartup(wVersionRequested, &wsaData);
if (wsaData.wVersion != wVersionRequested) {
fprintf(stderr,"\n Wrong Windoze socket library version!\n");
exit(0);
}
#endif
// Create the client-side socket
theSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (theSocket < 0) {
fprintf(stderr,"Couldn't create socket ... aborting!\n");
exit(0);
}
struct hostent *hostp;
if ((hostp = gethostbyname(hostName)) == 0) {
fprintf(stderr,"%s: unknown host ... aborting!\n", hostName);
exit(0);
}
// Fill in the address structure
saServer.sin_family = AF_INET;
memcpy((void *)&saServer.sin_addr, hostp->h_addr, hostp->h_length);
saServer.sin_port = htons(2001); // Port number
// Connect to the server
if(connect(theSocket, (struct sockaddr *)&saServer, sizeof(saServer)) < 0) {
fprintf(stderr,"Socket connect failed ... aborting!\n");
#if defined(__OS_Win_)
closesocket(theSocket);
WSACleanup();
#else
close(theSocket);
#endif
exit(0);
}
}
// Setup the exit thread.
#if defined(__OS_IRIX_)
exit_thread = sproc(monitorStdin, PR_SALL);
if (exit_thread == -1) {
fprintf(stderr, "Unable to create exit thread ... aborting.\n");
exit(0);
}
#elif defined(__OS_Linux_)
int err = 0;
err = pthread_create(&exit_thread, NULL, monitorStdin, NULL);
if (err) {
fprintf(stderr, "Unable to create exit thread ... aborting.\n");
exit(0);
}
#elif defined(__OS_Win_)
exit_thread = _beginthread(monitorStdin, 0, NULL);
if (exit_thread == -1) {
fprintf(stderr, "Unable to create exit thread ... aborting.\n");
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) {
fprintf(fileOut,"NoteOff\t\t%.3f %d %.1f %.1f\n",dt,channel,byte2,64.0);
}
} 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 (useSocket) {
if (send(theSocket, s, strlen(s), 0) < 0) {
fprintf(stderr,"Socket connection failed ... aborting.\n");
#if defined(__OS_Win_)
closesocket(theSocket);
WSACleanup();
#else
close(theSocket);
#endif
outAHere = 1;
exit(0);
}
}
else {
printf("%s", s);
fflush(stdout);
}
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 (useSocket) {
send(theSocket, s, strlen(s), 0);
#if defined(__OS_Win_)
closesocket(theSocket);
WSACleanup();
#else
close(theSocket);
#endif
}
else {
printf("%s", s);
fflush(stdout);
}
if (writeFileOut) {
printf("Wrote SKINI output to file %s.\n", fileName);
fclose(fileOut);
}
delete controller;
}
#endif

View File

@@ -1,582 +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"
#if defined(__STK_REALTIME_)
#define MIDI_BUFFER_SIZE 1024
int writeOffset;
int readOffset;
#if defined(__OS_IRIX_)
/*************************************/
/* SGI MIDI INPUT */
/*************************************/
#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(__OSS_API_)
/*************************************/
/* OSS MIDI INPUT */
/*************************************/
#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);
}
if (n == 4) { /* ignore reads returning less than 4 bytes */
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()
{
pthread_cancel(midi_input_thread);
if (_seqfd != 0) close(_seqfd);
delete [] midiBuffer;
}
int MIDIIO::nextMessage()
{
MIDIMESSAGE lastEvent;
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(__OS_Win_)
/*************************************/
/* Windoze MIDI INPUT */
/*************************************/
#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);
status &= 0xf0; // Clear lower byte of status
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;
}
#endif

View File

@@ -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(__OS_Win_)
#include <windows.h>
#include <mmsystem.h>
static void CALLBACK midiInputCallback( HMIDIOUT hmin, UINT inputStatus,
DWORD instancePtr, DWORD midiMessage, DWORD timestamp);
#endif
#endif

View File

@@ -1,152 +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)
{
// Concatenate the STK RAWWAVE_PATH to the rawwave file
char temp[128];
strcpy(temp, RAWWAVE_PATH);
soundfile[0] = new RawWvIn(strcat(temp,"rawwaves/mand1.raw"),"oneshot");
strcpy(temp, RAWWAVE_PATH);
soundfile[1] = new RawWvIn(strcat(temp,"rawwaves/mand2.raw"),"oneshot");
strcpy(temp, RAWWAVE_PATH);
soundfile[2] = new RawWvIn(strcat(temp,"rawwaves/mand3.raw"),"oneshot");
strcpy(temp, RAWWAVE_PATH);
soundfile[3] = new RawWvIn(strcat(temp,"rawwaves/mand4.raw"),"oneshot");
strcpy(temp, RAWWAVE_PATH);
soundfile[4] = new RawWvIn(strcat(temp,"rawwaves/mand5.raw"),"oneshot");
strcpy(temp, RAWWAVE_PATH);
soundfile[5] = new RawWvIn(strcat(temp,"rawwaves/mand6.raw"),"oneshot");
strcpy(temp, RAWWAVE_PATH);
soundfile[6] = new RawWvIn(strcat(temp,"rawwaves/mand7.raw"),"oneshot");
strcpy(temp, RAWWAVE_PATH);
soundfile[7] = new RawWvIn(strcat(temp,"rawwaves/mand8.raw"),"oneshot");
strcpy(temp, RAWWAVE_PATH);
soundfile[8] = new RawWvIn(strcat(temp,"rawwaves/mand9.raw"),"oneshot");
strcpy(temp, RAWWAVE_PATH);
soundfile[9] = new RawWvIn(strcat(temp,"rawwaves/mand10.raw"),"oneshot");
strcpy(temp, RAWWAVE_PATH);
soundfile[10] = new RawWvIn(strcat(temp,"rawwaves/mand11.raw"),"oneshot");
strcpy(temp, RAWWAVE_PATH);
soundfile[11] = new RawWvIn(strcat(temp,"rawwaves/mand12.raw"),"oneshot");
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)));
}
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);
}
}

View File

@@ -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 "RawWvIn.h"
class Mandolin : public Plucked2
{
protected:
RawWvIn *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

View File

@@ -1,116 +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()
{
// Concatenate the STK RAWWAVE_PATH to the rawwave file
char file[128];
strcpy(file, RAWWAVE_PATH);
wave = new RawWvIn(strcat(file,"rawwaves/marmstk1.raw"),"oneshot");
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();
}

View File

@@ -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

View File

@@ -1,178 +0,0 @@
/*******************************************/
/* MatWvIn Input Class, */
/* by Gary P. Scavone, 1999 */
/* */
/* This object inherits from WvIn and is */
/* used to open Matlab MAT-file data */
/* (doubles) files for playback. In */
/* order for this class to work, the */
/* MAT-file must contain a single array */
/* (matrix) of double-precision floating */
/* point values (can be multi-channel). */
/* It does not work for any other data */
/* formats. */
/* */
/* MAT-file data is either big- or */
/* little-endian, which can be determined */
/* from the header. */
/*******************************************/
#include "MatWvIn.h"
#include "swapstuf.h"
MatWvIn :: MatWvIn(char *fileName, char *mode)
{
extern double SwapDouble(double);
// Open the file and get header info
FILE *fd;
fd = fopen(fileName,"rb");
if (!fd) {
printf("Couldn't open or find MAT-file %s !!!\n",fileName);
exit(0);
}
// Make sure this is a version 5 MAT-file format and find its endian-ness
char head[4];
fseek(fd,0,SEEK_SET);
fread(&head,4,1,fd); // If any of the first 4 characters of the header = 0,
if (strstr(head,"0")) { // then this is a Version 4 MAT-file.
printf("This looks like a Version 4 MAT-file. I don't support\n");
printf("that at the moment, but you can add the code to MatWvIn if\n");
printf("you really need it.\n");
exit(0);
}
char mi[2];
int swap = 0;
fseek(fd,126,SEEK_SET); // Locate "M" and "I" characters in header
fread(&mi,2,1,fd);
#ifdef __LITTLE_ENDIAN__
if (!strncmp(mi,"MI",2)) {
swap = 1;
} else if (strncmp(mi,"IM",2)) {
printf("This doesn't appear to be a MAT-file %s !!!\n",fileName);
exit(0);
}
#else
if (!strncmp(mi,"IM",2)) {
swap = 1;
} else if (strncmp(mi,"MI",2)) {
printf("This doesn't appear to be a MAT-file %s !!!\n",fileName);
exit(0);
}
#endif
// Check the data element type
INT32 datatype;
fread(&datatype,4,1,fd);
if (swap) datatype = SwapINT32(datatype);
if (datatype != 14) {
printf("I'm expecting a single array (or matrix) data element.\n");
printf("This doesn't appear to be the case with your data. Sorry!\n");
exit(0);
}
// Check the array data type
INT32 tmp;
INT32 size;
fseek(fd,168,SEEK_SET);
fread(&tmp,4,1,fd);
if (swap) tmp = SwapINT32(tmp);
if (tmp == 1) { // array name > 4 characters
fread(&tmp,4,1,fd); // get array name length
if (swap) tmp = SwapINT32(tmp);
size = (INT32) ceil((float)tmp/8);
fseek(fd,size*8,SEEK_CUR); // jump over array name
}
else { // array name <= 4 characters, compressed data element
fseek(fd,4,SEEK_CUR);
}
fread(&tmp,4,1,fd);
if (swap) tmp = SwapINT32(tmp);
if (tmp != 9) {
printf("I'm expecting the array data to be in double precision\n");
printf("floating-point format. This doesn't appear to be the case\n");
printf("with your data. Sorry!\n");
exit(0);
}
// Get number of rows from the header
INT32 rows;
fseek(fd,160,SEEK_SET);
fread(&rows,4,1,fd); // rows
if (swap) rows = SwapINT32(rows);
// Get number of columns from the header
INT32 columns;
fread(&columns,4,1,fd); // columns
if (swap) columns = SwapINT32(columns);
// Make channels = smaller of rows or columns
if (rows < columns) {
channels = rows;
length = columns;
}
else {
channels = columns;
length = rows;
}
data = (MY_FLOAT *) new MY_FLOAT[(length+1)*channels];
// Move read pointer to the data in the file
INT32 headsize;
fseek(fd,132,SEEK_SET);
fread(&headsize,4,1,fd); // file size from 132nd byte
if (swap) headsize = SwapINT32(headsize);
headsize -= length * 8 * channels;
fseek(fd,headsize,SEEK_CUR);
// Read samples into data[]
long i = 0;
double temp;
if (channels == rows) {
while (fread(&temp,8,1,fd)) {
if (swap) temp = SwapDouble(temp);
data[i++] = (MY_FLOAT) temp;
}
} else {
long j = 0;
while (fread(&temp,8,1,fd)) {
if (swap) temp = SwapDouble(temp);
data[channels*i+j] = (MY_FLOAT) temp;
i++;
if (!(i<length)) {
i = 0;
j++;
}
}
}
fclose(fd);
// Setup for looping or one-shot playback
if (!strcmp(mode,"looping")) {
looping = 1;
for (int j=0; j<channels; j++)
data[length*channels+j] = data[j]; // extra sample for interpolation
}
else if (!strcmp(mode,"oneshot")) {
looping = 0;
for (int j=0; j<channels; j++)
data[length*channels+j] = data[(length-1)*channels+j]; // extra sample for interpolation
}
else {
fprintf(stderr,"ERROR: Unsupported MatWvIn mode: %s\n",mode);
free(data);
exit(0);
}
rate = (MY_FLOAT) 1.0;
interpolate = 0;
time = (MY_FLOAT) 0.0;
phaseOffset = (MY_FLOAT) 0.0;
finished = 0;
lastOutput = (MY_FLOAT *) calloc(channels, sizeof(MY_FLOAT));
}
MatWvIn :: ~MatWvIn()
{
}

View File

@@ -1,33 +0,0 @@
/*******************************************/
/* MatWvIn Input Class, */
/* by Gary P. Scavone, 1999 */
/* */
/* This object inherits from WvIn and is */
/* used to open Matlab MAT-file data */
/* (doubles) files for playback. In */
/* order for this class to work, the */
/* MAT-file must contain a single array */
/* (matrix) of double-precision floating */
/* point values (can be multi-channel). */
/* It does not work for any other data */
/* formats. */
/* */
/* MAT-file data is either big- or */
/* little-endian, which can be determined */
/* from the header. */
/*******************************************/
#if !defined(__MatWvIn_h)
#define __MatWvIn_h
#include "Object.h"
#include "WvIn.h"
class MatWvIn : public WvIn
{
public:
MatWvIn(char *fileName, char *mode);
~MatWvIn();
};
#endif

View File

@@ -1,199 +0,0 @@
/*******************************************/
/* Matlab MAT-file Output Class, */
/* by Gary P. Scavone, 1999. */
/* This object creates a Matlab MAT-file */
/* structure with a numeric array */
/* subelement and fills it with buffers */
/* of samples (doubles). */
/* */
/* When originally created, the Matlab */
/* MAT-file format was not public and I */
/* had to reverse-engineer the format. */
/* Matlab finally released the format in */
/* the Spring of 1999, and this class was */
/* updated to more closely adhere to */
/* specifications. */
/*******************************************/
#include "MatWvOut.h"
/******** Matlab Matfile Header Struct *******/
struct matheaderform {
char heading[124]; // Header text field
INT16 hff[2]; // Header flag fields
INT32 adf[11]; // Array data format fields
// There's more, but it's of variable length
};
FILE *openMatFile(int chans,char *fileName) {
struct matheaderform hdr;
FILE *fd;
char tempName[128];
char arrayName[128];
int i;
INT32 tmp, headsize, namelen;
strcpy(hdr.heading,"MATLAB 5.0 MAT-file, Generated using the Synthesis ToolKit (STK). By Gary P. Scavone, CCRMA, Stanford University, 1999.");
for (i=strlen(hdr.heading);i<124;i++) hdr.heading[i] = ' ';
// Header Flag Fields
hdr.hff[0] = (INT16) 0x0100; // Version field
hdr.hff[1] = (INT16) 'M'; // Endian indicator field ("MI")
hdr.hff[1] <<= 8;
hdr.hff[1] += 'I';
hdr.adf[0] = (INT32) 14; // Matlab array data type value
hdr.adf[1] = (INT32) 0; // Size of file after this point to end (in bytes)
// Don't know size yet.
// Numeric Array Subelements (4):
// 1. Array Flags
hdr.adf[2] = (INT32) 6; // Matlab 32-bit unsigned integer data type value
hdr.adf[3] = (INT32) 8; // 8 bytes of data to follow
hdr.adf[4] = (INT32) 6; // Double-precision array, no array flags set
hdr.adf[5] = (INT32) 0; // 4 bytes undefined
// 2. Array Dimensions
hdr.adf[6] = (INT32) 5; // Matlab 32-bit signed integer data type value
hdr.adf[7] = (INT32) 8; // 8 bytes of data to follow (2D array)
hdr.adf[8] = (INT32) chans; // This is the number of rows
hdr.adf[9] = (INT32) 0; // This is the number of columns
// 3. Array Name
// We'll use fileName for the matlab array name (as well as the file name).
// If fileName is 4 characters or less, we have to use a compressed data element
// format for the array name data element. Otherwise, the array name must
// be formatted in 8-byte increments (up to 31 characters + NULL).
namelen = strlen(fileName);
if (strstr(fileName,".mat")) namelen -= 4;
if (namelen > 31) { // Check length of array name
namelen = 31;
printf("File name too long for MATLAB array name.\n");
printf("Using first 31 characters only.\n");
}
strncpy(arrayName,fileName,namelen);
if (namelen > 4) {
hdr.adf[10] = 1; // Matlab 8-bit signed integer data type value
}
else { // Compressed data element format
hdr.adf[10] = namelen;
hdr.adf[10] <<=16;
hdr.adf[10] += 1;
}
headsize = 40; // Number of bytes in data element so far
// Format file name
strcpy(tempName,fileName);
if (strstr(tempName,".mat")==NULL) strcat(tempName,".mat");
// Open file and write fixed header information
fd = fopen(tempName,"w+b");
if (!fd) {
printf("Couldn't create matfile %s !!!!!!!!\n",fileName);
exit(0);
}
arrayName[namelen] = '\0';
printf("\nCreating MAT-file %s with MATLAB array %s\n\n", tempName, arrayName);
fwrite(&hdr,sizeof(char),172,fd); // Write the fixed portion of the header
// Write MATLAB array name
if (namelen > 4) {
fwrite(&namelen,sizeof(INT32),1,fd); // Size of array name in bytes (chars)
fwrite(arrayName,sizeof(char),namelen,fd);
tmp = (INT32) ceil((float)namelen/8);
fseek(fd,tmp*8-namelen,SEEK_CUR);
headsize += tmp*8;
}
else { // Compressed data element format
fwrite(arrayName,sizeof(char),namelen,fd);
tmp = 4-namelen;
fseek(fd,tmp,SEEK_CUR);
}
// Finish writing known header information
tmp = 9; // Matlab IEEE 754 double data type
fwrite(&tmp,sizeof(INT32),1,fd);
tmp = 0; // Size of real part subelement in bytes (8 per sample)
fwrite(&tmp,sizeof(INT32),1,fd);
headsize += 8; // Total number of bytes in data element so far
fseek(fd,132,SEEK_SET);
fwrite(&headsize,sizeof(INT32),1,fd); // Write header size ... will update at end
fseek(fd,0,SEEK_END);
return fd;
}
MatWvOut :: MatWvOut(char *fileName)
{
channels = 1;
fd = openMatFile(channels,fileName);
counter = 0;
totalCount = 0;
}
MatWvOut :: MatWvOut(int chans, char *fileName)
{
channels = chans;
fd = openMatFile(channels,fileName);
counter = 0;
totalCount = 0;
}
MatWvOut :: ~MatWvOut()
{
double temp;
INT32 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(INT32),1,fd); /* Write number of columns */
fseek(fd,132,SEEK_SET);
fread(&headsize,sizeof(INT32),1,fd);
temp1 = headsize;
headsize += (INT32) (totalCount * 8 * channels);
fseek(fd,132,SEEK_SET);
fwrite(&headsize,sizeof(INT32),1,fd); /* Write file size (minus some header info) */
fseek(fd,temp1+132,SEEK_SET);
temp1 = totalCount * 8 * channels;
fwrite(&temp1,sizeof(INT32),1,fd); /* Write data size (in bytes) */
fclose(fd);
}
INT32 MatWvOut :: getCounter()
{
return totalCount;
}
MY_FLOAT MatWvOut :: getTime()
{
return (MY_FLOAT) totalCount * ONE_OVER_SRATE;
}
void MatWvOut :: tick(MY_FLOAT sample)
{
for (int i=0;i<channels;i++)
data[counter++] = (double) (sample);
totalCount++;
if (counter == MAT_BUFFER_SIZE) {
fwrite(data,sizeof(double),MAT_BUFFER_SIZE,fd);
counter = 0;
}
}
void MatWvOut :: mtick(MY_MULTI samples)
{
for (int i=0;i<channels;i++)
data[counter++] = (double) *samples++;
totalCount++;
if (counter == MAT_BUFFER_SIZE) {
fwrite(data,sizeof(double),MAT_BUFFER_SIZE,fd);
counter = 0;
}
}

View File

@@ -1,44 +0,0 @@
/*******************************************/
/* Matlab MAT-file Output Class, */
/* by Gary P. Scavone, 1999. */
/* This object creates a Matlab MAT-file */
/* structure with a numeric array */
/* subelement and fills it with buffers */
/* of samples (doubles). */
/* */
/* When originally created, the Matlab */
/* MAT-file format was not public and I */
/* had to reverse-engineer the format. */
/* Matlab finally released the format in */
/* the Spring of 1999, and this class was */
/* updated to more closely adhere to */
/* specifications. */
/*******************************************/
#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-file uses doubles */
INT32 counter;
INT32 totalCount;
int channels;
public:
MatWvOut(char *infileName);
MatWvOut(int chans, char *infileName);
~MatWvOut();
INT32 getCounter();
MY_FLOAT getTime();
void tick(MY_FLOAT sample);
void mtick(MY_MULTI samples);
};
#endif // defined(__MatWvOut_h)

View File

@@ -1,189 +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;
// Concatenate the STK RAWWAVE_PATH to the rawwave file
char file[128];
strcpy(file, RAWWAVE_PATH);
vibr = new RawWvIn(strcat(file,"rawwaves/sinewave.raw"),"looping");
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;
}

View File

@@ -1,51 +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 "RawWvIn.h"
#include "BiQuad.h"
#include "OnePole.h"
class Modal4 : public Instrmnt
{
protected:
Envelope *envelope;
RawWvIn *wave;
BiQuad *filters[4];
OnePole *onepole;
RawWvIn *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

View File

@@ -1,86 +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()
{
// Concatenate the STK RAWWAVE_PATH to the rawwave file
char file[128];
strcpy(file, RAWWAVE_PATH);
vibwave = new RawWvIn(strcat(file,"rawwaves/sinewave.raw"),"looping");
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);
}
*/

View File

@@ -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 "RawWvIn.h"
#include "SubNoise.h"
#include "OnePole.h"
class Modulatr : public Object
{
protected:
RawWvIn *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

View File

@@ -1,114 +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()
{
// Concatenate the STK RAWWAVE_PATH to the rawwave file
char temp[128];
char file[128];
strcpy(temp, RAWWAVE_PATH);
strcpy(file,temp);
attacks[0] = new RawWvIn(strcat(file,"rawwaves/mandpluk.raw"),"oneshot");
strcpy(file,temp);
loops[0] = new RawWvIn(strcat(file,"rawwaves/impuls20.raw"),"looping");
strcpy(file,temp);
loops[1] = new RawWvIn(strcat(file,"rawwaves/sinewave.raw"),"looping"); /* 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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -1,52 +0,0 @@
/*******************************************/
/* Noise Generator Class, */
/* by Perry R. Cook, 1995-96 */
/* White noise as often as you like. */
/*******************************************/
#include "Noise.h"
#ifdef __OS_NeXT_
#include <libc.h>
#endif
#if defined(__OS_Win_) /* For Windoze */
#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()
{
#if defined(__OS_Win_) /* For Windoze */
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());
}
*/

View File

@@ -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

View File

@@ -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()
{
}

View File

@@ -1,131 +0,0 @@
/*********************************************/
/* Object Class, by Perry R. Cook, 1995-99 */
/* */
/* 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();
};
/* The OS type definitions are made in the Makefile */
#if defined(__OS_NeXT_) /* For NeXTStep - Black or White Hardware */
// No special defines at this time
#elif defined(__OS_IRIX_) /* For SGI */
#define __STK_REALTIME_
#elif defined(__OS_Linux_) /* For Linux */
#define __STK_REALTIME_
#define __OSS_API_ /* Use OSS API */
#define __LITTLE_ENDIAN__
#elif defined(__OS_Win_) /* For WindowsXX or NT */
#define __STK_REALTIME_
#define __WINDS_API_ /* For DirectSound API */
// #define __WINMM_API_ /* For Win MM API */
#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.
* NOTE FOR WINDOZE USERS: Given inherent delays in the sound
* output mechanism under Windoze, there is a trade-off between
* smoothness of fast SKINI parameter updates and input/output
* latency as discussed above. You can use buffer sizes as low
* as 100 (maybe lower) for delay critical applications, but in
* this case SKINI parameter updates will be clumped together
* and sound unnatural. If you want smoother parameter updates
* and you can live with more delay, try using buffer sizes
* closer to 1000. If you need smooth parameter updates AND
* low delay, don't use Windoze!
*/
#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
/* The following definition is concatenated to the
* beginning of all references to rawwave files in
* the various STK core classes (ex. Clarinet.cpp).
* If you wish to move the rawwaves directory to a
* different location in your file system, you will
* need to set this path definition appropriately.
* The current definition is a relative reference
* that will work "out of the box" for the STK
* distribution.
*/
#define RAWWAVE_PATH "../"
/* Sampling Rate */
#define SRATE (MY_FLOAT) 22050.0
/* Other SRATE derived defines */
#define SRATE_OVER_TWO (MY_FLOAT) (SRATE / 2)
#define ONE_OVER_SRATE (MY_FLOAT) (1 / SRATE)
#define TWO_PI_OVER_SRATE (MY_FLOAT) (2 * PI / SRATE)
/* 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 increases
* 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 float
/* MY_MULTI is just a pointer to MY_FLOAT. This type is used
* to pass multichannel data back and forth within STK.
*/
typedef MY_FLOAT *MY_MULTI;
/* INT16 is just that ... a 16-bit signed integer. */
typedef signed short INT16;
/* INT32 is just that ... a 32-bit signed integer. */
typedef signed long INT32;
/* Debugging define, causes massive printf's to come out.
* Also enables timing calculations in WaveOut class, other stuff.
* Uncomment to enable.
*/
//#define _debug_ 1
/* MIDI definitions */
#define NORM_7 (MY_FLOAT) 0.0078125 /* this is 1/128 */
#endif

View File

@@ -1,62 +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(sizeof(MY_FLOAT));
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;
}

View File

@@ -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

View File

@@ -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(sizeof(MY_FLOAT));
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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -1,63 +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()
{
// Concatenate the STK RAWWAVE_PATH to the rawwave file
char file1[128];
char file2[128];
char file3[128];
char file4[128];
strcpy(file1, RAWWAVE_PATH);
strcpy(file2, RAWWAVE_PATH);
strcpy(file3, RAWWAVE_PATH);
strcpy(file4, RAWWAVE_PATH);
this->loadWaves(strcat(file1,"rawwaves/sinewave.raw"),
strcat(file2,"rawwaves/sinewave.raw"),
strcat(file3,"rawwaves/sinewave.raw"),
strcat(file4,"rawwaves/fwavblnk.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
}

View File

@@ -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

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