mirror of
https://github.com/thestk/stk
synced 2026-01-12 04:21:52 +00:00
Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a8a65870f | ||
|
|
9af41126cb | ||
|
|
d2ed001eb5 | ||
|
|
3706458166 | ||
|
|
c92cf7468d | ||
|
|
e54b0cefab | ||
|
|
1a8403e203 | ||
|
|
554a74374b | ||
|
|
21b93795e7 | ||
|
|
11cf5faa0a | ||
|
|
de344668dd | ||
|
|
fe20fe92a2 | ||
|
|
e11bff2fe8 | ||
|
|
503ed3cc9f | ||
|
|
5d63b50e85 | ||
|
|
d12ef806ac | ||
|
|
ffce5357c6 | ||
|
|
b39c0bb101 | ||
|
|
f25eb5c3d7 | ||
|
|
71e5c027fb | ||
|
|
43dcd5775a | ||
|
|
b6a2202011 | ||
|
|
eccd8c9981 | ||
|
|
d199342e86 | ||
|
|
27d9b79dc7 | ||
|
|
2cbce2d8bd | ||
|
|
a6381b9d38 | ||
|
|
cf06b7598b | ||
|
|
586b0add5f | ||
|
|
6e0d1955a8 | ||
|
|
2f09fcd019 | ||
|
|
81475b04c5 | ||
|
|
3f126af4e5 |
145
Hierarchy.txt
145
Hierarchy.txt
@@ -1,145 +0,0 @@
|
||||
STK: A ToolKit of Audio Synthesis Classes and Instruments in C++
|
||||
Version 3.1
|
||||
|
||||
By Perry R. Cook, 1995-2000
|
||||
and Gary P. Scavone, 1997-2000.
|
||||
|
||||
STK Classes, Version 3.1
|
||||
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
|
||||
44
INSTALL
Normal file
44
INSTALL
Normal file
@@ -0,0 +1,44 @@
|
||||
The Synthesis ToolKit in C++ (STK)
|
||||
|
||||
By Perry R. Cook and Gary P. Scavone, 1995-2009.
|
||||
|
||||
The Synthesis ToolKit in C++ can be used in a variety of ways, depending on your particular needs. Some people just 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 API where supported. Note however that the ALSA library is required in order to compile the RtMidi class, even 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/gary/rawwaves and /home/gary/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
|
||||
|
||||
In addition, a linux RPM is available from the Planet CCRMA WWW site (http://ccrma.stanford.edu/planetccrma/software/).
|
||||
|
||||
|
||||
For Windows Users:
|
||||
|
||||
MinGW support is provided in the configure script. In addition, Visual C++ project files are included for each of the example STK projects.
|
||||
221
README
Normal file
221
README
Normal file
@@ -0,0 +1,221 @@
|
||||
The Synthesis ToolKit in C++ (STK)
|
||||
|
||||
By Perry R. Cook and Gary P. Scavone, 1995-2009.
|
||||
|
||||
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 (it's mostly platform-independent C and 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. In
|
||||
fact, the ToolKit has been working continuously for nearly 10 years
|
||||
now. 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 Synthesis ToolKit is free for non-commercial use. The only parts
|
||||
of the Synthesis ToolKit that are platform-dependent concern real-time
|
||||
audio and MIDI input and output, and that is taken care of with a few
|
||||
special classes. 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 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,
|
||||
Macintosh OS-X, 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 20 milliseconds or
|
||||
so, while input sound latency is on the order of a hundred
|
||||
milliseconds or more!
|
||||
|
||||
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 (Linux, SGI, and Macintosh OS X only).
|
||||
|
||||
|
||||
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-2009 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 . . .
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
STK: A ToolKit of Audio Synthesis Classes and Instruments in C++
|
||||
Version 3.1
|
||||
|
||||
By Perry R. Cook, 1995-2000
|
||||
and Gary P. Scavone, 1997-2000.
|
||||
|
||||
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). The Advanced Linux Sound Architecture (ALSA) drivers seem to perform well, though I've done only minimal testing with them. You'll need to install the OSS compatability library. You can read more about ALSA at http://www.alsa-project.org/. ALSA is open source and holds great promise for audio under Linux.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
STK: A ToolKit of Audio Synthesis Classes and Instruments in C++
|
||||
Version 3.1
|
||||
|
||||
By Perry R. Cook, 1995-2000
|
||||
and Gary P. Scavone, 1997-2000.
|
||||
|
||||
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.
|
||||
|
||||
NOTE REGARDING PTHREADS:
|
||||
|
||||
With release 3.1, STK is now using the pthread API under Irix. It appears that pthread functionality is standard on SGI, so this change shouldn't cause any problems. If I'm wrong, let me know!
|
||||
@@ -1,71 +0,0 @@
|
||||
STK: A ToolKit of Audio Synthesis Classes and Instruments in C++
|
||||
Version 3.1
|
||||
|
||||
By Perry R. Cook, 1995-2000
|
||||
and Gary P. Scavone, 1997-2000.
|
||||
|
||||
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. There is no DirectSoundCapture support for WindowsNT ... you'll have to switch to 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.
|
||||
|
||||
|
||||
WINDOWS 2000:
|
||||
|
||||
I don't have Windows 2000 and I don't expect to get it anytime soon. Things should work under 2000 at least as well as they do using NT. Since 2000 is supposed to ship with DirectX 7.0, the DirectSoundCapture functionality should work as well.
|
||||
123
README.txt
123
README.txt
@@ -1,123 +0,0 @@
|
||||
STK: A ToolKit of Audio Synthesis Classes and Instruments in C++
|
||||
Version 3.1
|
||||
|
||||
By Perry R. Cook, 1995-2000
|
||||
and Gary P. Scavone, 1997-2000.
|
||||
|
||||
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 were added to STK with release 3.0, 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 were extended in release 3.0 to function under Unix platforms, as well as Windoze platforms. Further, the socket server thread was 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. RagaMatic is a totally cool application for achieving inner piece. 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 . . .
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
STK: A ToolKit of Audio Synthesis Classes and Instruments in C++
|
||||
Release 3.1
|
||||
|
||||
By Perry R. Cook, 1995-2000
|
||||
and Gary P. Scavone, 1997-2000
|
||||
|
||||
v3.1: (13 March 2000)
|
||||
- new RagaMatic project!!!
|
||||
- added "microphone position" to Mandolin in STKdemo
|
||||
- fixed MIDI system message exclusion under Irix
|
||||
- added a few bitmaps for the Shaker instruments
|
||||
- made destructors virtual for Reverb.h, WvIn.h and Simple.h
|
||||
- fixed bug setting delay length in DLineA when value too big
|
||||
- fixed bug in WinMM realtime code (RTSoundIO)
|
||||
- added tick() method to BowTabl, JetTabl, and ReedTabl (same as lookup)
|
||||
- switched to pthread API on SGI platforms
|
||||
- added some defines to Object.h for random number generation, FPU overflow checking, etc...
|
||||
- a lot of minor changes, some bug fixes ... can't remember all of them
|
||||
|
||||
|
||||
v3.0: (10 October 1999)
|
||||
- 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.
|
||||
197
STK/ADSR.cpp
197
STK/ADSR.cpp
@@ -1,197 +0,0 @@
|
||||
/*******************************************/
|
||||
/* ADSR Subclass of the Envelope Class, */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* This is the traditional ADSR (Attack */
|
||||
/* Decay, Sustain, Release) ADSR. */
|
||||
/* It responds to simple KeyOn and KeyOff */
|
||||
/* messages, keeping track of it's state. */
|
||||
/* There are two tick (update value) */
|
||||
/* methods, one returns the value, and */
|
||||
/* other returns the state (0 = A, 1 = D, */
|
||||
/* 2 = S, 3 = R) */
|
||||
/*******************************************/
|
||||
|
||||
#include "ADSR.h"
|
||||
|
||||
ADSR :: ADSR() : Envelope()
|
||||
{
|
||||
target = (MY_FLOAT) 0.0;
|
||||
value = (MY_FLOAT) 0.0;
|
||||
attackRate = (MY_FLOAT) 0.001;
|
||||
decayRate = (MY_FLOAT) 0.001;
|
||||
sustainLevel = (MY_FLOAT) 0.5;
|
||||
releaseRate = (MY_FLOAT) 0.01;
|
||||
state = 0;
|
||||
}
|
||||
|
||||
ADSR :: ~ADSR()
|
||||
{
|
||||
/* Nothing to do here */
|
||||
}
|
||||
|
||||
void ADSR :: keyOn()
|
||||
{
|
||||
target = (MY_FLOAT) 1.0;
|
||||
rate = attackRate;
|
||||
state = 0;
|
||||
}
|
||||
|
||||
void ADSR :: keyOff()
|
||||
{
|
||||
target = (MY_FLOAT) 0.0;
|
||||
rate = releaseRate;
|
||||
state = 3;
|
||||
}
|
||||
|
||||
void ADSR :: setAttackRate(MY_FLOAT aRate)
|
||||
{
|
||||
if (aRate < 0.0) {
|
||||
printf("negative rates not allowed!!, correcting\n");
|
||||
attackRate = -aRate;
|
||||
}
|
||||
else attackRate = aRate;
|
||||
}
|
||||
|
||||
void ADSR :: setDecayRate(MY_FLOAT aRate)
|
||||
{
|
||||
if (aRate < 0.0) {
|
||||
printf("negative rates not allowed!!, correcting\n");
|
||||
decayRate = -aRate;
|
||||
}
|
||||
else decayRate = aRate;
|
||||
}
|
||||
|
||||
void ADSR :: setSustainLevel(MY_FLOAT aLevel)
|
||||
{
|
||||
if (aLevel < 0.0 ) {
|
||||
printf("Sustain level out of range!!, correcting\n");
|
||||
sustainLevel = (MY_FLOAT) 0.0;
|
||||
}
|
||||
else sustainLevel = aLevel;
|
||||
}
|
||||
|
||||
void ADSR :: setReleaseRate(MY_FLOAT aRate)
|
||||
{
|
||||
if (aRate < 0.0) {
|
||||
printf("negative rates not allowed!!, correcting\n");
|
||||
releaseRate = -aRate;
|
||||
}
|
||||
else releaseRate = aRate;
|
||||
}
|
||||
|
||||
void ADSR :: setAttackTime(MY_FLOAT aTime)
|
||||
{
|
||||
if (aTime < 0.0) {
|
||||
printf("negative times not allowed!!, correcting\n");
|
||||
attackRate = ONE_OVER_SRATE / -aTime;
|
||||
}
|
||||
else attackRate = ONE_OVER_SRATE / aTime;
|
||||
}
|
||||
|
||||
void ADSR :: setDecayTime(MY_FLOAT aTime)
|
||||
{
|
||||
if (aTime < 0.0) {
|
||||
printf("negative times not allowed!!, correcting\n");
|
||||
decayRate = ONE_OVER_SRATE / -aTime;
|
||||
}
|
||||
else decayRate = ONE_OVER_SRATE / aTime;
|
||||
}
|
||||
|
||||
void ADSR :: setReleaseTime(MY_FLOAT aTime)
|
||||
{
|
||||
if (aTime < 0.0) {
|
||||
printf("negative times not allowed!!, correcting\n");
|
||||
releaseRate = ONE_OVER_SRATE / -aTime;
|
||||
}
|
||||
else releaseRate = ONE_OVER_SRATE / aTime;
|
||||
}
|
||||
|
||||
void ADSR :: setAllTimes(MY_FLOAT attTime, MY_FLOAT decTime, MY_FLOAT susLevel, MY_FLOAT relTime)
|
||||
{
|
||||
this->setAttackTime(attTime);
|
||||
this->setDecayTime(decTime);
|
||||
this->setSustainLevel(susLevel);
|
||||
this->setReleaseTime(relTime);
|
||||
}
|
||||
|
||||
void ADSR :: setTarget(MY_FLOAT aTarget)
|
||||
{
|
||||
target = aTarget;
|
||||
if (value < target) {
|
||||
state = ATTACK;
|
||||
this->setSustainLevel(target);
|
||||
rate = attackRate;
|
||||
}
|
||||
if (value > target) {
|
||||
this->setSustainLevel(target);
|
||||
state = DECAY;
|
||||
rate = decayRate;
|
||||
}
|
||||
}
|
||||
|
||||
void ADSR :: setValue(MY_FLOAT aValue)
|
||||
{
|
||||
state = SUSTAIN;
|
||||
target = aValue;
|
||||
value = aValue;
|
||||
this->setSustainLevel(aValue);
|
||||
rate = (MY_FLOAT) 0.0;
|
||||
}
|
||||
|
||||
MY_FLOAT ADSR :: tick()
|
||||
{
|
||||
if (state==ATTACK) {
|
||||
value += rate;
|
||||
if (value >= target) {
|
||||
value = target;
|
||||
rate = decayRate;
|
||||
target = sustainLevel;
|
||||
state = DECAY;
|
||||
}
|
||||
}
|
||||
else if (state==DECAY) {
|
||||
value -= decayRate;
|
||||
if (value <= sustainLevel) {
|
||||
value = sustainLevel;
|
||||
rate = (MY_FLOAT) 0.0;
|
||||
state = SUSTAIN;
|
||||
}
|
||||
}
|
||||
else if (state==RELEASE) {
|
||||
value -= releaseRate;
|
||||
if (value <= 0.0) {
|
||||
value = (MY_FLOAT) 0.0;
|
||||
state = 4;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
int ADSR :: informTick()
|
||||
{
|
||||
this->tick();
|
||||
return state;
|
||||
}
|
||||
|
||||
MY_FLOAT ADSR :: lastOut()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
/************ Test Main ************************/
|
||||
/*
|
||||
void main()
|
||||
{
|
||||
long i;
|
||||
ADSR test;
|
||||
|
||||
test.setAttackRate(0.15);
|
||||
test.keyOn();
|
||||
while(test.informTick()==ATTACK) printf("%lf\n",test.tick());
|
||||
test.setDecayRate(0.1);
|
||||
while (test.informTick()==DECAY) printf("%lf\n",test.lastOut());
|
||||
test.setReleaseRate(0.05);
|
||||
test.keyOff();
|
||||
while(test.informTick()==RELEASE) printf("%lf\n",test.lastOut());
|
||||
}
|
||||
*/
|
||||
46
STK/ADSR.h
46
STK/ADSR.h
@@ -1,46 +0,0 @@
|
||||
/*******************************************/
|
||||
/* ADSR Subclass of the Envelope Class, */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* This is the traditional ADSR (Attack */
|
||||
/* Decay, Sustain, Release) envelope. */
|
||||
/* It responds to simple KeyOn and KeyOff */
|
||||
/* messages, keeping track of it's state. */
|
||||
/* There are two tick (update value) */
|
||||
/* methods, one returns the value, and */
|
||||
/* other returns the state (0 = A, 1 = D, */
|
||||
/* 2 = S, 3 = R) */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__ADSR_h)
|
||||
#define __ADSR_h
|
||||
|
||||
#include "Envelope.h"
|
||||
|
||||
class ADSR : public Envelope
|
||||
{
|
||||
protected:
|
||||
MY_FLOAT attackRate;
|
||||
MY_FLOAT decayRate;
|
||||
MY_FLOAT sustainLevel;
|
||||
MY_FLOAT releaseRate;
|
||||
public:
|
||||
ADSR();
|
||||
~ADSR();
|
||||
void keyOn();
|
||||
void keyOff();
|
||||
void setAttackRate(MY_FLOAT aRate);
|
||||
void setDecayRate(MY_FLOAT aRate);
|
||||
void setSustainLevel(MY_FLOAT aLevel);
|
||||
void setReleaseRate(MY_FLOAT aRate);
|
||||
void setAttackTime(MY_FLOAT aTime);
|
||||
void setDecayTime(MY_FLOAT aTime);
|
||||
void setReleaseTime(MY_FLOAT aTime);
|
||||
void setAllTimes(MY_FLOAT attTime, MY_FLOAT decTime, MY_FLOAT susLevel, MY_FLOAT relTime);
|
||||
void setTarget(MY_FLOAT aTarget);
|
||||
void setValue(MY_FLOAT aValue);
|
||||
MY_FLOAT tick();
|
||||
int informTick();
|
||||
MY_FLOAT lastOut();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
31
STK/BiQuad.h
31
STK/BiQuad.h
@@ -1,31 +0,0 @@
|
||||
/*******************************************/
|
||||
/* BiQuad (2-pole, 2-zero) Filter Class, */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* See books on filters to understand */
|
||||
/* more about how this works. Nothing */
|
||||
/* out of the ordinary in this version. */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__BiQuad_h)
|
||||
#define __BiQuad_h
|
||||
|
||||
#include "Filter.h"
|
||||
|
||||
class BiQuad : public Filter
|
||||
{
|
||||
protected:
|
||||
MY_FLOAT poleCoeffs[2];
|
||||
MY_FLOAT zeroCoeffs[2];
|
||||
public:
|
||||
BiQuad();
|
||||
~BiQuad();
|
||||
void clear();
|
||||
void setPoleCoeffs(MY_FLOAT *coeffs);
|
||||
void setZeroCoeffs(MY_FLOAT *coeffs);
|
||||
void setGain(MY_FLOAT aValue);
|
||||
void setFreqAndReson(MY_FLOAT freq, MY_FLOAT reson);
|
||||
void setEqualGainZeroes();
|
||||
MY_FLOAT tick(MY_FLOAT sample);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,52 +0,0 @@
|
||||
/***********************************************/
|
||||
/* Simple Bow Table Object, after Smith */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/***********************************************/
|
||||
|
||||
#include "BowTabl.h"
|
||||
|
||||
BowTabl :: BowTabl()
|
||||
{
|
||||
/* offset is a bias, really not needed unless */
|
||||
/* friction is different in each direction */
|
||||
offSet = (MY_FLOAT) 0.0;
|
||||
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)
|
||||
{
|
||||
return this->tick(sample);
|
||||
}
|
||||
|
||||
MY_FLOAT BowTabl :: tick(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;
|
||||
}
|
||||
@@ -1,27 +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 tick(MY_FLOAT sample);
|
||||
MY_FLOAT lastOut();
|
||||
};
|
||||
|
||||
#endif
|
||||
166
STK/Bowed.cpp
166
STK/Bowed.cpp
@@ -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");
|
||||
}
|
||||
}
|
||||
56
STK/Bowed.h
56
STK/Bowed.h
@@ -1,56 +0,0 @@
|
||||
/******************************************/
|
||||
/* Bowed String model ala Smith */
|
||||
/* after McIntyre, Schumacher, Woodhouse */
|
||||
/* by Perry Cook, 1995-96 */
|
||||
/* */
|
||||
/* This is a waveguide model, and thus */
|
||||
/* relates to various Stanford Univ. */
|
||||
/* and possibly Yamaha and other patents.*/
|
||||
/* */
|
||||
/* Controls: CONTROL1 = bowPressure */
|
||||
/* CONTROL2 = bowPosition */
|
||||
/* CONTROL3 = vibrFreq */
|
||||
/* MOD_WHEEL= vibrGain */
|
||||
/* */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__Bowed_h)
|
||||
#define __Bowed_h
|
||||
|
||||
#include "Instrmnt.h"
|
||||
#include "DLineL.h"
|
||||
#include "BowTabl.h"
|
||||
#include "OnePole.h"
|
||||
#include "BiQuad.h"
|
||||
#include "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
|
||||
318
STK/BowedBar.cpp
318
STK/BowedBar.cpp
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
135
STK/Brass.cpp
135
STK/Brass.cpp
@@ -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");
|
||||
}
|
||||
}
|
||||
53
STK/Brass.h
53
STK/Brass.h
@@ -1,53 +0,0 @@
|
||||
/******************************************/
|
||||
/* Simple Brass Instrument Model ala */
|
||||
/* Cook (TBone, HosePlayer) */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* */
|
||||
/* This is a waveguide model, and thus */
|
||||
/* relates to various Stanford Univ. */
|
||||
/* and possibly Yamaha and other patents.*/
|
||||
/* */
|
||||
/* Controls: CONTROL1 = lipTension */
|
||||
/* CONTROL2 = slideLength */
|
||||
/* CONTROL3 = vibFreq */
|
||||
/* MOD_WHEEL= vibAmt */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__Brass_h)
|
||||
#define __Brass_h
|
||||
|
||||
#include "Instrmnt.h"
|
||||
#include "DLineA.h"
|
||||
#include "LipFilt.h"
|
||||
#include "DCBlock.h"
|
||||
#include "ADSR.h"
|
||||
#include "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
|
||||
130
STK/Clarinet.cpp
130
STK/Clarinet.cpp
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
107
STK/DLineA.cpp
107
STK/DLineA.cpp
@@ -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 + 1.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
|
||||
}
|
||||
43
STK/DLineA.h
43
STK/DLineA.h
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
34
STK/DLineL.h
34
STK/DLineL.h
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
35
STK/DLineN.h
35
STK/DLineN.h
@@ -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
|
||||
|
||||
184
STK/DrumSynt.cpp
184
STK/DrumSynt.cpp
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
122
STK/Envelope.cpp
122
STK/Envelope.cpp
@@ -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());
|
||||
}
|
||||
*/
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
184
STK/FM4Op.cpp
184
STK/FM4Op.cpp
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
59
STK/FM4Op.h
59
STK/FM4Op.h
@@ -1,59 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Master Class for 4 Operator FM Synth */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* This instrument contains an 4 waves, */
|
||||
/* 4 envelopes, and various state vars. */
|
||||
/* */
|
||||
/* The basic Chowning/Stanford FM patent */
|
||||
/* expired April 1995, but there exist */
|
||||
/* follow-on patents, mostly assigned to */
|
||||
/* Yamaha. If you are of the type who */
|
||||
/* should worry about this (making money) */
|
||||
/* worry away. */
|
||||
/* */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__FM4Op_h)
|
||||
#define __FM4Op_h
|
||||
|
||||
#include "Instrmnt.h"
|
||||
#include "ADSR.h"
|
||||
#include "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
|
||||
136
STK/FMVoices.cpp
136
STK/FMVoices.cpp
@@ -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 = 0.0;
|
||||
int tempi, tempi2 = 0;
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -1,24 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Filter Class, by Perry R. Cook, 1995-96*/
|
||||
/* This is the base class for all filters.*/
|
||||
/* To me, most anything is a filter, but */
|
||||
/* I'll be a little less general here, and*/
|
||||
/* define a filter as something which has */
|
||||
/* input(s), output(s), and gain. */
|
||||
/*******************************************/
|
||||
|
||||
#include "Filter.h"
|
||||
|
||||
Filter :: Filter() : Object()
|
||||
{
|
||||
}
|
||||
|
||||
Filter :: ~Filter()
|
||||
{
|
||||
}
|
||||
|
||||
MY_FLOAT Filter :: lastOut()
|
||||
{
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
28
STK/Filter.h
28
STK/Filter.h
@@ -1,28 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Filter Class, by Perry R. Cook, 1995-96*/
|
||||
/* This is the base class for all filters.*/
|
||||
/* To me, most anything is a filter, but */
|
||||
/* I'll be a little less general here, and*/
|
||||
/* define a filter as something which has */
|
||||
/* input(s), output(s), and gain. */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__Filter_h)
|
||||
#define __Filter_h
|
||||
|
||||
#include "Object.h"
|
||||
|
||||
class Filter : public Object
|
||||
{
|
||||
protected:
|
||||
MY_FLOAT gain;
|
||||
MY_FLOAT *outputs;
|
||||
MY_FLOAT *inputs;
|
||||
MY_FLOAT lastOutput;
|
||||
public:
|
||||
Filter();
|
||||
virtual ~Filter();
|
||||
MY_FLOAT lastOut();
|
||||
};
|
||||
|
||||
#endif
|
||||
178
STK/Flute.cpp
178
STK/Flute.cpp
@@ -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");
|
||||
}
|
||||
}
|
||||
64
STK/Flute.h
64
STK/Flute.h
@@ -1,64 +0,0 @@
|
||||
/******************************************/
|
||||
/* WaveGuide Flute ala Karjalainen, */
|
||||
/* Smith, Waryznyk, etc. */
|
||||
/* with polynomial Jet ala Cook */
|
||||
/* by Perry Cook, 1995-96 */
|
||||
/* */
|
||||
/* This is a waveguide model, and thus */
|
||||
/* relates to various Stanford Univ. */
|
||||
/* and possibly Yamaha and other patents.*/
|
||||
/* */
|
||||
/* Controls: CONTROL1 = jetDelay */
|
||||
/* CONTROL2 = noiseGain */
|
||||
/* CONTROL3 = vibFreq */
|
||||
/* MOD_WHEEL= vibAmt */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__Flute_h)
|
||||
#define __Flute_h
|
||||
|
||||
#include "Instrmnt.h"
|
||||
#include "JetTabl.h"
|
||||
#include "DLineL.h"
|
||||
#include "OnePole.h"
|
||||
#include "DCBlock.h"
|
||||
#include "Noise.h"
|
||||
#include "ADSR.h"
|
||||
#include "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
|
||||
139
STK/FormSwep.cpp
139
STK/FormSwep.cpp
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
/******************************************/
|
||||
/* Instrument SuperClass for Toolkit96 */
|
||||
/* Perry R. Cook, Princeton University */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__Instrmnt_h)
|
||||
#define __Instrmnt_h
|
||||
|
||||
#include "Object.h"
|
||||
|
||||
class Instrmnt : public Object
|
||||
{
|
||||
protected:
|
||||
MY_FLOAT lastOutput;
|
||||
public:
|
||||
Instrmnt();
|
||||
virtual ~Instrmnt();
|
||||
MY_FLOAT lastOut();
|
||||
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
|
||||
virtual void noteOff(MY_FLOAT amp);
|
||||
virtual void setFreq(MY_FLOAT frequency);
|
||||
virtual MY_FLOAT tick();
|
||||
virtual void controlChange(int number, MY_FLOAT value);
|
||||
};
|
||||
|
||||
#endif
|
||||
166
STK/JCRev.cpp
166
STK/JCRev.cpp
@@ -1,166 +0,0 @@
|
||||
/*******************************************/
|
||||
/* JVRev Reverb Subclass */
|
||||
/* by Tim Stilson, 1998 */
|
||||
/* based on CLM JCRev */
|
||||
/* Integrated into STK by Gary Scavone */
|
||||
/* */
|
||||
/* This is based on some of the famous */
|
||||
/* Stanford CCRMA reverbs (NRev, KipRev) */
|
||||
/* all based on the Chowning/Moorer/ */
|
||||
/* Schroeder reverberators, which use */
|
||||
/* networks of simple allpass and comb */
|
||||
/* delay filters. This particular */
|
||||
/* arrangement consists of 3 allpass */
|
||||
/* filters in series, followed by 4 comb */
|
||||
/* filters in parallel, an optional */
|
||||
/* lowpass filter, and two decorrelation */
|
||||
/* delay lines in parallel at the output. */
|
||||
/*******************************************/
|
||||
|
||||
#include "JCRev.h"
|
||||
|
||||
//#define LOWPASS
|
||||
|
||||
JCRev :: JCRev(MY_FLOAT T60)
|
||||
{
|
||||
/* These are the values from CLM's JCRev.ins ... I found that the
|
||||
impulse response sounded better with the shorter delay lengths.
|
||||
--Gary Scavone, 2/1998
|
||||
int lens[9] = {4799,4999,5399,5801,1051,337,113,573,487};
|
||||
*/
|
||||
int lens[9] = {1777,1847,1993,2137,389,127,43,211,179};
|
||||
int val, i;
|
||||
|
||||
if (SRATE < 44100.0) {
|
||||
double srscale = SRATE / 44100.0;
|
||||
for (i=0; i<9; i++) {
|
||||
val = (int) floor(srscale * lens[i]);
|
||||
if ((val & 1) == 0) val++;
|
||||
while (!this->isprime(val)) val += 2;
|
||||
lens[i] = val;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i<3; i++)
|
||||
{
|
||||
APdelayLine[i] = new DLineN(lens[i+4] + 2);
|
||||
APdelayLine[i]->setDelay(lens[i+4]);
|
||||
}
|
||||
for (i=0; i<4; i++)
|
||||
{
|
||||
CdelayLine[i] = new DLineN(lens[i] + 2);
|
||||
CdelayLine[i]->setDelay(lens[i]);
|
||||
combCoeff[i] = pow(10,(-3 * lens[i] / (T60 * SRATE)));
|
||||
// printf("combCoeff[%d] = %f\n", i, combCoeff[i]);
|
||||
}
|
||||
outLdelayLine = new DLineN(lens[7] + 2);
|
||||
outLdelayLine->setDelay(lens[7]);
|
||||
outRdelayLine = new DLineN(lens[8] + 2);
|
||||
outRdelayLine->setDelay(lens[8]);
|
||||
allPassCoeff = 0.7;
|
||||
effectMix = 0.3;
|
||||
this->clear();
|
||||
}
|
||||
|
||||
JCRev :: ~JCRev()
|
||||
{
|
||||
delete APdelayLine[0];
|
||||
delete APdelayLine[1];
|
||||
delete APdelayLine[2];
|
||||
delete CdelayLine[0];
|
||||
delete CdelayLine[1];
|
||||
delete CdelayLine[2];
|
||||
delete CdelayLine[3];
|
||||
delete outLdelayLine;
|
||||
delete outRdelayLine;
|
||||
}
|
||||
|
||||
void JCRev :: clear()
|
||||
{
|
||||
APdelayLine[0]->clear();
|
||||
APdelayLine[1]->clear();
|
||||
APdelayLine[2]->clear();
|
||||
CdelayLine[0]->clear();
|
||||
CdelayLine[1]->clear();
|
||||
CdelayLine[2]->clear();
|
||||
CdelayLine[3]->clear();
|
||||
outRdelayLine->clear();
|
||||
outLdelayLine->clear();
|
||||
lastOutL = 0.0;
|
||||
lastOutR = 0.0;
|
||||
combsum1=0.0;
|
||||
combsum2=0.0;
|
||||
combsum=0.0;
|
||||
}
|
||||
|
||||
void JCRev :: setEffectMix(MY_FLOAT mix)
|
||||
{
|
||||
effectMix = mix;
|
||||
}
|
||||
|
||||
MY_FLOAT JCRev :: lastOutput()
|
||||
{
|
||||
return (lastOutL + lastOutR) * 0.5;
|
||||
}
|
||||
|
||||
MY_FLOAT JCRev :: lastOutputL()
|
||||
{
|
||||
return lastOutL;
|
||||
}
|
||||
|
||||
MY_FLOAT JCRev :: lastOutputR()
|
||||
{
|
||||
return lastOutR;
|
||||
}
|
||||
|
||||
MY_FLOAT JCRev :: tick(MY_FLOAT input)
|
||||
{
|
||||
MY_FLOAT temp,temp0,temp1,temp2,temp3,temp4,temp5,temp6;
|
||||
MY_FLOAT filtout;
|
||||
|
||||
temp = APdelayLine[0]->lastOut();
|
||||
temp0 = allPassCoeff * temp;
|
||||
temp0 += input;
|
||||
APdelayLine[0]->tick(temp0);
|
||||
temp0 = -(allPassCoeff * temp0) + temp;
|
||||
|
||||
temp = APdelayLine[1]->lastOut();
|
||||
temp1 = allPassCoeff * temp;
|
||||
temp1 += temp0;
|
||||
APdelayLine[1]->tick(temp1);
|
||||
temp1 = -(allPassCoeff * temp1) + temp;
|
||||
|
||||
temp = APdelayLine[2]->lastOut();
|
||||
temp2 = allPassCoeff * temp;
|
||||
temp2 += temp1;
|
||||
APdelayLine[2]->tick(temp2);
|
||||
temp2 = -(allPassCoeff * temp2) + temp;
|
||||
|
||||
temp3 = temp2 + (combCoeff[0] * CdelayLine[0]->lastOut());
|
||||
temp4 = temp2 + (combCoeff[1] * CdelayLine[1]->lastOut());
|
||||
temp5 = temp2 + (combCoeff[2] * CdelayLine[2]->lastOut());
|
||||
temp6 = temp2 + (combCoeff[3] * CdelayLine[3]->lastOut());
|
||||
|
||||
CdelayLine[0]->tick(temp3);
|
||||
CdelayLine[1]->tick(temp4);
|
||||
CdelayLine[2]->tick(temp5);
|
||||
CdelayLine[3]->tick(temp6);
|
||||
|
||||
#ifdef LOWPASS
|
||||
combsum2=combsum1;
|
||||
combsum1=combsum;
|
||||
combsum = temp3+temp4+temp5+temp6;
|
||||
filtout= 0.5*combsum1+0.25*(combsum+combsum2);
|
||||
#else
|
||||
filtout = temp3+temp4+temp5+temp6;
|
||||
#endif
|
||||
|
||||
lastOutL = effectMix * (outLdelayLine->tick(filtout));
|
||||
lastOutR = effectMix * (outRdelayLine->tick(filtout));
|
||||
temp = (1.0 - effectMix) * input;
|
||||
lastOutL += temp;
|
||||
lastOutR += temp;
|
||||
|
||||
return (lastOutL + lastOutR) * 0.5;
|
||||
|
||||
}
|
||||
52
STK/JCRev.h
52
STK/JCRev.h
@@ -1,52 +0,0 @@
|
||||
/*******************************************/
|
||||
/* JVRev Reverb Subclass */
|
||||
/* by Tim Stilson, 1998 */
|
||||
/* based on CLM JCRev */
|
||||
/* Integrated into STK by Gary Scavone */
|
||||
/* */
|
||||
/* This is based on some of the famous */
|
||||
/* Stanford CCRMA reverbs (NRev, KipRev) */
|
||||
/* all based on the 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
|
||||
|
||||
@@ -1,43 +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)
|
||||
{
|
||||
return this->tick(sample);
|
||||
}
|
||||
|
||||
MY_FLOAT JetTabl :: tick(MY_FLOAT sample)
|
||||
// Perform "Table Lookup"
|
||||
// By Polynomial Calculation
|
||||
{
|
||||
// (x^3 - x) approximates sigmoid of jet
|
||||
lastOutput = sample * (sample*sample - (MY_FLOAT) 1.0);
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1,27 +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 tick(MY_FLOAT deltaP);
|
||||
MY_FLOAT lastOut();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,65 +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 */
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
404
STK/MD2SKINI.cpp
404
STK/MD2SKINI.cpp
@@ -1,404 +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_) || defined(__OS_Linux_))
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
|
||||
pthread_t exit_thread;
|
||||
|
||||
#elif defined(__OS_Win_)
|
||||
|
||||
#include <process.h>
|
||||
#include <winsock.h>
|
||||
|
||||
unsigned long exit_thread;
|
||||
|
||||
#endif
|
||||
|
||||
// The thread function protocols are slightly different
|
||||
// under Windoze ... but of course!
|
||||
#if (defined(__OS_IRIX_) || 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);
|
||||
}
|
||||
}
|
||||
|
||||
#if (defined(__OS_IRIX_) || defined(__OS_Linux_))
|
||||
pthread_exit(NULL);
|
||||
return NULL;
|
||||
#elif defined(__OS_Win_)
|
||||
_endthread();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void usage(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);
|
||||
}
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
{
|
||||
long j, i = 1;
|
||||
MY_FLOAT byte2, byte3;
|
||||
int channel;
|
||||
int firstMessage = 1;
|
||||
int writeFileOut = 0;
|
||||
FILE *fileOut = NULL;
|
||||
MIDIIO *controller;
|
||||
char hostName[256];
|
||||
char fileName[256];
|
||||
int useSocket = 0;
|
||||
int theSocket = 0;
|
||||
struct sockaddr_in saServer;
|
||||
static struct timeval timeout = {0, 10000}; // ten millisecond
|
||||
|
||||
if (argc>5) {
|
||||
usage();
|
||||
}
|
||||
|
||||
// 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:
|
||||
usage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else usage();
|
||||
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_) || defined(__OS_Linux_))
|
||||
if (pthread_create(&exit_thread, NULL, monitorStdin, NULL)) {
|
||||
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));
|
||||
} else {
|
||||
// With Irix 5.3, you can no longer use the usleep()
|
||||
// function. And in Windoze, you can't use the select()
|
||||
// function to do timings. I love supporting multiple
|
||||
// platforms!
|
||||
#if defined(__OS_Win_)
|
||||
Sleep ( (DWORD) 5);
|
||||
#else
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 10000; // 0.01 seconds
|
||||
select(0, NULL, NULL, NULL, &timeout);
|
||||
#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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
582
STK/MIDIIO.cpp
582
STK/MIDIIO.cpp
@@ -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 <pthread.h>
|
||||
#include <dmedia/midi.h>
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
|
||||
MDport inport;
|
||||
|
||||
MDevent *midiBuffer;
|
||||
|
||||
pthread_t midi_input_thread;
|
||||
|
||||
void *midiInputThread(void *)
|
||||
{
|
||||
MDevent newMessage;
|
||||
int status;
|
||||
|
||||
while (1) {
|
||||
mdReceive(inport, &newMessage, 1);
|
||||
status = (newMessage.msg[0] & MD_STATUSMASK);
|
||||
|
||||
// Ignore all system messages
|
||||
//if (!((status & 0xff) == 0xfe || (status & 0xff) == 0xf8)) {
|
||||
if (status != 0xf0) {
|
||||
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;
|
||||
|
||||
if (pthread_create(&midi_input_thread, NULL, midiInputThread, NULL)) {
|
||||
fprintf(stderr, "unable to create MIDI input thread ... aborting.\n");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
MIDIIO :: ~MIDIIO()
|
||||
{
|
||||
pthread_cancel(midi_input_thread);
|
||||
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
|
||||
56
STK/MIDIIO.h
56
STK/MIDIIO.h
@@ -1,56 +0,0 @@
|
||||
/******************************************/
|
||||
/* MIDIIO.h */
|
||||
/* Realtime MIDI I/O Object for STK, */
|
||||
/* by Gary P. Scavone, 1998. */
|
||||
/* Based in part on code by Perry */
|
||||
/* Cook (SGI), Paul Leonard (Linux), */
|
||||
/* the RoseGarden team (Linux), and */
|
||||
/* Bill Putnam (Win95/NT). */
|
||||
/* */
|
||||
/* At the moment, this object only */
|
||||
/* handles MIDI Input, though MIDI */
|
||||
/* Output code can go here when someone */
|
||||
/* decides they need it (and writes it). */
|
||||
/* */
|
||||
/* This object opens a MIDI Input device */
|
||||
/* and parses MIDI data. Time stamp */
|
||||
/* info is converted to deltaTime. */
|
||||
/* MIDI data is stored as MY_FLOAT to */
|
||||
/* conform with SKINI. */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__MIDIIO_h)
|
||||
#define __MIDIIO_h
|
||||
|
||||
#include "Object.h"
|
||||
|
||||
class MIDIIO : public Object
|
||||
{
|
||||
protected:
|
||||
int messageType;
|
||||
int channel;
|
||||
float byteTwo;
|
||||
float byteThree;
|
||||
MY_FLOAT deltaTime;
|
||||
public:
|
||||
MIDIIO();
|
||||
~MIDIIO();
|
||||
void printMessage();
|
||||
int nextMessage();
|
||||
int getType();
|
||||
int getChannel();
|
||||
MY_FLOAT getByteTwo();
|
||||
MY_FLOAT getByteThree();
|
||||
MY_FLOAT getDeltaTime();
|
||||
};
|
||||
|
||||
#if defined(__OS_Win_)
|
||||
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h>
|
||||
|
||||
static void CALLBACK midiInputCallback( HMIDIOUT hmin, UINT inputStatus,
|
||||
DWORD instancePtr, DWORD midiMessage, DWORD timestamp);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
152
STK/Mandolin.cpp
152
STK/Mandolin.cpp
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
116
STK/Marimba.cpp
116
STK/Marimba.cpp
@@ -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();
|
||||
}
|
||||
@@ -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
|
||||
178
STK/MatWvIn.cpp
178
STK/MatWvIn.cpp
@@ -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()
|
||||
{
|
||||
}
|
||||
@@ -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
|
||||
199
STK/MatWvOut.cpp
199
STK/MatWvOut.cpp
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
189
STK/Modal4.cpp
189
STK/Modal4.cpp
@@ -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;
|
||||
}
|
||||
|
||||
51
STK/Modal4.h
51
STK/Modal4.h
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
*/
|
||||
@@ -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
|
||||
114
STK/Moog1.cpp
114
STK/Moog1.cpp
@@ -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;
|
||||
}
|
||||
|
||||
34
STK/Moog1.h
34
STK/Moog1.h
@@ -1,34 +0,0 @@
|
||||
/******************************************/
|
||||
/* Moog1 Subclass of */
|
||||
/* Sampling Synthesizer Class */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* */
|
||||
/* Controls: CONTROL1 = filterQ */
|
||||
/* CONTROL2 = filterRate */
|
||||
/* CONTROL3 = vibFreq */
|
||||
/* MOD_WHEEL= vibAmt */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__Moog1_h)
|
||||
#define __Moog1_h
|
||||
|
||||
#include "SamplFlt.h"
|
||||
|
||||
class Moog1 : public SamplFlt
|
||||
{
|
||||
private:
|
||||
MY_FLOAT modDepth;
|
||||
MY_FLOAT filterQ;
|
||||
MY_FLOAT filterRate;
|
||||
public:
|
||||
Moog1();
|
||||
~Moog1();
|
||||
virtual void setFreq(MY_FLOAT frequency);
|
||||
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
|
||||
void setModulationSpeed(MY_FLOAT mSpeed);
|
||||
void setModulationDepth(MY_FLOAT mDepth);
|
||||
virtual void controlChange(int number, MY_FLOAT value);
|
||||
virtual MY_FLOAT tick();
|
||||
};
|
||||
|
||||
#endif
|
||||
140
STK/NRev.cpp
140
STK/NRev.cpp
@@ -1,140 +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)
|
||||
{
|
||||
// FPU underflow checks seem to make things much
|
||||
// worse here, so I won't do them.
|
||||
MY_FLOAT temp,temp0,temp1,temp2,temp3;
|
||||
int i;
|
||||
|
||||
temp0 = 0.0;
|
||||
for (i=0; i<6; i++)
|
||||
{
|
||||
temp = input + (combCoef[i] * CdelayLine[i]->lastOut());
|
||||
temp0 += CdelayLine[i]->tick(temp);
|
||||
}
|
||||
for (i=0; i<3; i++)
|
||||
{
|
||||
temp = APdelayLine[i]->lastOut();
|
||||
temp1 = allPassCoeff * temp;
|
||||
temp1 += temp0;
|
||||
APdelayLine[i]->tick(temp1);
|
||||
temp0 = -(allPassCoeff * temp1) + temp;
|
||||
}
|
||||
lpLastout = 0.7*lpLastout + 0.3*temp0; // onepole LP filter
|
||||
temp = APdelayLine[3]->lastOut();
|
||||
temp1 = allPassCoeff * temp;
|
||||
temp1 += lpLastout;
|
||||
APdelayLine[3]->tick(temp1);
|
||||
temp1 = -(allPassCoeff * temp1) + temp;
|
||||
|
||||
temp = APdelayLine[4]->lastOut();
|
||||
temp2 = allPassCoeff * temp;
|
||||
temp2 += temp1;
|
||||
APdelayLine[4]->tick(temp2);
|
||||
lastOutL = effectMix*(-(allPassCoeff * temp2) + temp);
|
||||
|
||||
temp = APdelayLine[5]->lastOut();
|
||||
temp3 = allPassCoeff * temp;
|
||||
temp3 += temp1;
|
||||
APdelayLine[5]->tick(temp3);
|
||||
lastOutR = effectMix*(-(allPassCoeff * temp3) + temp);
|
||||
|
||||
temp = (1.0 - effectMix) * input;
|
||||
lastOutL += temp;
|
||||
lastOutR += temp;
|
||||
|
||||
return (lastOutL + lastOutR) * 0.5;
|
||||
|
||||
}
|
||||
52
STK/NRev.h
52
STK/NRev.h
@@ -1,52 +0,0 @@
|
||||
/******************************************/
|
||||
/* NRev Reverb Subclass */
|
||||
/* by Tim Stilson, 1998 */
|
||||
/* based on CLM NRev */
|
||||
/* Integrated into STK by Gary Scavone */
|
||||
/* */
|
||||
/* This is based on some of the famous */
|
||||
/* Stanford CCRMA reverbs (NRev, KipRev) */
|
||||
/* all based on the the Chowning/Moorer/ */
|
||||
/* Schroeder reverberators, which use */
|
||||
/* networks of simple allpass and comb */
|
||||
/* delay filters. This particular */
|
||||
/* arrangement consists of 6 comb */
|
||||
/* filters in parallel, followed by 3 */
|
||||
/* allpass filters, a lowpass filter, */
|
||||
/* and another allpass in series, */
|
||||
/* followed by two allpass filters in */
|
||||
/* parallel with corresponding right and */
|
||||
/* left outputs. */
|
||||
/******************************************/
|
||||
|
||||
#if !defined(__NRev_h)
|
||||
#define __NRev_h
|
||||
|
||||
#include "Object.h"
|
||||
#include "Reverb.h"
|
||||
#include "DLineN.h"
|
||||
|
||||
class NRev : public Reverb
|
||||
{
|
||||
protected:
|
||||
DLineN *APdelayLine[8];
|
||||
DLineN *CdelayLine[6];
|
||||
MY_FLOAT allPassCoeff;
|
||||
MY_FLOAT combCoef[6];
|
||||
MY_FLOAT lpLastout;
|
||||
MY_FLOAT lastOutL;
|
||||
MY_FLOAT lastOutR;
|
||||
MY_FLOAT effectMix;
|
||||
public:
|
||||
NRev(MY_FLOAT T60);
|
||||
~NRev();
|
||||
void clear();
|
||||
void setEffectMix(MY_FLOAT mix);
|
||||
MY_FLOAT lastOutput();
|
||||
MY_FLOAT lastOutputL();
|
||||
MY_FLOAT lastOutputR();
|
||||
MY_FLOAT tick(MY_FLOAT input);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,37 +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
|
||||
|
||||
Noise :: Noise() : Object()
|
||||
{
|
||||
lastOutput = (MY_FLOAT) 0.0;
|
||||
}
|
||||
|
||||
Noise :: ~Noise()
|
||||
{
|
||||
}
|
||||
|
||||
MY_FLOAT Noise :: tick()
|
||||
{
|
||||
#if defined(__OS_Win_) /* For Windoze */
|
||||
lastOutput = (MY_FLOAT) (rand() - (int)RANDLIMIT_OVER_TWO);
|
||||
#else /* This is for Linux, NeXT and SGI */
|
||||
lastOutput = (MY_FLOAT) (random() - (int)RANDLIMIT_OVER_TWO);
|
||||
#endif
|
||||
|
||||
lastOutput *= (MY_FLOAT) ONE_OVER_RANDLIMIT;
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
MY_FLOAT Noise :: lastOut()
|
||||
{
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
23
STK/Noise.h
23
STK/Noise.h
@@ -1,23 +0,0 @@
|
||||
/*******************************************/
|
||||
/* Noise Generator Class, */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* White noise as often as you like. */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__Noise_h)
|
||||
#define __Noise_h
|
||||
|
||||
#include "Object.h"
|
||||
|
||||
class Noise : public Object
|
||||
{
|
||||
protected:
|
||||
MY_FLOAT lastOutput;
|
||||
public:
|
||||
Noise();
|
||||
virtual ~Noise();
|
||||
MY_FLOAT tick();
|
||||
MY_FLOAT lastOut();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -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()
|
||||
{
|
||||
}
|
||||
|
||||
155
STK/Object.h
155
STK/Object.h
@@ -1,155 +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 */
|
||||
#define RANDLIMIT 2147483647
|
||||
#elif defined(__OS_IRIX_) /* For SGI */
|
||||
#define __STK_REALTIME_
|
||||
#define RANDLIMIT 2147483647
|
||||
#elif defined(__OS_Linux_) /* For Linux */
|
||||
#define __STK_REALTIME_
|
||||
#define __OSS_API_ /* Use OSS API */
|
||||
#define __LITTLE_ENDIAN__
|
||||
#define RANDLIMIT 2147483647
|
||||
#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__
|
||||
#define RANDLIMIT 32767
|
||||
#endif
|
||||
|
||||
/* Real-time audio input and output buffer size. The value of
|
||||
* this buffer should be an integer multiple of the number of
|
||||
* channels your application plans to support, in order that
|
||||
* multi-channel data is not split across multiple buffers. If
|
||||
* clicks are occuring in the input or 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 audio
|
||||
* input and 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
|
||||
|
||||
/* Useful random number generator values */
|
||||
#define ONE_OVER_RANDLIMIT (1.0/RANDLIMIT)
|
||||
#define RANDLIMIT_OVER_TWO (int)(RANDLIMIT/2)
|
||||
|
||||
/* FPU Underflow Limit
|
||||
* The IEEE specification doesn't call for automatic
|
||||
* zeroing of floating-point values when they reach
|
||||
* their numerical limits. Instead, most processors
|
||||
* switch to a much more computation-intensive mode
|
||||
* when a FPU underflow occurs. We set a lower limit
|
||||
* here for our own (not so efficient) checks. Here's
|
||||
* a useful macro for limiting MY_FLOATs. At this time,
|
||||
* no FPU underflow checks are being performed.
|
||||
*/
|
||||
#define FPU_UFLOW_LIMIT 0.0000000001
|
||||
#define LIMIT_MY_FLOAT(j) ((((j)<(MY_FLOAT)FPU_UFLOW_LIMIT)&&((j)>(MY_FLOAT)-FPU_UFLOW_LIMIT))?(MY_FLOAT)0.0:(j))
|
||||
|
||||
/* 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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
/*******************************************/
|
||||
/* One Zero Filter Class, */
|
||||
/* by Perry R. Cook, 1995-96 */
|
||||
/* The parameter gain is an additional */
|
||||
/* gain parameter applied to the filter */
|
||||
/* on top of the normalization that takes */
|
||||
/* place automatically. So the net max */
|
||||
/* gain through the system equals the */
|
||||
/* value of gain. sgain is the combina- */
|
||||
/* tion of gain and the normalization */
|
||||
/* parameter, so if you set the poleCoeff */
|
||||
/* to alpha, sgain is always set to */
|
||||
/* gain / (1.0 - fabs(alpha)). */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__OneZero_h)
|
||||
#define __OneZero_h
|
||||
|
||||
#include "Filter.h"
|
||||
|
||||
class OneZero : public Filter
|
||||
{
|
||||
protected:
|
||||
MY_FLOAT zeroCoeff;
|
||||
MY_FLOAT sgain;
|
||||
public:
|
||||
OneZero();
|
||||
~OneZero();
|
||||
void clear();
|
||||
void setGain(MY_FLOAT aValue);
|
||||
void setCoeff(MY_FLOAT aValue);
|
||||
MY_FLOAT tick(MY_FLOAT sample);
|
||||
};
|
||||
|
||||
#endif
|
||||
113
STK/PRCRev.cpp
113
STK/PRCRev.cpp
@@ -1,113 +0,0 @@
|
||||
/*******************************************/
|
||||
/* PRCRev, a simple reverb unit */
|
||||
/* by Perry Cook, 1996. */
|
||||
/* Incorporated into the Reverb superclass */
|
||||
/* by Gary Scavone, 1998. */
|
||||
/* */
|
||||
/* This is based on some of the famous */
|
||||
/* Stanford CCRMA reverbs (NRev, KipRev) */
|
||||
/* all based on the the Chowning/Moorer/ */
|
||||
/* Schroeder reverberators, which use */
|
||||
/* networks of simple allpass and comb */
|
||||
/* delay filters. This particular */
|
||||
/* structure consists of 2 allpass units */
|
||||
/* in series followed by 2 comb filters in */
|
||||
/* parallel. */
|
||||
/*******************************************/
|
||||
|
||||
#include "PRCRev.h"
|
||||
|
||||
PRCRev :: PRCRev(MY_FLOAT T60)
|
||||
{
|
||||
int lens[4]={353,1097,1777,2137};
|
||||
double srscale = SRATE / 44100.0;
|
||||
int val, i;
|
||||
|
||||
if (SRATE < 44100.0) {
|
||||
for (i=0; i<4; i++) {
|
||||
val = (int) floor(srscale * lens[i]);
|
||||
if ((val & 1) == 0) val++;
|
||||
while (!this->isprime(val)) val += 2;
|
||||
lens[i] = val;
|
||||
}
|
||||
}
|
||||
for (i=0; i<2; i++)
|
||||
{
|
||||
APdelayLine[i] = new DLineN(lens[i] + 2);
|
||||
APdelayLine[i]->setDelay(lens[i]);
|
||||
CdelayLine[i] = new DLineN(lens[i+2] + 2);
|
||||
CdelayLine[i]->setDelay(lens[i+2]);
|
||||
combCoeff[i] = pow(10,(-3 * lens[i+2] / (T60 * SRATE)));
|
||||
}
|
||||
|
||||
allPassCoeff = (MY_FLOAT) 0.7;
|
||||
effectMix = (MY_FLOAT) 0.5;
|
||||
this->clear();
|
||||
}
|
||||
|
||||
PRCRev :: ~PRCRev()
|
||||
{
|
||||
delete APdelayLine[0];
|
||||
delete APdelayLine[1];
|
||||
delete CdelayLine[0];
|
||||
delete CdelayLine[1];
|
||||
}
|
||||
|
||||
void PRCRev :: clear()
|
||||
{
|
||||
APdelayLine[0]->clear();
|
||||
APdelayLine[1]->clear();
|
||||
CdelayLine[0]->clear();
|
||||
CdelayLine[1]->clear();
|
||||
lastOutL = (MY_FLOAT) 0.0;
|
||||
lastOutR = (MY_FLOAT) 0.0;
|
||||
}
|
||||
|
||||
void PRCRev :: setEffectMix(MY_FLOAT mix)
|
||||
{
|
||||
effectMix = mix;
|
||||
}
|
||||
|
||||
MY_FLOAT PRCRev :: lastOutput()
|
||||
{
|
||||
return (lastOutL + lastOutR) * (MY_FLOAT) 0.5;
|
||||
}
|
||||
|
||||
MY_FLOAT PRCRev :: lastOutputL()
|
||||
{
|
||||
return lastOutL;
|
||||
}
|
||||
|
||||
MY_FLOAT PRCRev :: lastOutputR()
|
||||
{
|
||||
return lastOutR;
|
||||
}
|
||||
|
||||
MY_FLOAT PRCRev :: tick(MY_FLOAT input)
|
||||
{
|
||||
MY_FLOAT temp,temp0,temp1,temp2,temp3;
|
||||
|
||||
temp = APdelayLine[0]->lastOut();
|
||||
temp0 = allPassCoeff * temp;
|
||||
temp0 += input;
|
||||
APdelayLine[0]->tick(temp0);
|
||||
temp0 = -(allPassCoeff * temp0) + temp;
|
||||
|
||||
temp = APdelayLine[1]->lastOut();
|
||||
temp1 = allPassCoeff * temp;
|
||||
temp1 += temp0;
|
||||
APdelayLine[1]->tick(temp1);
|
||||
temp1 = -(allPassCoeff * temp1) + temp;
|
||||
|
||||
temp2 = temp1 + (combCoeff[0] * CdelayLine[0]->lastOut());
|
||||
temp3 = temp1 + (combCoeff[1] * CdelayLine[1]->lastOut());
|
||||
|
||||
lastOutL = effectMix * (CdelayLine[0]->tick(temp2));
|
||||
lastOutR = effectMix * (CdelayLine[1]->tick(temp3));
|
||||
temp = (MY_FLOAT) (1.0 - effectMix) * input;
|
||||
lastOutL += temp;
|
||||
lastOutR += temp;
|
||||
|
||||
return (lastOutL + lastOutR) * (MY_FLOAT) 0.5;
|
||||
|
||||
}
|
||||
43
STK/PRCRev.h
43
STK/PRCRev.h
@@ -1,43 +0,0 @@
|
||||
/*******************************************/
|
||||
/* PRCRev, a simple reverb unit */
|
||||
/* by Perry Cook, 1996. */
|
||||
/* Incorporated into the Reverb superclass */
|
||||
/* by Gary Scavone, 1998. */
|
||||
/* */
|
||||
/* This is based on some of the famous */
|
||||
/* Stanford CCRMA reverbs (NRev, KipRev) */
|
||||
/* all based on the the Chowning/Moorer/ */
|
||||
/* Schroeder reverberators, which use */
|
||||
/* networks of simple allpass and comb */
|
||||
/* delay filters. */
|
||||
/*******************************************/
|
||||
|
||||
#if !defined(__PRCRev_h)
|
||||
#define __PRCRev_h
|
||||
|
||||
#include "Reverb.h"
|
||||
#include "DLineN.h"
|
||||
|
||||
class PRCRev : public Reverb
|
||||
{
|
||||
protected:
|
||||
DLineN *APdelayLine[2];
|
||||
DLineN *CdelayLine[2];
|
||||
MY_FLOAT allPassCoeff;
|
||||
MY_FLOAT combCoeff[2];
|
||||
MY_FLOAT lastOutL;
|
||||
MY_FLOAT lastOutR;
|
||||
MY_FLOAT effectMix;
|
||||
public:
|
||||
PRCRev(MY_FLOAT T60);
|
||||
~PRCRev();
|
||||
void clear();
|
||||
void setEffectMix(MY_FLOAT mix);
|
||||
MY_FLOAT lastOutput();
|
||||
MY_FLOAT lastOutputL();
|
||||
MY_FLOAT lastOutputR();
|
||||
MY_FLOAT tick(MY_FLOAT input);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -1,84 +0,0 @@
|
||||
/******************************************/
|
||||
/* Karplus-Strong plucked string model */
|
||||
/* by Perry Cook, 1995-96 */
|
||||
/* */
|
||||
/* There exist at least two patents, */
|
||||
/* assigned to Stanford, bearing the */
|
||||
/* names of Karplus and/or Strong. */
|
||||
/******************************************/
|
||||
|
||||
#include "Plucked.h"
|
||||
|
||||
Plucked :: Plucked(MY_FLOAT lowestFreq)
|
||||
{
|
||||
length = (long) (SRATE / lowestFreq + 1);
|
||||
loopGain = (MY_FLOAT) 0.999;
|
||||
delayLine = new DLineA(length);
|
||||
loopFilt = new OneZero;
|
||||
pickFilt = new OnePole;
|
||||
noise = new Noise;
|
||||
this->clear();
|
||||
}
|
||||
|
||||
Plucked :: ~Plucked()
|
||||
{
|
||||
delete delayLine;
|
||||
delete loopFilt;
|
||||
delete pickFilt;
|
||||
delete noise;
|
||||
}
|
||||
|
||||
void Plucked :: clear()
|
||||
{
|
||||
delayLine->clear();
|
||||
loopFilt->clear();
|
||||
pickFilt->clear();
|
||||
}
|
||||
|
||||
void Plucked :: setFreq(MY_FLOAT frequency)
|
||||
{
|
||||
MY_FLOAT delay;
|
||||
delay = (SRATE / frequency) - (MY_FLOAT) 0.5; /* length - delays */
|
||||
delayLine->setDelay(delay);
|
||||
loopGain = (MY_FLOAT) 0.995 + (frequency * (MY_FLOAT) 0.000005);
|
||||
if (loopGain>1.0) loopGain = (MY_FLOAT) 0.99999;
|
||||
}
|
||||
|
||||
void Plucked :: pluck(MY_FLOAT amplitude)
|
||||
{
|
||||
long i;
|
||||
pickFilt->setPole((MY_FLOAT) 0.999 - (amplitude * (MY_FLOAT) 0.15));
|
||||
pickFilt->setGain(amplitude * (MY_FLOAT) 0.5);
|
||||
for (i=0;i<length;i++)
|
||||
// fill delay with noise additively with current contents
|
||||
delayLine->tick(delayLine->lastOut() * (MY_FLOAT) 0.6
|
||||
+ pickFilt->tick(noise->tick()));
|
||||
|
||||
}
|
||||
|
||||
void Plucked :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
||||
{
|
||||
this->setFreq(freq);
|
||||
this->pluck(amp);
|
||||
#if defined(_debug_)
|
||||
printf("Plucked : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Plucked :: noteOff(MY_FLOAT amp)
|
||||
{
|
||||
loopGain = (MY_FLOAT) 1.0 - amp;
|
||||
#if defined(_debug_)
|
||||
printf("Plucked : NoteOff: Amp=%lf\n",amp);
|
||||
#endif
|
||||
}
|
||||
|
||||
MY_FLOAT Plucked :: tick()
|
||||
{
|
||||
/* check this out */
|
||||
/* here's the whole inner loop of the instrument!! */
|
||||
lastOutput = delayLine->tick(loopFilt->tick(delayLine->lastOut() * loopGain));
|
||||
lastOutput *= (MY_FLOAT) 3.0;
|
||||
return lastOutput;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user