271 Commits

Author SHA1 Message Date
garyscavone
7840967816 Revert "Fix for #108" 2021-03-19 13:30:25 -04:00
Gary Scavone
8132c90515 Added throw() to ~StkError declaration to support all C++ versions. 2021-03-18 15:09:01 -04:00
garyscavone
73004ac9c4 Merge pull request #110 from vuki/master
Fix for #108
2021-03-18 14:44:50 -04:00
garyscavone
a49f6e71e7 Merge pull request #109 from vuki/makefix
Add missing TapDelay to src/Makefile
2021-03-18 14:42:37 -04:00
Grzegorz Szwoch (sound)
926a9faca7 Fix for #108 2021-03-18 19:42:26 +01:00
Grzegorz Szwoch (sound)
34192d9a63 Fix for #108 2021-03-18 19:39:41 +01:00
Grzegorz Szwoch (sound)
fb2b0aa305 Add missing TapDelay to src/Makefile 2021-03-18 19:11:33 +01:00
garyscavone
ba967ff851 Merge pull request #108 from vuki/wrappointer
Add StkFrames constructor that wraps pointer to existing buffer
2021-03-18 11:47:11 -04:00
Grzegorz Szwoch (sound)
109f0bd9a8 Add StkFrames constructor that wraps pointer to existing buffer 2021-03-08 09:26:15 +01:00
Gary Scavone
7b94384705 Doxygen fix for underscores 2021-03-05 14:47:44 -05:00
garyscavone
b379160f2b Merge pull request #107 from vuki/operators
StkFrames: add * and *= operators for multiplication by StkFloat; ret…
2021-02-25 20:39:46 -05:00
Grzegorz Szwoch (sound)
4b5b142531 StkFrames: add * and *= operators for multiplication by StkFloat; return reference from += and *- operators 2021-02-25 13:17:58 +01:00
garyscavone
f1a75a8691 Merge pull request #106 from vuki/stkerror
Make StkError inherit from std::exception
2021-02-24 09:18:15 -05:00
Grzegorz Szwoch (sound)
e5cab23433 Make StkError inherit from std::exception 2021-02-24 11:13:47 +01:00
garyscavone
5a8b2234c7 Merge pull request #105 from vuki/master
Fix infinite loop in RtWvOut destructor
2021-02-23 17:22:56 -05:00
Grzegorz Szwoch (sound)
314835cc70 Fix infinite loop in RtWvOut destructor 2021-02-23 21:19:36 +01:00
garyscavone
fb15f76d45 Merge pull request #97 from ryandesign/autoconf-vars
Support exec_prefix, bindir, includedir, libdir
2020-05-08 12:37:06 -04:00
garyscavone
921493d4fe Merge pull request #96 from ryandesign/LDFLAGS
Use any LDFLAGS set when running ./configure
2020-05-08 12:35:47 -04:00
Ryan Schmidt
4cbdd0d3dc Support exec_prefix, bindir, includedir, libdir
Autoconf configure scripts allow the user to specify alternate
directories for exec_prefix, bindir, includedir, and libdir (see
./configure --help). Now, they are honored by the Makefile.
2020-05-06 13:33:45 -05:00
Ryan Schmidt
c97f5b4b3a Use any LDFLAGS set when running ./configure 2020-05-06 12:47:50 -05:00
garyscavone
809cb26e12 Merge pull request #95 from thestk/cocoapods-update
Update iOS demo project
2020-04-12 11:12:00 -04:00
Ariel Elkin
dbe725c40d update readme 2020-04-12 15:33:04 +01:00
Ariel Elkin
f47fde31b0 update iOS Demos 2020-04-12 15:21:48 +01:00
Ariel Elkin
5ec15d2043 updated podspec for release 4.6.1 2020-04-12 11:32:38 +01:00
Stephen Sinclair
33baf69d3e Envelope.cpp: include cmath for fabs 2020-03-31 13:44:38 +02:00
Stephen Sinclair
975c9a365f Add configure cases to select OSS for netbsd and freebsd. 2020-03-31 13:40:43 +02:00
aarón montoya-moraga
00ddf89798 fix subtitle format in README.md 2020-03-31 13:38:45 +02:00
Gary Scavone
a8b6affd8c New default argument to keyOn and keyOff in Envelope, fix in setTime function, updates to Guitar string coupling, EGuitar tcl interface, reordering of operations in Flute algorithm. 2020-03-15 16:45:30 -04:00
garyscavone
444dab21fd Merge pull request #93 from alxarsenault/master
Fix setRandomFactor range error in Granulate.
2020-03-09 10:50:59 -04:00
Alexandre Arsenault
7fc638ce32 Fix setRandomFactor range error in Granulate. 2020-03-09 10:28:44 -04:00
Gary Scavone
f489451660 Final doc updates before release 4.6.1. 2019-04-18 09:27:12 -04:00
Gary Scavone
b6143915a9 Updated RtAudio/RtMidi for new release, plus additional documentation updates. 2019-04-18 09:18:19 -04:00
Gary Scavone
38970124ec Documentation updates in advance of release 4.6.1 2019-04-18 08:56:31 -04:00
Gary Scavone
ae2bac1601 Added new Recorder class, fixed bug in StifKarp. 2019-04-16 11:04:41 -04:00
Gary Scavone
8de7543266 Update to Modulate to allow noise rate control. 2019-02-05 20:34:18 -05:00
Stephen Sinclair
f8550110d6 VS2017: rename demo.exe -> stk-demo.exe 2018-12-21 12:28:09 +01:00
cepthomas
e4d373b658 Updated docs for windows. Still could use some re-org but would need to consider all platforms.
Fixed a few links. Still lots more broken.
2018-11-13 12:28:23 -06:00
cepthomas
2fffa79174 Added template to create new VS2017 applications easily. 2018-11-13 11:52:08 -06:00
cepthomas
448c12b0f4 Updated all solution and project files to VS2017. 2018-11-12 16:15:48 -06:00
cepthomas
f88fc8690b stk issue 87: Updated demo project to VS2017. Removed old project build files. Updated doc. 2018-11-08 10:00:33 -06:00
garyscavone
0591733bd7 Merge pull request #83 from ryandesign/CocoaPods
Use intercaps for CocoaPods and use https for web site
2018-08-27 17:39:13 -04:00
garyscavone
7fe70c4223 Merge pull request #82 from ryandesign/API-name-typos
Fix API names
2018-08-27 17:38:53 -04:00
garyscavone
3d455a4644 Merge pull request #81 from ryandesign/lowercase-extension
Rename "README.MD" to "README.md"
2018-08-27 17:36:35 -04:00
garyscavone
db79599c01 Merge pull request #84 from ryandesign/eg
Fix spelling of "e.g."
2018-08-27 17:36:11 -04:00
garyscavone
7f06bf46f3 Merge pull request #85 from ryandesign/tcl-tk-xcode
Fix capitalization of Tcl, Tk, and Xcode
2018-08-27 17:34:20 -04:00
Ryan Schmidt
03b4299af4 Change "tcl" to "Tcl" 2018-08-25 22:21:18 -05:00
Ryan Schmidt
c531f68a56 Change "tcl/tk" to "Tcl/Tk" 2018-08-25 22:20:12 -05:00
Ryan Schmidt
0a5dbf59d2 Change "XCode" to "Xcode" 2018-08-25 22:17:29 -05:00
Ryan Schmidt
493fb35b3f Add missing apostrophe and parentheses
And capitalize and add a period at the end of the next sentence.
2018-08-25 20:53:32 -05:00
Ryan Schmidt
00f7424140 Change "ex." to "e.g." 2018-08-25 20:51:15 -05:00
Ryan Schmidt
47822b8ce8 Change "eg:" to "e.g." 2018-08-25 20:46:09 -05:00
Ryan Schmidt
4a27274c0f Change "eg." to "e.g." 2018-08-25 20:44:44 -05:00
Ryan Schmidt
d1f08072f9 Change "http://cocoapods.org/" to "https://cocoapods.org"
Their web server enforces https now.
2018-08-25 20:31:28 -05:00
Ryan Schmidt
3211b94abb Change "Cocoapods" to "CocoaPods"
That seems to be the preferred capitalization.
2018-08-25 20:31:15 -05:00
Ryan Schmidt
5e28beb4db Change "Direct Sound" to "DirectSound" 2018-08-25 20:16:07 -05:00
Ryan Schmidt
21d392dca7 Change "Core Audio" to "CoreAudio" 2018-08-25 20:15:08 -05:00
Ryan Schmidt
f79d75037a Change "Core Midi" to "CoreMIDI" 2018-08-25 20:13:57 -05:00
Ryan Schmidt
3efa214fbd Rename "README.MD" to "README.md"
Lowercase filename extensions are used everywhere else in this project.
2018-08-25 19:50:05 -05:00
Ryan Schmidt
6acefc08a8 Use cp -R instead of cp -r
According to the cp(1) manpage on macOS, the -r option is historic its
use is strongly discouraged.
2018-08-25 20:27:41 -03:00
Gary Scavone
6ce3ac9e10 Fix in FileLoop::getSize() to return file size in samples, rather than the chunk size if chunking.(GPS) 2018-04-27 13:21:14 +02:00
Gary Scavone
11d1dc54f3 Update of RtAudio and RtMidi classes in advance of 4.6.0 release. 2017-08-31 17:28:55 -07:00
Gary Scavone
d6c67cc479 Version and documentation updates in preparation for 4.6.0 release. 2017-08-30 12:48:34 -07:00
Stephen Sinclair
6ed16eb806 Check for jack on all operating systems. 2017-08-26 23:40:57 -03:00
Stephen Sinclair
05230b11d5 Don't check all libraries, use AS_IF.
Configure was checking for ALSA even if --without-alsa provided.

Fix AC_ARG_WITH usage to be like the manual suggests:
https://autotools.io/autoconf/arguments.html
2017-08-22 17:06:24 -03:00
Stephen Sinclair
3e103671d9 Remove Jack dependency on ALSA.
Closes #72.
2017-08-22 17:05:53 -03:00
Stephen Sinclair
071280a311 Fix warnings about unsigned-signed comparison. 2017-07-29 19:15:34 -04:00
garyscavone
15a2c89f89 Merge pull request #71 from thestk/arielelkin-patch-1
Update README-iOS.md
2017-05-18 16:07:32 -04:00
Ariel Elkin
889328c3c1 Update README-iOS.md
fix markdown syntax
2017-05-18 16:53:46 -03:00
Gary Scavone
62416d7e3f Fix to FileWvIn / FileLoop for file open issue and normalization. 2017-05-04 16:32:53 -04:00
Gary Scavone
9627701d04 Added optional argument to FileWvIn and FileLoop to distinguish int-to-float scaling from data normalization. The default values should produce the same behaviour as before. 2017-05-03 16:15:42 -04:00
Gary Scavone
9966f06757 FMVoices bug fix to avoid currentVowel > 31. 2017-05-03 15:20:19 -04:00
Gary Scavone
56bcdc32ed Fix to zero new delay memory in setMaximumDelay() function. 2017-02-24 08:36:02 -05:00
Gary Scavone
2ddc79e3bd Bug fix for MAT-files in FileWrite.cpp 2017-02-18 10:08:57 -05:00
Gary Scavone
96b1a72186 Bug fix in MidiFileIn.cpp for timing with time-code formats. 2016-11-02 18:03:25 -04:00
Gary Scavone
2a6ada02a7 Updates to demo project scripts to specify the path to the binary file 2016-09-21 15:10:56 -04:00
garyscavone
488301223a Merge pull request #64 from rhenninger/patch-1
#63: add separate index for tokens in parseString
2016-09-14 19:50:57 -04:00
garyscavone
08f71c8fa9 Merge pull request #66 from rhenninger/patch-2
redirect non-conforming writes to cerr to oStream_
2016-09-14 19:49:34 -04:00
rhenninger
e03aa486dd redirect non-conforming writes to cerr to oStream_
One error message was going to cerr instead of oStream_ in resonate.cpp
2016-09-11 13:51:10 -04:00
rhenninger
5dd605ecfd redirect non-conforming writes to cerr to oStream_
One error message in mandolin.cpp was going to cerr instead of oStream_
2016-09-11 13:47:25 -04:00
rhenninger
77a5cfa4aa redirect non-conforming writes to cerr to oStream_
Most error messages go to oStream_.  Two in guitar.cpp don't conform.
2016-09-11 13:38:57 -04:00
Gary Scavone
77bdb45575 Bug fix in duplex.cpp 2016-09-06 11:27:36 -04:00
rhenninger
ff52b9f0b0 Need to cover zero token case (Shakers)
Previous fix to#63 didn't cover case where there are no tokens left because skini messages provides all values.  For example, changing a shaker instrument has no further tokens, but rather pulls two constants directly from skini_msgs[].  Changed test ca line161 to bail out when more tokens are expected and none are left: when data type is SK_INT, SK_DBL or SK_STR (all less than 0)
2016-08-15 09:16:50 -04:00
rhenninger
fe0f5d7f96 Update Skini.cpp 2016-08-06 08:40:07 -04:00
rhenninger
e1aa259517 #63: add separate index for tokens in parseString
Added a separate index for accessing tokens leaving the original index for values to work as it always does.  Code now correctly parses SKINI text for midi extension commands as well as basic commands.
2016-08-06 08:11:35 -04:00
garyscavone
95fcd14213 Merge pull request #56 from ryandesign/master
Fix build on case-sensitive OS X
2016-02-26 07:54:41 -05:00
Ryan Schmidt
a5bef56e76 Fix build on case-sensitive OS X
Fix capitalization of CoreMIDI framework to fix build on Macs with
case-sensitive filesystems.
2016-02-25 22:23:37 -06:00
Gary Scavone
fb50d69e08 Lots of documentation updates in advance of new release (4.5.1). 2016-02-22 20:51:07 -05:00
Gary Scavone
126ff9d9e1 Updated RtMidi and RtAudio files after new releases. 2016-02-22 20:05:28 -05:00
Gary Scavone
83b75ed339 Fix for FileWvIn and FileLoop classes so that files are closed unless chunking. 2016-02-03 16:37:51 -05:00
Gary Scavone
f0f6668f25 Fixed typo in documentation. 2016-02-03 14:03:00 -05:00
garyscavone
a506acc708 Merge pull request #53 from arielelkin/master
set ENABLE_TESTABILITY = YES on project.pbxproj
2015-12-13 12:13:29 -05:00
garyscavone
3e42e3db3f Merge pull request #54 from arielelkin/setRawWavePathForDemoProject
set raw wave path for demo project
2015-12-13 12:12:52 -05:00
Ariel Elkin
852bdec0c9 set raw wave path for demo project 2015-12-13 16:55:45 +01:00
Ariel Elkin
9d8673a24e set ENABLE_TESTABILITY = YES on project.pbxproj 2015-12-13 16:42:52 +01:00
garyscavone
57344a11a9 Merge pull request #52 from fsateler/update-config-files
Update config.{sub,guess}
2015-12-13 09:45:33 -05:00
Felipe Sateler
00da5562cd Update config.{sub,guess}
This is needed to build on newer architectures
2015-12-10 22:57:17 -03:00
garyscavone
b02298a9f4 Merge pull request #51 from sonoro1234/clear_alertList_brnch
add Stk::clear_alertList method
2015-12-04 07:54:51 -05:00
Victor Bombi
d1b4dd485b add Stk::clear_alertList method 2015-12-04 09:24:31 +01:00
garyscavone
6d5a779879 Merge pull request #49 from sonoro1234/removealert_branch
add removeSampleRateAlert to ADSR and Asymp
2015-12-02 19:47:51 -05:00
garyscavone
7ea8b10c6a Merge pull request #48 from fsateler/master
Fix install target for new soname scheme
2015-12-02 19:46:50 -05:00
Victor Bombi
0e69055579 VoicForm: change message Clarinet to Voicform 2015-12-01 18:53:14 +01:00
Victor Bombi
c2833d356a add removeSampleRateAlert to ADSR and Asymp to pair with addSampleRateAlert 2015-12-01 18:23:09 +01:00
Felipe Sateler
0f16f683c9 Fix install target for new soname scheme 2015-11-27 20:36:28 -03:00
garyscavone
f3b1f35a8c Merge pull request #47 from fsateler/patch-1
Makefile.in: Reuse version from configure.ac
2015-11-22 19:14:49 -05:00
Felipe Sateler
262fe5a2d1 Makefile.in: Reuse version from configure.ac
Otherwise they get out of sync
2015-11-19 23:49:50 -03:00
Gary Scavone
5e79513e5a Update to play.cpp to play mono files out as stereo. 2015-11-03 16:35:46 -05:00
garyscavone
f13866e696 Merge pull request #44 from arielelkin/StkFrames_cast
StkFrames::operator+:  cast nFrames to unsigned int
2015-04-08 07:59:33 -04:00
Ariel Elkin
9533f2bc66 StkFrames::operator+: cast nFrames to unsigned int given we add it to a value of type unsigned int 2015-04-08 02:48:46 +02:00
Gary Scavone
8c0ad97a25 Update to demo project Makefile.in and Demo.tcl to fix problems due to previous updates. 2015-03-25 16:09:03 -04:00
garyscavone
87461b1471 Merge pull request #42 from Ahbee/fixTypo
fixed typos in `getChannel`  `setChannel()`
2015-03-25 15:53:17 -04:00
Abhi
58fc744ea4 fixed typos in getChannel setChannel() 2015-03-23 23:00:49 -04:00
Gary Scavone
35f66c806e Bugfix in DelayL::setDelay(); Updated tick() functions in RtWvIn and InetWvIn to support channel offset 2014-11-03 15:33:44 -05:00
garyscavone
0a7c541cdc Merge pull request #38 from Ahbee/rename
Renamed StkFrames::copyChannel to StkFrames::getChannel
2014-11-03 14:11:17 -05:00
garyscavone
0e55d2d2b1 Merge pull request #37 from Ahbee/feature-operator+
add StkFrames::operator+
2014-11-03 14:10:09 -05:00
garyscavone
c1c314e7d6 Merge pull request #36 from Ahbee/feature-setChannel
added StkFrames::setChannel
2014-11-03 14:09:40 -05:00
garyscavone
84d947c750 Merge pull request #39 from danlin/master
correct placement of #endif
2014-09-30 07:52:06 -04:00
Daniel Lindenfelser
05560b102d correct placement of #endif 2014-09-30 05:54:50 +02:00
Abhi
759fc187bc Renamed StkFrames::copyChannel
Renamed StkFrames::copyChannel to StkFrames::getChannel.
2014-09-21 21:28:39 -04:00
Abhi
46be0d56c3 added StkFrames::setChannel 2014-09-21 20:43:41 -04:00
Abhi
032e76da70 add StkFrames::operator+ 2014-09-21 18:06:47 -04:00
garyscavone
aae7f609cf Merge pull request #35 from Ahbee/copychannel
adds function StkFrames::copyChannel
2014-09-19 08:21:56 -04:00
garyscavone
d959a1167d Merge pull request #34 from Ahbee/FileWv_tick
add channel arg to WvIn::tick
2014-09-19 08:20:13 -04:00
garyscavone
c9f8c017bc Merge pull request #33 from Ahbee/BugFix_DelayL
Bug fix in delayL and delayA
2014-09-19 08:17:51 -04:00
Abhi
6094f40399 renamed argument sourceChannel to channel 2014-09-16 19:24:29 -04:00
Abhi
a2fb59f476 Fixed spelling 2014-09-16 17:57:30 -04:00
Abhi
f905623d10 added StkFrames::copyChannel 2014-09-16 17:53:18 -04:00
Abhi
b196c58c75 add channel arg to WvIn::tick
StkFrames& tick( StkFrames& frames ) ` is now StkFrames& tick(
StkFrames& frames, unsigned int channel = 0 )` . same applies to
FIleLoop and FileWvIn
2014-09-16 12:50:58 -04:00
Abhi
20b9411a5a fixed bug in DelayA :: setMaximumDelay
inputs_ needs to be set to all zeros
2014-09-13 19:25:08 -04:00
Abhi
bc3cfa8fb5 fixed bug in DelayL :: setMaximumDelay
need to initialize values to zero
2014-09-13 18:01:26 -04:00
Gary Scavone
d1acfb07ed Merge branch 'master' of https://github.com/thestk/stk with local. 2014-09-11 09:49:37 -04:00
Gary Scavone
b5f046871b Memory leak fix in StkFrames::operator= function 2014-09-11 09:46:25 -04:00
garyscavone
1de1f1e63d Merge pull request #30 from Karbonforms/master
fix Twang.cpp: not sure why this bug never was identified earlier (GS)
2014-09-06 21:10:50 -04:00
klf
4ce317a5a7 fix Twang.cpp
Was producing noise (values far in excess of +/- 1.0)
reverted line removed since 4.4.4
2014-08-21 10:01:57 +01:00
garyscavone
2e8a0cdd50 Merge pull request #27 from fsateler/stk-soname
Bump soname with each release
2014-08-11 14:23:42 -04:00
garyscavone
5f9f7f6f08 Merge pull request #29 from radarsat1/master
Finish renaming SKINI.msg and SKINI.tbl to SKINImsg.h and SKINItbl.h, re...
2014-08-11 14:21:59 -04:00
Stephen Sinclair
a2be4bc721 Finish renaming SKINI.msg and SKINI.tbl to SKINImsg.h and SKINItbl.h, respectively. 2014-08-07 11:53:21 +02:00
garyscavone
2437623d67 Merge pull request #26 from fsateler/rename-demo
Rename demo program to stk-demo
2014-06-10 20:25:17 -04:00
Felipe Sateler
0063a57dcb Bump soname with each release
Imitate the libtool -release style of versioning, as long as the ABI is not stable
2014-06-09 21:01:56 -04:00
Felipe Sateler
cc568a58c1 Rename demo program to stk-demo
This allows distributors to ship the program, because demo is too generic a name
2014-06-09 12:17:02 -04:00
Ariel Elkin
1799064d6f Update README-iOS.md 2014-05-12 15:22:07 -04:00
garyscavone
540d45dbbd Merge pull request #25 from arielelkin/rename-skini.msg
Rename SKINI.msg to SKINImsg.h and SKINI.tbl to SKINItbl.h
2014-05-06 09:19:00 -04:00
Ariel Elkin
222f81c1c1 Rename SKINI.msg to SKINImsg.h and SKINI.tbl to SKINItbl.h 2014-05-02 14:02:00 -04:00
Gary Scavone
cbb2fea120 Updated docs for release date. 2014-04-26 16:33:24 -04:00
Gary Scavone
4e4e8053a5 Updated to RtAudio 4.1.1; Fixed typo in ElectricGuitar script. 2014-04-26 15:04:32 -04:00
Gary Scavone
dc2bfe01d0 Added FunctionDiscoveryKeys_devpkey.h file necessary for WASAPI compile in MinGW. 2014-04-23 12:42:10 -04:00
Gary Scavone
ea52f1f1a8 Removed undefined clear() functions in FM, Resonate, Simple, and Sampler classes; a few documentation updates in preparation for 4.5.0 release. 2014-04-23 12:12:35 -04:00
Gary Scavone
1c5d42e64c Updated to latest version of RtAudio with support for WASAPI using MinGW. 2014-04-23 11:39:32 -04:00
Gary Scavone
f1c929a6c4 Merge branch 'master' of https://github.com/thestk/stk 2014-04-18 10:27:55 -04:00
Gary Scavone
d6dba8859f Another update to FileRead for Aiff sowt uncompressed format. 2014-04-18 10:27:17 -04:00
Gary Scavone
069cc1c339 Update to FileRead for Aiff sowt uncompressed format. 2014-04-18 09:43:08 -04:00
garyscavone
32574e97d6 Merge pull request #24 from gperciva/master
add clear() to abstract Instrumnt.h
2014-04-16 10:05:03 -04:00
Graham Percival
a0638ad024 add clear() to abstract Instrumnt.h
This simplies code which uses different instruments.
2014-04-15 09:55:42 +08:00
garyscavone
3ad1a59585 Merge pull request #23 from arielelkin/update_ios_readme
iOS: updated readme
2014-04-13 14:19:54 -04:00
garyscavone
90c33cae06 Merge pull request #22 from arielelkin/iOS_static_lib_reorg
iOS Lib: move static lib target and rawwaves bundle to Products folder
2014-04-13 14:18:43 -04:00
garyscavone
1ce9b33ca3 Merge pull request #19 from arielelkin/Whistle-new-typedefs
Whistle: Replace const declarations with typedefs
2014-04-13 14:18:13 -04:00
garyscavone
3caee97842 Merge pull request #18 from arielelkin/fix-variable-types-in-Iir
fix variable types in Iir
2014-04-13 14:17:42 -04:00
garyscavone
887baf05f8 Merge pull request #17 from arielelkin/fix-variable-types-in-Granulate
Fix variable types in Granulate
2014-04-13 14:16:33 -04:00
Ariel Elkin
aec65bcb76 iOS: updated readme 2014-04-12 00:15:15 +02:00
Ariel Elkin
db6fc1f0df iOS Lib: move static lib target and rawwaves bundle to Products folder 2014-04-12 00:10:39 +02:00
Ariel Elkin
1a2509ead9 Iir: change variable types from std::vector<StkFloat>::size_type to size_t 2014-04-11 23:50:52 +02:00
Ariel Elkin
7388163b7c Granulate.cpp: change variable types from std::vector<Grain>::size_type to size_t 2014-04-11 23:47:51 +02:00
Ariel Elkin
3d9bb4051b Whistle.cpp: Comment out unused variables 2014-04-11 23:44:46 +02:00
Gary Scavone
92ca28918f Bug fix in FreeVerb; Added <cstring> header in Stk.h (which seemed necessary for MinGW). 2014-04-11 16:03:52 -04:00
Gary Scavone
32a3b551d8 Documentation updates in preparation for 4.5.0 release. 2014-04-11 10:18:38 -04:00
Gary Scavone
a9a654862f A few more RtError updates in documentation and .dsp files. 2014-04-11 09:52:02 -04:00
Gary Scavone
a239b58651 More RtError updates in various project files. 2014-04-11 09:44:49 -04:00
Gary Scavone
caf7d2f2eb Updated to new releases of RtAudio and RtMidi. 2014-04-11 09:29:42 -04:00
Gary Scavone
3ee62e42d0 Date changes in preparation for new release. 2014-04-11 09:10:58 -04:00
garyscavone
afa3069dea Merge pull request #21 from arielelkin/readme_improvements
updated readmes
2014-04-11 08:50:41 -04:00
garyscavone
2c136e82ef Merge pull request #20 from arielelkin/Messager-new-typedef
Messager: add MessagerSourceType typedef
2014-04-07 20:50:53 -04:00
garyscavone
17b45a1dad Merge pull request #16 from arielelkin/explicit-casts-in-FileWrite.cpp
FileWrite.cpp: make explicit casts.
2014-04-07 20:24:15 -04:00
Ariel Elkin
dbecf1f7f0 FileWrite::setMatFile : type of iterator should be size_t 2014-04-07 15:20:37 +01:00
garyscavone
4c8e0dec43 Merge pull request #15 from arielelkin/fix-variable-types-in-TapDelay
Fix variable types in tap delay
2014-04-07 10:07:22 -04:00
garyscavone
914a76cae0 Merge pull request #14 from arielelkin/fix-variable-types-in-LentPitShift
fix variable types in LentPitShift
2014-04-07 10:04:21 -04:00
garyscavone
979c6877c9 Merge pull request #13 from arielelkin/remove-register-keyword
remove register keyword
2014-04-07 10:01:19 -04:00
Ariel Elkin
fff3e0b887 update iOS Readme 2014-04-07 13:49:30 +01:00
Ariel Elkin
a027a515af updated readmes 2014-04-07 13:45:13 +01:00
Ariel Elkin
1f0cad64dd Messager: add MessagerSourceType typedef 2014-04-06 08:55:26 +01:00
Ariel Elkin
3d3ab8b86a Whistle: Replace const declarations with typedefs 2014-04-06 08:50:31 +01:00
Ariel Elkin
e4146d6dae Update TapDelay.cpp 2014-04-06 08:39:31 +01:00
Ariel Elkin
79cdf449b5 fix variable types in Iir 2014-04-06 08:37:04 +01:00
Ariel Elkin
ce076784a4 Fix variable types in Granulate 2014-04-06 08:33:25 +01:00
Ariel Elkin
0f6f1c4194 fix variable types in LentPitShift 2014-04-06 08:26:33 +01:00
Ariel Elkin
b2cefb3b53 TapDelay: fix variable types 2014-04-06 08:24:32 +01:00
Ariel Elkin
1468ad7e12 FileWrite.cpp: make explicit casts. 2014-04-06 08:11:52 +01:00
Ariel Elkin
eade52ff5c remove register keyword 2014-04-05 21:39:57 +01:00
garyscavone
4e90d3ffd2 Merge pull request #11 from arielelkin/ios_lib
iOS-friendly static library
2014-03-30 20:23:20 -04:00
Ariel Elkin
b2c4aa87bb full rename from tempiOSDir to iOS/demo 2014-03-30 23:43:32 +01:00
Ariel Elkin
85ca274a33 Temporary rename of iOS Demo direcotry to tempiOSDir 2014-03-30 23:39:20 +01:00
Ariel Elkin
eccc38a093 removed xccheckout file 2014-03-22 01:50:01 +00:00
Ariel Elkin
3ebdbe6977 update xccheckout file for Xcode 5.1 2014-03-14 18:36:01 +00:00
Ariel Elkin
742cf6a202 remove woebegone changes to base STK class 2014-03-14 18:34:43 +00:00
Ariel Elkin
b7cbce0ced move iOS demo project to iOS folder 2014-03-14 18:07:53 +00:00
Ariel Elkin
b5e24dec52 ensure bundle url is there before making a C string from it 2014-03-14 17:51:41 +00:00
Gary Scavone
8658acabee Merge branch 'master' of https://github.com/thestk/stk 2014-03-12 13:30:49 -04:00
Gary Scavone
0e7077c0f3 ADSR fix for decay/release time calculations; FileRead variable size fixes and argument check. 2014-03-12 13:27:05 -04:00
garyscavone
e2f4193e1a Merge pull request #9 from arielelkin/fix_warnings_in_MidiFileIn.cpp
make casts in MidiFileIn.cpp explicit
2014-03-12 12:50:36 -04:00
garyscavone
f38bcceed7 Merge pull request #10 from fsateler/configure-static-shared
Add configure options to build static or shared libraries
2014-03-12 12:48:13 -04:00
Felipe Sateler
9e2cad425a Add configure options to build static or shared libraries 2014-03-12 11:21:39 -03:00
Ariel Elkin
3e43d5e297 Merge branch 'ios_lib' of github.com:arielelkin/stk into ios_lib 2014-03-12 04:49:25 +01:00
Ariel Elkin
8055f1d040 set raw wave path dynamically if needed 2014-03-12 04:49:11 +01:00
Ariel Elkin
5e145ff682 Update README.md 2014-03-08 18:57:24 +01:00
Ariel Elkin
042dea6ff7 Update README.md 2014-03-08 18:56:08 +01:00
Ariel Elkin
04ba9c694e update readme.md for iOS lib 2014-03-08 18:42:52 +01:00
Ariel Elkin
40fe7dae1d Update README.md 2014-03-08 17:37:37 +01:00
Ariel Elkin
cafad844ad make casts in MidiFileIn.cpp explicit 2014-03-08 17:18:45 +01:00
Ariel Elkin
5749dc1c55 Merge branch 'ios_lib' of github.com:arielelkin/stk into ios_lib
Conflicts:
	STK for iOS/README.md
2014-03-08 17:06:13 +01:00
Ariel Elkin
8284487d4b added all files to iOS static library 2014-03-08 17:05:05 +01:00
Ariel Elkin
193a8ebb2e Update README.md 2014-03-04 02:51:23 +00:00
Ariel Elkin
84cf7c5344 add readme for iOS xcode project 2014-03-04 02:50:15 +00:00
Ariel Elkin
11ff75339d update UI in demo ViewController.mm 2014-03-04 02:33:39 +00:00
Ariel Elkin
96543e1b84 added iOS Demo to demo projects 2014-03-04 02:25:34 +00:00
Ariel Elkin
416c02c83c rename xcode projet to STK.xcodeproj 2014-03-03 20:37:43 +00:00
Ariel Elkin
08af1a08b4 Create rawwwaves bundle 2014-03-03 19:45:05 +00:00
garyscavone
4c6e8aee76 Merge pull request #6 from arielelkin/explicit-casts-in-Fir
make casts in Fir.h explicit
2014-02-28 13:02:09 -05:00
garyscavone
b2fbc4f302 Merge pull request #5 from arielelkin/explicit-cast-in-Stk.h-frames
explicitly cast return value in Stk::frames() to match return type
2014-02-28 13:00:25 -05:00
Ariel Elkin
7aefe7caff make casts in Fir.h explicit 2014-02-27 01:19:34 +00:00
Ariel Elkin
00f822e00c explicitly cast return value in frames() to match return type 2014-02-27 01:08:45 +00:00
Ariel Elkin
c2ae82f200 Created libSTK.a 2014-02-25 00:29:49 +00:00
Ariel Elkin
72786d0b72 Tidied Effects, Instruments, and Filters folders 2014-02-24 23:15:18 +00:00
Ariel Elkin
32f23f9538 created Generators, Instruments, Effects, Filters, and Helpers folders 2014-02-24 22:58:05 +00:00
Ariel Elkin
b0e8953a6f made Generators, Instruments, and FM folders 2014-02-23 23:42:18 +00:00
Ariel Elkin
586eeac02e add STK for iOS project with iOS-relevant files 2014-02-23 21:17:30 +00:00
Gary Scavone
1874c0efa9 Merge branch 'master' of https://github.com/thestk/stk 2014-01-18 15:56:04 -05:00
Gary Scavone
9e6a25d046 FileRead fix for long matlab array names. 2014-01-18 15:51:30 -05:00
garyscavone
8912a5c0af Merge pull request #4 from radarsat1/master
Fix several potential compilation issues on various platforms, fix ElectricGuitar script, fix version number, add McGill logo.
2014-01-18 12:49:51 -08:00
Pino Toscano
b017472cdf Build realtime projects only when requested 2014-01-12 15:10:38 +01:00
Felipe Sateler
ed754183e3 Add install target to Makefile.in 2014-01-12 14:58:32 +01:00
Stephen Sinclair
add961c2f4 Change "-lWsock32" to "-lwsock32" for case-sensitive file names.
This is needed to be able to cross-compile for Windows using MingW32
on Linux.
2014-01-12 14:51:49 +01:00
Gary Scavone
e619de2a65 Merge branch 'master' of https://github.com/thestk/stk 2014-01-09 12:31:25 -05:00
Gary Scavone
5e68ce4eeb Commented-out unused arguments in Stk.cpp 2014-01-09 12:24:38 -05:00
garyscavone
ae9e437ae8 Merge pull request #3 from arielelkin/FileRead_fix
Fixes for FileRead.cpp
2014-01-09 09:22:48 -08:00
garyscavone
4699f8ef59 Merge pull request #2 from arielelkin/master
logic issue in TapDelay::setTapDelays()
2014-01-09 09:12:34 -08:00
Ariel Elkin
80db57e79b FileRead::getMatInfo, fixed if-else block 2014-01-05 20:19:27 +00:00
Ariel Elkin
4078d9309d prevent division by zero in FileRead::getRawInfo 2014-01-03 03:36:19 +01:00
Ariel Elkin
18e210ea94 Update TapDelay.cpp 2013-12-29 00:48:48 +01:00
garyscavone
3369940892 Merge pull request #1 from tmatth/filewrite_fix_warnings
FileWrite: fix warnings
2013-12-21 22:56:24 -08:00
Tristan Matthews
c57c52c17e FileWrite: fix warnings
Namely:
- unused but set
- will break strict aliasing
- unchecked return value (fread)
2013-12-02 21:19:31 -05:00
Stephen Sinclair
1bbd2c003a Change version number to 4.4.4. 2013-10-12 14:11:25 +02:00
Stephen Sinclair
80561731fe Add the McGill logo to the doc directory. 2013-10-12 14:11:24 +02:00
Stephen Sinclair
4f0c39e7eb Rename Eguitar.tcl so that ElectricGuitar works on case-sensitive file systems.
The shell script uses a different case for the TCL script's filename.
2013-10-12 14:11:24 +02:00
Stephen Sinclair
b089236578 Remove a spurious echo in the configure script. 2013-10-12 14:11:24 +02:00
Stephen Sinclair
deaabdd041 Missing header include in Md2Skini. 2013-10-12 14:11:24 +02:00
Stephen Sinclair
caeaa5778c handleError member function must be declared const.
Otherwise it causes a compilation failure when called from const
functions.
2013-10-12 14:11:24 +02:00
Stephen Sinclair
c298839886 Extra bracket causes compilation failure in debug mode. 2013-10-12 14:11:24 +02:00
Stephen Sinclair
57e3fe7dae Fix markdown title and pandoc-style metadata. 2013-10-11 15:52:59 +02:00
Stephen Sinclair
4c8691eb08 Rename README and INSTALL files to give them a .md extension.
So that they are recognized as markdown and displayed correctly on the web.
2013-10-11 15:52:59 +02:00
Stephen Sinclair
3d0db65b1c Convert README and INSTALL instructions to markdown. 2013-10-11 15:52:59 +02:00
Stephen Sinclair
c8b7b67680 Add automake-generated files to .gitignore 2013-10-11 15:52:59 +02:00
Ariel Elkin
72095c0a3d Added .gitignore 2013-10-11 15:52:59 +02:00
Stephen Sinclair
e449ac3583 Create Release and Debug directories if they are not present.
Otherwise, build fails if these directories do not exist.
2013-10-11 15:52:59 +02:00
Stephen Sinclair
a117cd0bb1 Add a check for -lpthread. 2013-10-11 15:52:59 +02:00
Gary Scavone
fc877b87bf Version 4.4.4 2013-09-29 23:22:28 +02:00
Gary Scavone
0aec39260a Version 4.4.3 2013-09-29 23:21:29 +02:00
Gary Scavone
baca57040b Version 4.4.2 2013-09-29 23:15:24 +02:00
Gary Scavone
b6a2202011 Version 4.4.1 2013-09-29 23:14:45 +02:00
Gary Scavone
eccd8c9981 Version 4.4.0 2013-09-29 23:11:39 +02:00
Gary Scavone
d199342e86 Version 4.3.1 2013-09-29 23:07:08 +02:00
Gary Scavone
27d9b79dc7 Version 4.3.0 2013-09-29 23:07:00 +02:00
Gary Scavone
2cbce2d8bd Version 4.2.1 2013-09-29 23:06:23 +02:00
Gary Scavone
a6381b9d38 Version 4.2.0 2013-09-29 23:06:14 +02:00
Gary Scavone
cf06b7598b Version 4.1.3 2013-09-29 23:06:05 +02:00
Gary Scavone
586b0add5f Version 4.1.2 2013-09-29 23:05:20 +02:00
Gary Scavone
6e0d1955a8 Version 4.1.1 2013-09-29 23:05:09 +02:00
Gary Scavone
2f09fcd019 Version 4.1 2013-09-29 23:04:59 +02:00
Gary Scavone
81475b04c5 Version 4.0 2013-09-29 23:04:45 +02:00
Gary Scavone
3f126af4e5 Version 3.2 2013-09-29 22:42:55 +02:00
Gary Scavone
4b6500d3de Version 3.1 2013-09-29 22:42:17 +02:00
Gary Scavone
868787a5f9 Version 3.0 2013-09-29 22:41:42 +02:00
Gary Scavone
7c0ee03d60 Version 2.02 2013-09-29 22:40:37 +02:00
Gary Scavone
ea749b71d2 Version 2.01 2013-09-29 22:39:45 +02:00
677 changed files with 99106 additions and 12797 deletions

199
.gitignore vendored Normal file
View File

@@ -0,0 +1,199 @@
#####
# OS X temporary files that should never be committed
#
# c.f. http://www.westwind.com/reference/os-x/invisibles.html
.DS_Store
# c.f. http://www.westwind.com/reference/os-x/invisibles.html
.Trashes
# c.f. http://www.westwind.com/reference/os-x/invisibles.html
*.swp
# *.lock - this is used and abused by many editors for many different things.
# For the main ones I use (e.g. Eclipse), it should be excluded
# from source-control, but YMMV
*.lock
#
# profile - REMOVED temporarily (on double-checking, this seems incorrect; I can't find it in OS X docs?)
#profile
####
# Xcode temporary files that should never be committed
#
# NB: NIB/XIB files still exist even on Storyboard projects, so we want this...
*~.nib
####
# Xcode build files -
#
# NB: slash on the end, so we only remove the FOLDER, not any files that were badly named "DerivedData"
DerivedData/
# NB: slash on the end, so we only remove the FOLDER, not any files that were badly named "build"
build/
#####
# Xcode private settings (window sizes, bookmarks, breakpoints, custom executables, smart groups)
#
# This is complicated:
#
# SOMETIMES you need to put this file in version control.
# Apple designed it poorly - if you use "custom executables", they are
# saved in this file.
# 99% of projects do NOT use those, so they do NOT want to version control this file.
# ..but if you're in the 1%, comment out the line "*.pbxuser"
# .pbxuser: http://lists.apple.com/archives/xcode-users/2004/Jan/msg00193.html
*.pbxuser
# .mode1v3: http://lists.apple.com/archives/xcode-users/2007/Oct/msg00465.html
*.mode1v3
# .mode2v3: http://lists.apple.com/archives/xcode-users/2007/Oct/msg00465.html
*.mode2v3
# .perspectivev3: http://stackoverflow.com/questions/5223297/xcode-projects-what-is-a-perspectivev3-file
*.perspectivev3
# NB: also, whitelist the default ones, some projects need to use these
!default.pbxuser
!default.mode1v3
!default.mode2v3
!default.perspectivev3
####
# Xcode 4 - semi-personal settings
#
#
# OPTION 1: ---------------------------------
# throw away ALL personal settings (including custom schemes!
# - unless they are "shared")
#
# NB: this is exclusive with OPTION 2 below
xcuserdata
# OPTION 2: ---------------------------------
# get rid of ALL personal settings, but KEEP SOME OF THEM
# - NB: you must manually uncomment the bits you want to keep
#
# NB: this *requires* git v1.8.2 or above; you may need to upgrade to latest OS X,
# or manually install git over the top of the OS X version
# NB: this is exclusive with OPTION 1 above
#
#xcuserdata/**/*
# (requires option 2 above): Personal Schemes
#
#!xcuserdata/**/xcschemes/*
####
# Xcode 4 workspaces - more detailed
#
# Workspaces are important! They are a core feature of Xcode - don't exclude them :)
#
# Workspace layout is quite spammy. For reference:
#
# /(root)/
# /(project-name).xcodeproj/
# project.pbxproj
# /project.xcworkspace/
# contents.xcworkspacedata
# /xcuserdata/
# /(your name)/xcuserdatad/
# UserInterfaceState.xcuserstate
# /xcsshareddata/
# /xcschemes/
# (shared scheme name).xcscheme
# /xcuserdata/
# /(your name)/xcuserdatad/
# (private scheme).xcscheme
# xcschememanagement.plist
#
#
####
# Xcode 4 - Deprecated classes
#
# Allegedly, if you manually "deprecate" your classes, they get moved here.
#
# We're using source-control, so this is a "feature" that we do not want!
*.moved-aside
####
# Files generated by automake
Makefile
autom4te.cache
config.log
config.status
configure
projects/demo/Makefile
projects/demo/stk-demo
projects/demo/Release
projects/demo/Debug
projects/effects/Makefile
projects/effects/effects
projects/effects/Release
projects/effects/Debug
projects/eguitar/Makefile
projects/eguitar/eguitar
projects/eguitar/Release
projects/eguitar/Debug
projects/examples/Makefile
projects/examples/audioprobe
projects/examples/bethree
projects/examples/controlbee
projects/examples/crtsine
projects/examples/duplex
projects/examples/foursine
projects/examples/grains
projects/examples/inetIn
projects/examples/inetOut
projects/examples/libMakefile
projects/examples/midiprobe
projects/examples/play
projects/examples/playsmf
projects/examples/record
projects/examples/rtsine
projects/examples/sine
projects/examples/sineosc
projects/examples/threebees
projects/examples/Release
projects/examples/Debug
projects/ragamatic/Makefile
projects/ragamatic/ragamat
projects/ragamatic/Release
projects/ragamatic/Debug
src/libstk.a
src/Release
src/Debug
src/Makefile
####
# Files generated by Visual Studio
projects/*/.vs/
projects/*/*.exe
projects/*/*.ilk
projects/*/*.pdb
projects/*/*.vcxproj.user
projects/*/Release/
projects/*/Debug/

173
ADSR.cpp
View File

@@ -1,173 +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 = 0.0;
value = 0.0;
attackRate = 0.001;
decayRate = 0.001;
sustainLevel = 0.5;
releaseRate = 0.01;
state = 0;
}
ADSR :: ~ADSR()
{
/* Nothing to do here */
}
void ADSR :: keyOn()
{
target = 1.0;
rate = attackRate;
state = 0;
}
void ADSR :: keyOff()
{
target = 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;
attackRate = attackRate * RATE_NORM; /* SEE Object.h */
}
void ADSR :: setDecayRate(MY_FLOAT aRate)
{
if (aRate < 0.0) {
printf("negative rates not allowed!!, correcting\n");
decayRate = -aRate;
}
else decayRate = aRate;
decayRate = decayRate * RATE_NORM; /* SEE Object.h */
}
void ADSR :: setSustainLevel(MY_FLOAT aLevel)
{
if (aLevel < 0.0 ) {
printf("Sustain level out of range!!, correcting\n");
sustainLevel = 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;
releaseRate = releaseRate * RATE_NORM; /* SEE Object.h */
}
void ADSR :: setAll(MY_FLOAT attRate, MY_FLOAT decRate, MY_FLOAT susLevel, MY_FLOAT relRate)
{
this->setAttackRate(attRate);
this->setDecayRate(decRate);
this->setSustainLevel(susLevel);
this->setReleaseRate(relRate);
}
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 = 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 = 0.0;
state = SUSTAIN;
}
}
else if (state==RELEASE) {
value -= releaseRate;
if (value <= 0.0) {
value = 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());
}
*/

43
ADSR.h
View File

@@ -1,43 +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 setAll(MY_FLOAT attRate, MY_FLOAT decRate, MY_FLOAT susLevel, MY_FLOAT relRate);
void setTarget(MY_FLOAT aTarget);
void setValue(MY_FLOAT aValue);
MY_FLOAT tick();
int informTick();
MY_FLOAT lastOut();
};
#endif

View File

@@ -1,75 +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"
AgogoBel :: AgogoBel() : Modal4()
{
wave = new RawWave("rawwaves/britestk.raw");
wave->normalize();
wave->setRate(7.0); /* hardstick */
this->setRatioAndReson(0, 1.00,0.999); /* Set our */
this->setRatioAndReson(1, 4.08,0.999); /* resonances */
this->setRatioAndReson(2,6.669,0.999); /* here */
this->setRatioAndReson(3,-3725.0,0.999); /* (One fixed) */
this->setFiltGain(0,0.07); /* And filter */
this->setFiltGain(1,0.06); /* gains too */
this->setFiltGain(2,0.04);
this->setFiltGain(3,0.02);
directGain = 0.3;
}
AgogoBel :: ~AgogoBel()
{
delete wave;
}
void AgogoBel :: setStickHardness(MY_FLOAT hardness)
{
stickHardness = hardness; /* To an approximation, */
wave->setRate(3.0 + (8.0 * stickHardness)); /* hardness <-> center */
masterGain = 1.0; /* freq and amplitude */
}
void AgogoBel :: setStrikePosition(MY_FLOAT position)
{
MY_FLOAT temp,temp2;
temp2 = position * PI;
strikePosition = position; /* Hack only first */
temp = sin(0.7 * temp2); /* three modes, */
this->setFiltGain(0,0.08 * temp); /* leave the other */
temp = sin(0.1 + (5.0 * temp2)); /* fixed. Why? */
this->setFiltGain(1,0.07 * temp); /* So it doesn't */
temp = sin(0.2 + (7.0 * temp2)); /* sound like a */
this->setFiltGain(2,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 == MIDI_control1)
this->setStickHardness(value * NORM_7);
else if (number == MIDI_control2)
this->setStrikePosition(value * NORM_7);
else if (number == MIDI_control3)
vibr->setFreq((value * NORM_7 * 12.0));
else if (number == MIDI_mod_wheel)
vibrGain = (value * NORM_7);
else if (number == MIDI_after_touch)
this->strike(value * NORM_7);
else {
printf("AgogoBel : Undefined Control Number!!\n");
}
}

View File

@@ -1,26 +0,0 @@
/*******************************************/
/* AgogoBell SubClass of Modal4 Instrument*/
/* by Perry R. Cook, 1995-96 */
/* */
/* Controls: CONTROL1 = stickHardness */
/* CONTROL2 = strikePosition*/
/* CONTROL3 = vibFreq */
/* MOD_WHEEL= vibAmt */
/*******************************************/
#if !defined(__AgogoBel_h)
#define __AgogoBel_h
#include "Modal4.h"
class AgogoBel : public Modal4
{
public:
AgogoBel();
~AgogoBel();
void setStickHardness(MY_FLOAT hardness);
void setStrikePosition(MY_FLOAT position);
virtual void controlChange(int number, MY_FLOAT value);
};
#endif

View File

@@ -1,39 +0,0 @@
/*******************************************/
/* 1st order allpass filter. */
/* by Perry R. Cook, 1995-96 */
/* A special case of the one pole */
/* one zero filter. */
/*******************************************/
#include "AllPass1.h"
AllPass1 :: AllPass1()
{
inputs = (MY_FLOAT *) malloc(MY_FLOAT_SIZE);
outputs = (MY_FLOAT *) malloc(MY_FLOAT_SIZE);
this->clear();
}
AllPass1 :: ~AllPass1()
{
free(inputs);
free(outputs);
}
void AllPass1 :: clear()
{
outputs[0] = 0.0;
inputs[0] = 0.0;
lastOutput = 0.0;
}
MY_FLOAT AllPass1 :: tick(MY_FLOAT sample)
{
outputs[0] = sample - inputs[0] + (0.99 * outputs[0]);
inputs[0] = sample;
lastOutput = outputs[0];
return lastOutput;
}

View File

@@ -1,24 +0,0 @@
/*******************************************/
/* 1st order allpass filter. */
/* by Perry R. Cook, 1995-96 */
/* A special case of the one pole */
/* one zero filter. */
/*******************************************/
#include "Filter.h"
#if !defined(__AllPass1_h)
#define __AllPass1_h
#include "Filter.h"
class AllPass1 : Filter
{
public:
AllPass1();
~AllPass1();
void clear();
MY_FLOAT tick(MY_FLOAT sample);
};
#endif

View File

@@ -1,71 +0,0 @@
/******************************************/
/* Hammond(OID) Organ Subclass */
/* of Algorithm 8 (TX81Z) Subclass of */
/* 4 Operator FM Synth */
/* by Perry R. Cook, 1995-96 */
/******************************************/
#include "BeeThree.h"
BeeThree :: BeeThree() : FM4Alg8()
{
this->loadWaves("rawwaves/sinewave.raw",
"rawwaves/sinewave.raw",
"rawwaves/sinewave.raw",
"rawwaves/sinewave.raw");
this->setRatio(0,0.999);
this->setRatio(1,1.997);
this->setRatio(2,3.006);
this->setRatio(3,6.009);
gains[0] = __FM4Op_gains[95];
gains[1] = __FM4Op_gains[95];
gains[2] = __FM4Op_gains[99];
gains[3] = __FM4Op_gains[95];
adsr[0]->setAll(0.05,0.03,1.0,0.04);
adsr[1]->setAll(0.05,0.03,1.0,0.04);
adsr[2]->setAll(0.05,0.03,1.0,0.04);
adsr[3]->setAll(0.05,0.001,0.4,0.06);
twozero->setGain(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 = 1.0 + (modDepth * vibWave->tick() * 0.1);
waves[0]->setFreq(baseFreq * ratios[0] * temp);
waves[1]->setFreq(baseFreq * ratios[1] * temp);
waves[2]->setFreq(baseFreq * ratios[2] * temp);
waves[3]->setFreq(baseFreq * ratios[3] * temp);
}
lastOutput = FM4Alg8 :: tick();
return lastOutput;
}
void BeeThree :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
{
gains[0] = amp * __FM4Op_gains[95];
gains[1] = amp * __FM4Op_gains[95];
gains[2] = amp * __FM4Op_gains[99];
gains[3] = amp * __FM4Op_gains[95];
this->setFreq(freq);
this->keyOn();
#if defined(_debug_)
printf("BeeThree : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
#endif
}

View File

@@ -1,23 +0,0 @@
/******************************************/
/* HammondOid Organ Subclass */
/* of Algorithm 8 (TX81Z) Subclass of */
/* 4 Operator FM Synth */
/* by Perry R. Cook, 1995-96 */
/******************************************/
#if !defined(__BeeThree_h)
#define __BeeThree_h
#include "FM4Alg8.h"
class BeeThree : public FM4Alg8
{
public:
BeeThree();
~BeeThree();
virtual void setFreq(MY_FLOAT frequency);
MY_FLOAT tick();
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
};
#endif

View File

@@ -1,80 +0,0 @@
/*******************************************/
/* BiQuad (2-pole, 2-zero) Filter Class, */
/* by Perry R. Cook, 1995-96 */
/* See books on filters to understand */
/* more about how this works. Nothing */
/* out of the ordinary in this version. */
/*******************************************/
#include "BiQuad.h"
BiQuad :: BiQuad() : Filter()
{
inputs = (MY_FLOAT *) malloc(2 * MY_FLOAT_SIZE);
zeroCoeffs[0] = 0.0;
zeroCoeffs[1] = 0.0;
poleCoeffs[0] = 0.0;
poleCoeffs[1] = 0.0;
gain = 1.0;
this->clear();
}
BiQuad :: ~BiQuad()
{
free(inputs);
}
void BiQuad :: clear()
{
inputs[0] = 0.0;
inputs[1] = 0.0;
lastOutput = 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] = 2.0 * reson * cos(TWO_PI * freq / SRATE);
}
void BiQuad :: setEqualGainZeroes()
{
zeroCoeffs[1] = -1.0;
zeroCoeffs[0] = 0.0;
}
void BiQuad :: setGain(MY_FLOAT aValue)
{
gain = aValue;
}
MY_FLOAT BiQuad :: tick(MY_FLOAT sample) /* Perform Filter Operation */
{ /* Biquad is two pole, two zero filter */
MY_FLOAT temp; /* Look it up in your favorite DSP text */
temp = sample * gain; /* Here's the math for the */
temp += inputs[0] * poleCoeffs[0]; /* version which implements */
temp += inputs[1] * poleCoeffs[1]; /* only 2 state variables. */
lastOutput = temp; /* This form takes */
lastOutput += (inputs[0] * zeroCoeffs[0]); /* 5 multiplies and */
lastOutput += (inputs[1] * zeroCoeffs[1]); /* 4 adds */
inputs[1] = inputs[0]; /* and 3 moves */
inputs[0] = temp; /* like the 2 state-var form*/
return lastOutput;
}

View File

@@ -1,31 +0,0 @@
/*******************************************/
/* BiQuad (2-pole, 2-zero) Filter Class, */
/* by Perry R. Cook, 1995-96 */
/* See books on filters to understand */
/* more about how this works. Nothing */
/* out of the ordinary in this version. */
/*******************************************/
#if !defined(__BiQuad_h)
#define __BiQuad_h
#include "Filter.h"
class BiQuad : public Filter
{
protected:
MY_FLOAT poleCoeffs[2];
MY_FLOAT zeroCoeffs[2];
public:
BiQuad();
~BiQuad();
void clear();
void setPoleCoeffs(MY_FLOAT *coeffs);
void setZeroCoeffs(MY_FLOAT *coeffs);
void setGain(MY_FLOAT aValue);
void setFreqAndReson(MY_FLOAT freq, MY_FLOAT reson);
void setEqualGainZeroes();
MY_FLOAT tick(MY_FLOAT sample);
};
#endif

View File

@@ -1,46 +0,0 @@
/***********************************************/
/* Simple Bow Table Object, after Smith */
/* by Perry R. Cook, 1995-96 */
/***********************************************/
#include "BowTabl.h"
BowTabl :: BowTabl()
{
offSet = 0.0; /* offset is a bias, really not needed unless */
/* friction is different in each direction */
slope = 0.1; /* controls width of friction pulse, */
/* related to bowForce */
}
BowTabl :: ~BowTabl()
{
}
void BowTabl :: setOffset(MY_FLOAT aValue)
{
offSet = aValue;
}
void BowTabl :: setSlope(MY_FLOAT aValue)
{
slope = aValue;
}
MY_FLOAT BowTabl :: lookup(MY_FLOAT sample) /* Perform Table Lookup */
{ /* sample is differential */
/* string vs. bow velocity */
MY_FLOAT input;
input = sample + offSet; /* add bias to sample */
input *= slope; /* scale it */
lastOutput = fabs(input) + 0.75; /* below min delta, friction = 1 */
lastOutput = pow(lastOutput,-4.0);
// if (lastOutput < 0.0 ) lastOutput = 0.0; /* minimum friction is 0.0 */
if (lastOutput > 1.0 ) lastOutput = 1.0; /* maximum friction is 1.0 */
return lastOutput;
}
MY_FLOAT BowTabl :: lastOut()
{
return lastOutput;
}

View File

@@ -1,22 +0,0 @@
/***********************************************/
/* Simple Bow Table Object, after Smith */
/* by Perry R. Cook, 1995-96 */
/***********************************************/
#include "Object.h"
class BowTabl : public Object
{
protected:
MY_FLOAT offSet;
MY_FLOAT slope;
MY_FLOAT lastOutput;
public:
BowTabl();
~BowTabl();
void setOffset(MY_FLOAT aValue);
void setSlope(MY_FLOAT aValue);
MY_FLOAT lookup(MY_FLOAT sample);
MY_FLOAT lastOut();
};

160
Bowed.cpp
View File

@@ -1,160 +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"
Bowed :: Bowed(MY_FLOAT lowestFreq)
{
long length;
length = (long) (SRATE / lowestFreq + 1);
neckDelay = new DLineL(length);
length >> 1;
bridgeDelay = new DLineL(length);
bowTabl = new BowTabl;
reflFilt = new OnePole;
bodyFilt = new BiQuad;
vibr = new RawLoop("rawwaves/sinewave.raw");
adsr = new ADSR;
vibrGain = 0.0;
neckDelay->setDelay(100.0);
bridgeDelay->setDelay(29.0);
bowTabl->setSlope(3.0);
reflFilt->setPole(0.6 - (0.1 * RATE_NORM));
reflFilt->setGain(0.95);
bodyFilt->setFreqAndReson(500.0, 0.85);
bodyFilt->setEqualGainZeroes();
bodyFilt->setGain(0.2);
vibr->normalize();
vibr->setFreq(6.12723);
adsr->setAll(0.002,0.01,0.9,0.01);
betaRatio = 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 = (MY_FLOAT) SRATE / frequency - 4.0; /* delay - approx. filter delay */
bridgeDelay->setDelay(baseDelay * betaRatio); /* bow to bridge length */
neckDelay->setDelay(baseDelay * (1.0 - betaRatio)); /* bow to nut (finger) length */
}
void Bowed :: startBowing(MY_FLOAT amplitude, MY_FLOAT rate)
{
adsr->setRate(rate);
adsr->keyOn();
maxVelocity = 0.03 + (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 * 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((1.0 - amp) * 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=0,nutRefl=0;
MY_FLOAT newVel=0,velDiff=0,stringVel=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 * (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 == MIDI_control1)
bowTabl->setSlope(5.0 - (4.0 * value * NORM_7));
else if (number == MIDI_control2) {
betaRatio = 0.027236 + (0.2 * value * NORM_7);
bridgeDelay->setDelay(baseDelay * betaRatio); /* bow to bridge length */
neckDelay->setDelay(baseDelay * (1.0 - betaRatio)); /* bow to nut (finger) length */
}
else if (number == MIDI_control3)
vibr->setFreq((value * NORM_7 * 12.0));
else if (number == MIDI_mod_wheel)
vibrGain = (value * NORM_7 * 0.4);
else if (number == MIDI_after_touch)
adsr->setTarget(value * NORM_7);
else {
printf("Bowed : Undefined Control Number!!\n");
}
}

56
Bowed.h
View File

@@ -1,56 +0,0 @@
/******************************************/
/* Bowed String model ala Smith */
/* after McIntyre, Schumacher, Woodhouse */
/* by Perry Cook, 1995-96 */
/* */
/* This is a waveguide model, and thus */
/* relates to various Stanford Univ. */
/* and possibly Yamaha and other patents.*/
/* */
/* Controls: CONTROL1 = bowPressure */
/* CONTROL2 = bowPosition */
/* CONTROL3 = vibrFreq */
/* MOD_WHEEL= vibrGain */
/* */
/******************************************/
#if !defined(__Bowed_h)
#define __Bowed_h
#include "Instrmnt.h"
#include "DLineL.h"
#include "BowTabl.h"
#include "OnePole.h"
#include "BiQuad.h"
#include "RawLoop.h"
#include "ADSR.h"
class Bowed : public Instrmnt
{
protected:
DLineL *neckDelay;
DLineL *bridgeDelay;
BowTabl *bowTabl;
OnePole *reflFilt;
BiQuad *bodyFilt;
RawLoop *vibr;
ADSR *adsr;
MY_FLOAT maxVelocity;
MY_FLOAT baseDelay;
MY_FLOAT vibrGain;
MY_FLOAT betaRatio;
public:
Bowed(MY_FLOAT lowestFreq);
~Bowed();
void clear();
void startBowing(MY_FLOAT amplitude,MY_FLOAT rate);
void stopBowing(MY_FLOAT rate);
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
virtual void noteOff(MY_FLOAT amp);
virtual void setFreq(MY_FLOAT frequency);
void setVibrato(MY_FLOAT amount);
virtual void controlChange(int number, MY_FLOAT value);
virtual MY_FLOAT tick();
};
#endif

129
Brass.cpp
View File

@@ -1,129 +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"
Brass :: Brass(MY_FLOAT lowestFreq)
{
length = (long) (SRATE / lowestFreq + 1);
delayLine = new DLineA(length);
lipFilter = new LipFilt;
dcBlock = new DCBlock;
adsr = new ADSR;
adsr->setAll(0.02, 0.05, 1.0, 0.001);
vibr = new RawLoop("rawwaves/sinewave.raw");
this->clear();
vibr->normalize();
vibr->setFreq(6.137);
vibrGain = 0.05; /* breath periodic vibrato component */
}
Brass :: ~Brass()
{
delete delayLine;
delete lipFilter;
delete dcBlock;
delete adsr;
delete vibr;
}
void Brass :: clear()
{
delayLine->clear();
lipFilter->clear();
dcBlock->clear();
/* adsr->reset(); */
}
void Brass :: setFreq(MY_FLOAT frequency)
{
slideTarget = ((MY_FLOAT) SRATE / frequency * 2.0) + 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 * 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 * 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(0.3 * breathPressure, /* mouth input */
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 == MIDI_control1) {
temp = lipTarget * pow(4.0,(2.0*value*NORM_7) - 1.0);
this->setLip(temp);
}
else if (number == MIDI_control2)
delayLine->setDelay(slideTarget * (0.5 + (value * NORM_7)));
else if (number == MIDI_control3)
vibr->setFreq((value * NORM_7 * 12.0));
else if (number == MIDI_mod_wheel)
vibrGain = (value * NORM_7 * 0.4);
else if (number == MIDI_after_touch)
adsr->setTarget(value * NORM_7);
else {
printf("Brass : Undefined Control Number!!\n");
}
}

53
Brass.h
View File

@@ -1,53 +0,0 @@
/******************************************/
/* Simple Brass Instrument Model ala */
/* Cook (TBone, HosePlayer) */
/* by Perry R. Cook, 1995-96 */
/* */
/* This is a waveguide model, and thus */
/* relates to various Stanford Univ. */
/* and possibly Yamaha and other patents.*/
/* */
/* Controls: CONTROL1 = lipTension */
/* CONTROL2 = slideLength */
/* CONTROL3 = vibFreq */
/* MOD_WHEEL= vibAmt */
/******************************************/
#if !defined(__Brass_h)
#define __Brass_h
#include "Instrmnt.h"
#include "DLineA.h"
#include "LipFilt.h"
#include "DCBlock.h"
#include "ADSR.h"
#include "RawLoop.h"
class Brass: public Instrmnt
{
protected:
DLineA *delayLine;
LipFilt *lipFilter;
DCBlock *dcBlock;
ADSR *adsr;
RawLoop *vibr;
long length;
MY_FLOAT lipTarget;
MY_FLOAT slideTarget;
MY_FLOAT vibrGain;
MY_FLOAT maxPressure;
public:
Brass(MY_FLOAT lowestFreq);
~Brass();
void clear();
virtual void setFreq(MY_FLOAT frequency);
void setLip(MY_FLOAT frequency);
void startBlowing(MY_FLOAT amplitude,MY_FLOAT rate);
void stopBlowing(MY_FLOAT rate);
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
virtual void noteOff(MY_FLOAT amp);
virtual void controlChange(int number, MY_FLOAT value);
virtual MY_FLOAT tick();
};
#endif

View File

@@ -1,125 +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"
Clarinet :: Clarinet(MY_FLOAT lowestFreq)
{
length = (long) (SRATE / lowestFreq + 1);
delayLine = new DLineL(length);
reedTable = new ReedTabl;
reedTable->setOffset(0.7);
reedTable->setSlope(-0.3);
filter = new OneZero;
envelope = new Envelope;
noise = new Noise;
vibr = new RawLoop("rawwaves/sinewave.raw");
vibr->normalize();
vibr->setFreq(5.735);
outputGain = 1.0;
noiseGain = 0.2;
vibrGain = 0.1;
}
Clarinet :: ~Clarinet()
{
delete delayLine;
delete reedTable;
delete filter;
delete envelope;
delete noise;
delete vibr;
}
void Clarinet :: clear()
{
delayLine->clear();
filter->tick(0.0);
}
void Clarinet :: setFreq(MY_FLOAT frequency)
{
delayLine->setDelay /* length - approx filter delay */
((SRATE / frequency) * 0.5 - 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(0.0);
}
void Clarinet :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
{
this->setFreq(freq);
this->startBlowing(0.55 + (amp * 0.30),amp * 0.005);
outputGain = amp + 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 * 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 * -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 == MIDI_control1)
reedTable->setSlope(-0.44 + (0.26 * value * NORM_7));
else if (number == MIDI_control2)
noiseGain = (value * NORM_7 * 0.4);
else if (number == MIDI_control3)
vibr->setFreq((value * NORM_7 * 12.0));
else if (number == MIDI_mod_wheel)
vibrGain = (value * NORM_7 * 0.5);
else if (number == MIDI_after_touch) {
envelope->setValue(value * NORM_7);
}
else {
printf("Clarinet : Undefined Control Number!!\n");
}
}

View File

@@ -1,53 +0,0 @@
/******************************************/
/* Clarinet model ala Smith */
/* after McIntyre, Schumacher, Woodhouse */
/* by Perry Cook, 1995-96 */
/* */
/* This is a waveguide model, and thus */
/* relates to various Stanford Univ. */
/* and possibly Yamaha and other patents.*/
/* */
/* Controls: CONTROL1 = reedStiffns */
/* CONTROL2 = noiseGain */
/* CONTROL3 = vibFreq */
/* MOD_WHEEL= vibAmt */
/******************************************/
#if !defined(__Clarinet_h)
#define __Clarinet_h
#include "Instrmnt.h"
#include "DLineL.h"
#include "ReedTabl.h"
#include "OneZero.h"
#include "Envelope.h"
#include "Noise.h"
#include "RawLoop.h"
class Clarinet : public Instrmnt
{
protected:
DLineL *delayLine;
ReedTabl *reedTable;
OneZero *filter;
Envelope *envelope;
Noise *noise;
RawLoop *vibr;
long length;
MY_FLOAT outputGain;
MY_FLOAT noiseGain;
MY_FLOAT vibrGain;
public:
Clarinet(MY_FLOAT lowestFreq);
~Clarinet();
void clear();
virtual void setFreq(MY_FLOAT frequency);
void startBlowing(MY_FLOAT amplitude,MY_FLOAT rate);
void stopBlowing(MY_FLOAT rate);
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
virtual void noteOff(MY_FLOAT amp);
virtual MY_FLOAT tick();
virtual void controlChange(int number, MY_FLOAT value);
};
#endif

View File

@@ -1,41 +0,0 @@
/*******************************************/
/* DC Blocking Filter */
/* by Perry R. Cook, 1995-96 */
/* This guy is very helpful in, uh, */
/* blocking DC. Needed because a simple */
/* low-pass reflection filter allows DC */
/* to build up inside recursive */
/* structures. */
/*******************************************/
#include "DCBlock.h"
DCBlock :: DCBlock()
{
inputs = (MY_FLOAT *) malloc(MY_FLOAT_SIZE);
outputs = (MY_FLOAT *) malloc(MY_FLOAT_SIZE);
this->clear();
}
DCBlock :: ~DCBlock()
{
free(inputs);
free(outputs);
}
void DCBlock :: clear()
{
outputs[0] = 0.0;
inputs[0] = 0.0;
lastOutput = 0.0;
}
MY_FLOAT DCBlock :: tick(MY_FLOAT sample)
{
outputs[0] = sample - inputs[0] + (0.99 * outputs[0]);
inputs[0] = sample;
lastOutput = outputs[0];
return lastOutput;
}

View File

@@ -1,25 +0,0 @@
/*******************************************/
/* DC Blocking Filter */
/* by Perry R. Cook, 1995-96 */
/* This guy is very helpful in, uh, */
/* blocking DC. Needed because a simple */
/* low-pass reflection filter allows DC */
/* to build up inside recursive */
/* structures. */
/*******************************************/
#if !defined(__DCBlock_h)
#define __DCBlock_h
#include "Filter.h"
class DCBlock : public Filter
{
public:
DCBlock();
~DCBlock();
void clear();
MY_FLOAT tick(MY_FLOAT sample);
};
#endif

View File

@@ -1,104 +0,0 @@
/*******************************************/
/* */
/* AllPass Interpolating Delay Line */
/* Object by Perry R. Cook 1995-96 */
/* This one uses a delay line of maximum */
/* length specified on creation, and */
/* interpolates fractional length using */
/* an all-pass filter. This version is */
/* more efficient for computing static */
/* length delay lines (alpha and coeff */
/* are computed only when the length */
/* is set, there probably is a more */
/* efficient computational form if alpha */
/* is changed often (each sample)). */
/* */
/*******************************************/
#include "DLineA.h"
DLineA :: DLineA(long max_length)
{
long i;
length = max_length;
inputs = (MY_FLOAT *) malloc(length * MY_FLOAT_SIZE);
for (i=0;i<length;i++) inputs[i] = 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] = 0.0;
lastIn = 0;
lastOutput = 0;
}
void DLineA :: setDelay(MY_FLOAT lag)
{
MY_FLOAT outputPointer;
outputPointer = inPoint - lag + 2; /* outPoint chases inpoint */
/* + 2 for interp and other */
while (outputPointer<0)
outputPointer += length; /* modulo table length */
outPoint = (long) outputPointer; /* Integer part of delay */
alpha = 1.0 + outPoint - outputPointer; /* fractional part of delay */
if (alpha<0.1) {
outputPointer += 1.0; /* Hack to avoid pole/zero */
outPoint += 1; /* cancellation. Keeps allpass */
alpha += 1.0; /* delay in range of .1 to 1.1 */
}
coeff = (1.0 - alpha) / (1.0 + alpha); /* coefficient for all pass */
}
MY_FLOAT DLineA :: tick(MY_FLOAT sample) /* Take sample, yield sample */
{
MY_FLOAT temp;
inputs[inPoint++] = sample; /* Write input sample */
if (inPoint == length) /* Increment input pointer */
inPoint -= length; /* modulo length */
temp = inputs[outPoint++]; /* filter input */
if (outPoint == length) /* Increment output pointer */
outPoint -= length; /* modulo length */
lastOutput = -coeff * lastOutput; /* delayed output */
lastOutput += lastIn + (coeff * temp); /* input + delayed Input */
lastIn = temp;
return lastOutput; /* save output and return */
}
/************ Test Main Program *****************/
/*
void main()
{
DLineA delay(140);
FILE *fd;
MY_FLOAT temp;
short data;
long i;
fd = fopen("test.raw","wb");
delay.setDelay(128);
for (i=0;i<4096;i++) {
if (i%256 != 0) temp = 0.0; else temp = 1.0;
data = (temp + delay.tick(temp)) * 16000.0;
fwrite(&data,2,1,fd);
}
delay.setDelay(64.5);
for (i=0;i<4096;i++) {
if (i%256 != 0) temp = 0.0; else temp = 1.0;
data = (temp + delay.tick(temp)) * 16000.0;
fwrite(&data,2,1,fd);
}
fclose(fd);
}
*/

View File

@@ -1,41 +0,0 @@
/*******************************************/
/* */
/* AllPass Interpolating Delay Line */
/* Object by Perry R. Cook 1995-96 */
/* This one uses a delay line of maximum */
/* length specified on creation, and */
/* interpolates fractional length using */
/* an all-pass filter. This version is */
/* more efficient for computing static */
/* length delay lines (alpha and coeff */
/* are computed only when the length */
/* is set, there probably is a more */
/* efficient computational form if alpha */
/* is changed often (each sample)). */
/* */
/*******************************************/
#if !defined(__DLineA_h)
#define __DLineA_h
#include "Filter.h"
class DLineA : public Filter
{
protected:
long inPoint;
long outPoint;
long length;
MY_FLOAT alpha;
MY_FLOAT coeff;
MY_FLOAT lastIn;
public:
DLineA(long max_length);
~DLineA();
void clear();
void setDelay(MY_FLOAT length);
MY_FLOAT tick(MY_FLOAT sample);
};
#endif

View File

@@ -1,90 +0,0 @@
/*******************************************/
/* Linearly Interpolating Delay Line */
/* Object by Perry R. Cook 1995-96 */
/* This one uses a delay line of maximum */
/* length specified on creation, and */
/* linearly interpolates fractional */
/* length. It is designed to be more */
/* efficient if the delay length is not */
/* changed very often. */
/*******************************************/
#include "DLineL.h"
DLineL :: DLineL(long max_length)
{
length = max_length;
inputs = (MY_FLOAT *) malloc(length * MY_FLOAT_SIZE);
this->clear();
outPoint = 0;
inPoint = length >> 1;
}
DLineL :: ~DLineL()
{
free(inputs);
}
void DLineL :: clear()
{
long i;
for (i=0;i<length;i++) inputs[i] = 0.0;
lastOutput = 0;
}
void DLineL :: setDelay(MY_FLOAT lag)
{
MY_FLOAT outputPointer;
outputPointer = inPoint - lag; /* read chases write, add 1 for interp. */
while (outputPointer<0)
outputPointer += length; /* modulo maximum length */
outPoint = (long) outputPointer; /* integer part */
alpha = outputPointer - outPoint; /* fractional part */
omAlpha = 1.0 - alpha; /* 1.0 - fractional part (more efficient) */
}
MY_FLOAT DLineL :: tick(MY_FLOAT sample) /* Take one, yield one */
{
inputs[inPoint++] = sample; /* Input next sample */
if (inPoint == length) /* Check for end condition */
inPoint -= length;
lastOutput = inputs[outPoint++] * omAlpha; /* first 1/2 of interpolation */
if (outPoint<length) { /* Check for end condition */
lastOutput += inputs[outPoint] * alpha; /* second 1/2 of interpolation */
}
else { /* if at end . . . */
lastOutput += inputs[0] * alpha; /* second 1/2 of interpolation */
outPoint -= length;
}
return lastOutput;
}
/************ Test Main Program *****************/
/*
void main()
{
DLineL delay(140);
FILE *fd;
MY_FLOAT temp;
short data;
long i;
fd = fopen("test.raw","wb");
delay.setDelay(128);
for (i=0;i<4096;i++) {
if (i%256 != 0) temp = 0.0; else temp = 1.0;
data = (temp + delay.tick(temp)) * 16000.0;
fwrite(&data,2,1,fd);
}
delay.setDelay(64.5);
for (i=0;i<4096;i++) {
if (i%256 != 0) temp = 0.0; else temp = 1.0;
data = (temp + delay.tick(temp)) * 16000.0;
fwrite(&data,2,1,fd);
}
fclose(fd);
}
*/

View File

@@ -1,33 +0,0 @@
/*******************************************/
/* Linearly Interpolating Delay Line */
/* Object by Perry R. Cook 1995-96 */
/* This one uses a delay line of maximum */
/* length specified on creation, and */
/* linearly interpolates fractional */
/* length. It is designed to be more */
/* efficient if the delay length is not */
/* changed very often. */
/*******************************************/
#if !defined(__DLineL_h)
#define __DLineL_h
#include "Filter.h"
class DLineL : public Filter
{
protected:
long inPoint;
long outPoint;
long length;
MY_FLOAT alpha;
MY_FLOAT omAlpha;
public:
DLineL(long max_length);
~DLineL();
void clear();
void setDelay(MY_FLOAT length);
MY_FLOAT tick(MY_FLOAT sample);
};
#endif

View File

@@ -1,80 +0,0 @@
/*******************************************/
/* Non-Interpolating Delay Line */
/* Object by Perry R. Cook 1995-96 */
/* This one uses a delay line of maximum */
/* length specified on creation. A non- */
/* interpolating delay line should be */
/* used in non-time varying (reverb) or */
/* non-critical (????) applications. */
/*******************************************/
#include "DLineN.h"
DLineN :: DLineN(long max_length)
{
length = max_length;
inputs = (MY_FLOAT *) malloc(length * MY_FLOAT_SIZE);
this->clear();
this->setDelay(length * 0.5);
inPoint = 0;
outPoint = 0;
}
DLineN :: ~DLineN()
{
free(inputs);
}
void DLineN :: clear()
{
long i;
for (i=0;i<length;i++) inputs[i] = 0.0;
lastOutput = 0;
}
void DLineN :: setDelay(MY_FLOAT lag)
{
outPoint = inPoint - (long) lag; /* read chases write */
while (outPoint<0) outPoint += length; /* modulo maximum length */
}
MY_FLOAT DLineN :: tick(MY_FLOAT sample) /* Take one, yield one */
{
inputs[inPoint++] = sample; /* Input next sample */
if (inPoint == length) /* Check for end condition */
inPoint -= length;
lastOutput = inputs[outPoint++]; // first 1/2 of interpolation */
if (outPoint>=length) { // Check for end condition */
outPoint -= length;
}
return lastOutput;
}
/************ Test Main Program *****************/
/*
void main()
{
DLineN delay(140);
FILE *fd;
MY_FLOAT temp;
short data;
long i;
fd = fopen("test.raw","wb");
delay.setDelay(128);
for (i=0;i<4096;i++) {
if (i%256 != 0) temp = 0.0; else temp = 1.0;
data = (temp + delay.tick(temp)) * 16000.0;
fwrite(&data,2,1,fd);
}
delay.setDelay(64.5);
for (i=0;i<4096;i++) {
if (i%256 != 0) temp = 0.0; else temp = 1.0;
data = (temp + delay.tick(temp)) * 16000.0;
fwrite(&data,2,1,fd);
}
fclose(fd);
}
*/

View File

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

View File

@@ -1,164 +0,0 @@
/*******************************************/
/* Master Class for Drum Synthesizer */
/* by Perry R. Cook, 1995-96 */
/* This instrument contains a bunch of */
/* RawWvIn objects (Non-Interpolating, */
/* 1 shot players), run through a bunch */
/* of one-pole filters. You can specify */
/* the maximum Polyphony (maximum number */
/* of simultaneous voices) in a #define */
/* in the .h file. */
/*******************************************/
#include "DrumSynt.h"
#include <string.h>
char waveNames[DRUM_NUMWAVES][16] = {
"bass.raw",
"snar.raw",
"tomlow.raw",
"tommid.raw",
"tomhi.raw",
"hat.raw",
"ride.raw",
"crash.raw",
"cowbell.raw",
"tamb.raw"
};
DrumSynt :: DrumSynt() : Object()
{
int i;
/* char temp[64]; */
/* for (i=0;i<DRUM_NUMWAVES;i++) { */
/* strcpy(temp,"rawwaves/drumwavs/"); */
/* strcat(temp,waveNames[i]); */
/* waves[i] = new RawWvIn(temp); */
/* waves[i]->finish(); */
/* waves[i]->normalize(0.2); */
/* } */
for (i=0;i<DRUM_POLYPHONY;i++) {
filters[i] = new OnePole;
sounding[i] = -1;
/* filtSounding[i] = -1; */
}
numSounding = 0; /* This counts the number */
/* of sounding voices */
}
void DrumSynt :: noteOn(int noteNum, int vel)
{
int i,notDone;
char tempString[64];
RawWvIn *tempWv;
OnePole *tempFilt;
printf("NoteOn: %s vel=%i\n",waveNames[noteNum],vel);
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]; /* oldest voice and */
filters[i] = filters[i+1]; /* ripple all down */
}
waves[DRUM_POLYPHONY-1] = tempWv;
filters[DRUM_POLYPHONY-1] = tempFilt;
}
else {
numSounding += 1; /* otherwise just add one */
}
sounding[numSounding-1] = noteNum; /* allocate new wave */
strcpy(tempString,"rawwaves/drumwavs/");
strcat(tempString,waveNames[noteNum]);
waves[numSounding-1] = new RawWvIn(tempString);
waves[numSounding-1]->normalize(0.2);
filters[numSounding-1]->setPole(0.999 - (vel / 32.0));
filters[numSounding-1]->setGain(vel / 128.0);
}
else {
waves[notDone]->reset();
filters[notDone]->setPole(0.999 - (vel / 32.0));
filters[notDone]->setGain(vel / 128.0);
}
printf("Number Sounding = %i\n",numSounding);
for (i=0;i<numSounding;i++) printf(" %i ",sounding[i]);
printf("\n");
}
MY_FLOAT DrumSynt :: tick()
{
int i, j, notDone;
MY_FLOAT output;
OnePole *tempFilt;
i = 0;
notDone = 1;
output = 0.0;
if (numSounding == 0) notDone = 0;
while (notDone && (i < numSounding)) {
output += waves[i]->lastOut();
if (waves[i]->informTick() == 1) {
printf("Wave %i %i down here\n",i,sounding[i]);
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;
if (numSounding == 0) notDone = 0;
i -= 1;
}
i++;
}
return output;
}
/************** Test Main Program *********************/
#include "miditabl.h"
#include "RawWvOut.h"
#include "Reverb.h"
#include "Noise.h"
int main()
{
long i,j;
DrumSynt instrument;
RawWvOut output("test.snd");
Reverb reverb(2137);
Noise noise;
for (j=0;j<100;j++) {
i = (int) (fabs(noise.tick()) * DRUM_NUMWAVES);
instrument.noteOn(i,127);
for (i=0;i<2000;i++) output.tick(reverb.tick(instrument.tick()));
}
for (i=0;i<22000;i++) output.tick(reverb.tick(instrument.tick()));
}

View File

@@ -1,37 +0,0 @@
/*******************************************/
/* Master Class for Drum Synthesizer */
/* by Perry R. Cook, 1995-96 */
/* This instrument contains a bunch of */
/* RawWvIn objects (Non-Interpolating, */
/* 1 shot players), run through a bunch */
/* of one-pole filters. You can specify */
/* the maximum Polyphony (maximum number */
/* of simultaneous voices) in a #define */
/* in the .h file. */
/*******************************************/
#if !defined(__DrumSynt_h)
#define __DrumSynt_h
#include "Object.h"
#include "RawWvIn.h"
#include "OnePole.h"
#define DRUM_NUMWAVES 10
#define DRUM_POLYPHONY 4
class DrumSynt : public Object
{
protected:
RawWvIn *waves[DRUM_POLYPHONY];
OnePole *filters[DRUM_POLYPHONY];
int sounding[DRUM_POLYPHONY];
int numSounding;
public:
DrumSynt();
/* ~DrumSynt(); */
void noteOn(int noteNum, int vel);
MY_FLOAT tick();
};
#endif

View File

@@ -1,113 +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 = 0.0;
value = 0.0;
rate = 0.001;
state = 0;
}
Envelope :: ~Envelope()
{
}
void Envelope :: keyOn()
{
target = 1.0;
if (value != target) state = 1;
}
void Envelope :: keyOff()
{
target = 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;
rate = rate * RATE_NORM; /* SEE Object.h */
}
void Envelope :: setTarget(MY_FLOAT aTarget)
{
target = aTarget;
if (value != target) state = 1;
}
void Envelope :: setValue(MY_FLOAT aValue)
{
state = 0;
target = aValue;
value = aValue;
}
MY_FLOAT Envelope :: tick()
{
if (state) {
if (target > value) {
value += rate;
if (value >= target) {
value = target;
state = 0;
}
}
else {
value -= rate;
if (value <= target) {
value = target;
state = 0;
}
}
}
return value;
}
int Envelope :: informTick()
{
this->tick();
return state;
}
MY_FLOAT Envelope :: lastOut()
{
return value;
}
/************ Test Main ************************/
/*
void main()
{
long i;
Envelope test;
test.setRate(0.15);
test.keyOn();
for (i=0;i<10;i++) printf("%lf\n",test.tick());
test.setRate(0.1);
test.setTarget(0.5);
while (test.informTick()) printf("%lf\n",test.lastOut());
test.setRate(0.05);
test.keyOff();
while(test.informTick()) printf("%lf\n",test.lastOut());
}
*/

View File

@@ -1,40 +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();
~Envelope();
void keyOn();
void keyOff();
void setRate(MY_FLOAT aRate);
void setTarget(MY_FLOAT aTarget);
void setValue(MY_FLOAT aValue);
MY_FLOAT tick();
int informTick();
MY_FLOAT lastOut();
};
#endif

View File

@@ -1,51 +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. */
}
MY_FLOAT FM4Alg3 :: tick()
{
MY_FLOAT temp;
temp = vibWave->tick() * modDepth * 0.2;
waves[0]->setFreq(baseFreq * (1.0 + temp) * ratios[0]);
waves[1]->setFreq(baseFreq * (1.0 + temp) * ratios[1]);
waves[2]->setFreq(baseFreq * (1.0 + temp) * ratios[2]);
waves[3]->setFreq(baseFreq * (1.0 + temp) * ratios[3]);
temp = gains[2] * adsr[2]->tick() * waves[2]->tick();
waves[1]->addPhaseOffset(temp);
waves[3]->addPhaseOffset(twozero->lastOut());
temp = (1.0 - (control2 * 0.5)) * gains[3] * adsr[3]->tick() * waves[3]->tick();
twozero->tick(temp);
temp += control2 * 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 * 0.5;
return lastOutput;
}

View File

@@ -1,29 +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();
MY_FLOAT tick();
};
#endif

View File

@@ -1,48 +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. */
}
MY_FLOAT FM4Alg4 :: tick()
{
MY_FLOAT temp;
temp = vibWave->tick() * modDepth * 0.2;
waves[0]->setFreq(baseFreq * (1.0 + temp) * ratios[0]);
waves[1]->setFreq(baseFreq * (1.0 + temp) * ratios[1]);
waves[2]->setFreq(baseFreq * (1.0 + temp) * ratios[2]);
waves[3]->setFreq(baseFreq * (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 = (1.0 - (control2 * 0.5)) * gains[2] * adsr[2]->tick() * waves[2]->tick();
temp += control2 * 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 * 0.5;
return lastOutput;
}

View File

@@ -1,29 +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();
MY_FLOAT tick();
};
#endif

View File

@@ -1,48 +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. */
}
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 = (1.0 - (control2 * 0.5)) * gains[0] * adsr[0]->tick() * waves[0]->tick();
temp += control2 * 0.5 * gains[2] * adsr[2]->tick() * waves[2]->tick();
temp2 = vibWave->tick() * modDepth; /* Calculate amplitude mod */
temp = temp * (1.0 + temp2); /* and apply it to output */
lastOutput = temp * 0.5;
return lastOutput;
}

View File

@@ -1,32 +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();
MY_FLOAT tick();
};
#endif

View File

@@ -1,54 +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. */
}
MY_FLOAT FM4Alg6 :: tick()
{
MY_FLOAT temp,temp2;
temp = gains[3] * adsr[3]->tick() * waves[3]->tick();
temp2 = vibWave->tick() * modDepth * 0.1; /* Calculate frequency mod */
waves[0]->setFreq(baseFreq * (1.0 + temp2) * ratios[0]);
waves[1]->setFreq(baseFreq * (1.0 + temp2) * ratios[1]);
waves[2]->setFreq(baseFreq * (1.0 + temp2) * ratios[2]);
waves[3]->setFreq(baseFreq * (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 * 0.33;
}
void FM4Alg6 :: controlChange(int number, MY_FLOAT value)
{
}

View File

@@ -1,35 +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();
MY_FLOAT tick();
virtual void controlChange(int number, MY_FLOAT value);
};
#endif

View File

@@ -1,43 +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. */
}
MY_FLOAT FM4Alg8 :: tick()
{
MY_FLOAT temp;
waves[3]->addPhaseOffset(twozero->lastOut());
temp = control1 * 2.0 * gains[3] * adsr[3]->tick() * waves[3]->tick();
twozero->tick(temp);
temp += control2 * 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 * 0.125;
return lastOutput;
}

View File

@@ -1,33 +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 MY_FLOAT tick();
};
#endif

179
FM4Op.cpp
View File

@@ -1,179 +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"
FM4Op :: FM4Op()
{
int i;
MY_FLOAT temp;
MY_FLOAT tempCoeffs[2] = {0.0, -1.0};
adsr[0] = new ADSR;
adsr[1] = new ADSR;
adsr[2] = new ADSR;
adsr[3] = new ADSR;
twozero = new TwoZero;
vibWave = new RawLoop("rawwaves/sinewave.raw");
vibWave->normalize();
vibWave->setFreq(6.0); /* should make this random?? */
modDepth = 0.0;
/* We don't make the waves here yet, because */
/* we don't know what they will be. */
baseFreq = 440.0;
ratios[0] = 1.0;
ratios[1] = 1.0;
ratios[2] = 1.0;
ratios[3] = 1.0;
gains[0] = 1.0;
gains[1] = 1.0;
gains[2] = 1.0;
gains[3] = 1.0;
twozero->setZeroCoeffs(tempCoeffs);
twozero->setGain(0.0);
control1 = 1.0;
control2 = 1.0;
temp = 1.0;
for (i=99;i>=0;i--) {
__FM4Op_gains[i] = temp;
temp *= 0.933033;
}
temp = 1.0;
for (i=15;i>=0;i--) {
__FM4Op_susLevels[i] = temp;
temp *= 0.707101;
}
temp = 8.498186;
for (i=0;i<32;i++) {
__FM4Op_attTimes[i] = temp;
temp *= 0.707101;
}
}
FM4Op :: ~FM4Op()
{
delete adsr[0];
delete adsr[1];
delete adsr[2];
delete adsr[3];
delete waves[0];
delete waves[1];
delete waves[2];
delete waves[3];
delete vibWave;
delete twozero;
}
void FM4Op :: loadWaves(char* wave1, char* wave2, char* wave3, char* wave4)
{
int i;
waves[0] = new RawLoop(wave1);
waves[1] = new RawLoop(wave2);
waves[2] = new RawLoop(wave3);
waves[3] = new RawLoop(wave4);
for (i=0;i<4;i++) {
waves[i]->normalize();
}
}
void FM4Op :: setFreq(MY_FLOAT frequency)
{
baseFreq = frequency;
waves[0]->setFreq(baseFreq * ratios[0]);
waves[1]->setFreq(baseFreq * ratios[1]);
waves[2]->setFreq(baseFreq * ratios[2]);
waves[3]->setFreq(baseFreq * ratios[3]);
}
void FM4Op :: setRatio(int whichOne, MY_FLOAT ratio)
{
ratios[whichOne] = ratio;
if (ratio>0.0)
waves[whichOne]->setFreq(baseFreq * ratio);
else
waves[whichOne]->setFreq(ratio);
}
void FM4Op :: setGain(int whichOne, MY_FLOAT gain)
{
gains[whichOne]=gain;
}
void FM4Op :: keyOn()
{
adsr[0]->keyOn();
adsr[1]->keyOn();
adsr[2]->keyOn();
adsr[3]->keyOn();
}
void FM4Op :: keyOff()
{
adsr[0]->keyOff();
adsr[1]->keyOff();
adsr[2]->keyOff();
adsr[3]->keyOff();
}
void FM4Op :: noteOff(MY_FLOAT amp)
{
this->keyOff();
#if defined(_debug_)
printf("FM4Op : NoteOff: Amp=%lf\n",amp);
#endif
}
void FM4Op :: setModulationSpeed(MY_FLOAT mSpeed)
{
vibWave->setFreq(mSpeed);
}
void FM4Op :: setModulationDepth(MY_FLOAT mDepth)
{
modDepth = mDepth;
}
void FM4Op :: setControl1(MY_FLOAT cVal)
{
control1 = cVal*2.0;
}
void FM4Op :: setControl2(MY_FLOAT cVal)
{
control2 = cVal*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 == MIDI_control1)
this->setControl1(value * NORM_7);
else if (number == MIDI_control2)
this->setControl2(value * NORM_7);
else if (number == MIDI_control3)
this->setModulationSpeed(value * NORM_7 * 12.0); /* 0 to 12 Hz */
else if (number == MIDI_mod_wheel)
this->setModulationDepth(value * NORM_7);
else if (number == MIDI_after_touch) {
adsr[0]->setTarget(value * NORM_7);
adsr[1]->setTarget(value * NORM_7);
adsr[2]->setTarget(value * NORM_7);
adsr[3]->setTarget(value * NORM_7);
}
else {
printf("FM4Op : Undefined Control Number!!\n");
}
}

59
FM4Op.h
View File

@@ -1,59 +0,0 @@
/*******************************************/
/* Master Class for 4 Operator FM Synth */
/* by Perry R. Cook, 1995-96 */
/* This instrument contains an 4 waves, */
/* 4 envelopes, and various state vars. */
/* */
/* The basic Chowning/Stanford FM patent */
/* expired April 1995, but there exist */
/* follow-on patents, mostly assigned to */
/* Yamaha. If you are of the type who */
/* should worry about this (making money) */
/* worry away. */
/* */
/*******************************************/
#if !defined(__FM4Op_h)
#define __FM4Op_h
#include "Instrmnt.h"
#include "ADSR.h"
#include "RawLoop.h"
#include "TwoZero.h"
class FM4Op : public Instrmnt
{
protected:
ADSR *adsr[4];
RawLoop *waves[4];
RawLoop *vibWave;
TwoZero *twozero;
MY_FLOAT baseFreq;
MY_FLOAT ratios[4];
MY_FLOAT gains[4];
MY_FLOAT modDepth;
MY_FLOAT control1;
MY_FLOAT control2;
MY_FLOAT __FM4Op_gains[100];
MY_FLOAT __FM4Op_susLevels[16];
MY_FLOAT __FM4Op_attTimes[32];
public:
FM4Op();
~FM4Op();
void loadWaves(char* wave1, char* wave2, char* wave3, char* wave4);
void clear();
void setFreq(MY_FLOAT frequency);
void setRatio(int whichOne, MY_FLOAT ratio);
void setGain(int whichOne, MY_FLOAT gain);
void keyOn();
void keyOff();
void noteOff(MY_FLOAT amp);
/* There's no tick() method here, because that depends on the algorithm */
void setModulationSpeed(MY_FLOAT mSpeed);
void setModulationDepth(MY_FLOAT mDepth);
void setControl1(MY_FLOAT cVal);
void setControl2(MY_FLOAT cVal);
virtual void controlChange(int number, MY_FLOAT value);
};
#endif

View File

@@ -1,118 +0,0 @@
/******************************************/
/* Singing Voice Synthesis Subclass */
/* of Algorithm 6 (TX81Z) Subclass of */
/* 4 Operator FM Synth */
/* by Perry R. Cook, 1996 */
/******************************************/
#include "FMVoices.h"
FMVoices :: FMVoices() : FM4Alg6()
{
this->loadWaves("rawwaves/sinewave.raw",
"rawwaves/sinewave.raw",
"rawwaves/sinewave.raw",
"rawwaves/sinewave.raw");
this->setRatio(0,2.00);
this->setRatio(1,4.00);
this->setRatio(2,12.0);
this->setRatio(3,1.00);
gains[3] = __FM4Op_gains[80];
adsr[0]->setAll(0.001,0.001,__FM4Op_susLevels[15],0.001);
adsr[1]->setAll(0.001,0.001,__FM4Op_susLevels[15],0.001);
adsr[2]->setAll(0.001,0.001,__FM4Op_susLevels[15],0.001);
adsr[3]->setAll(0.05,0.05,__FM4Op_susLevels[15],0.0001);
twozero->setGain(0.0);
modDepth = 0.005;
currentVowel = 0;
tilt[0] = 1.0;
tilt[1] = 0.5;
tilt[2] = 0.2;
mods[0] = 1.0;
mods[1] = 1.1;
mods[2] = 1.1;
baseFreq = 110.0;
this->setFreq(110.0);
}
#include "phonTabl.h"
void FMVoices :: setFreq(MY_FLOAT frequency)
{
MY_FLOAT temp,temp2;
int tempi,tempi2;
if (currentVowel < 16) {
tempi2 = currentVowel;
temp2 = 0.9;
}
else if (currentVowel < 32) {
tempi2 = currentVowel - 16;
temp2 = 1.0;
}
else if (currentVowel < 48) {
tempi2 = currentVowel - 32;
temp2 = 1.1;
}
else if (currentVowel < 64) {
tempi2 = currentVowel - 48;
temp2 = 1.2;
}
baseFreq = frequency;
temp = (temp2 * phonParams[tempi2][0][0] / baseFreq) + 0.5;
tempi = (int) temp;
this->setRatio(0,(MY_FLOAT) tempi);
temp = (temp2 * phonParams[tempi2][1][0] / baseFreq) + 0.5;
tempi = (int) temp;
this->setRatio(1,(MY_FLOAT) tempi);
temp = (temp2 * phonParams[tempi2][2][0] / baseFreq) + 0.5;
tempi = (int) temp;
this->setRatio(2,(MY_FLOAT) tempi);
gains[0] = 1.0; // pow(10.0,phonParams[tempi2][0][2] * 0.05);
gains[1] = 1.0; // pow(10.0,phonParams[tempi2][1][2] * 0.05);
gains[2] = 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 == MIDI_control1)
gains[3] = __FM4Op_gains[(int) (value * 0.78125)];
else if (number == MIDI_control2) {
tempi = (int) (value / 2);
currentVowel = tempi;
this->setFreq(baseFreq);
}
else if (number == MIDI_control3)
this->setModulationSpeed(value * NORM_7 * 12.0); /* 0 to 12 Hz */
else if (number == MIDI_mod_wheel)
this->setModulationDepth(value * NORM_7);
else if (number == MIDI_after_touch) {
temp = value * NORM_7;
tilt[0] = temp;
tilt[1] = temp * temp;
tilt[2] = temp * temp * temp;
}
else {
printf("FM4Op : Undefined Control Number!!\n");
}
}

View File

@@ -1,24 +0,0 @@
/******************************************/
/* Singing Voice Synthesis Subclass */
/* of Algorithm 6 (TX81Z) Subclass of */
/* 4 Operator FM Synth */
/* by Perry R. Cook, 1996 */
/******************************************/
#if !defined(__FMVoices_h)
#define __FMVoices_h
#include "FM4Alg6.h"
class FMVoices : public FM4Alg6
{
protected:
int currentVowel;
public:
FMVoices();
virtual void setFreq(MY_FLOAT frequency);
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
virtual void controlChange(int number, MY_FLOAT value);
};
#endif

View File

@@ -1,24 +0,0 @@
/*******************************************/
/* Filter Class, by Perry R. Cook, 1995-96*/
/* This is the base class for all filters.*/
/* To me, most anything is a filter, but */
/* I'll be a little less general here, and*/
/* define a filter as something which has */
/* input(s), output(s), and gain. */
/*******************************************/
#include "Filter.h"
Filter :: Filter() : Object()
{
}
Filter :: ~Filter()
{
}
MY_FLOAT Filter :: lastOut()
{
return lastOutput;
}

View File

@@ -1,28 +0,0 @@
/*******************************************/
/* Filter Class, by Perry R. Cook, 1995-96*/
/* This is the base class for all filters.*/
/* To me, most anything is a filter, but */
/* I'll be a little less general here, and*/
/* define a filter as something which has */
/* input(s), output(s), and gain. */
/*******************************************/
#if !defined(__Filter_h)
#define __Filter_h
#include "Object.h"
class Filter : public Object
{
protected:
MY_FLOAT gain;
MY_FLOAT *outputs;
MY_FLOAT *inputs;
MY_FLOAT lastOutput;
public:
Filter();
~Filter();
MY_FLOAT lastOut();
};
#endif

172
Flute.cpp
View File

@@ -1,172 +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"
Flute :: Flute(MY_FLOAT lowestFreq)
{
long length;
length = (long) (SRATE / lowestFreq + 1);
boreDelay = new DLineL(length);
length >> 1;
jetDelay = new DLineL(length);
jetTable = new JetTabl;
filter = new OnePole;
dcBlock = new DCBlock;
noise = new Noise;
adsr = new ADSR;
vibr = new RawLoop("rawwaves/sinewave.raw");
this->clear();
boreDelay->setDelay(100.0);
jetDelay->setDelay(49.0);
filter->setPole(0.7 - (0.1 * RATE_NORM));
filter->setGain(-1.0);
vibr->normalize();
vibr->setFreq(5.925);
adsr->setAll(0.02, 0.05, 0.8, 0.001);
endRefl = 0.5;
jetRefl = 0.5;
noiseGain = 0.15; /* Breath pressure random component */
vibrGain = 0.05; /* breath periodic vibrato component */
jetRatio = 0.32;
}
Flute :: ~Flute()
{
delete jetDelay;
delete boreDelay;
delete jetTable;
delete filter;
delete dcBlock;
delete noise;
delete adsr;
delete vibr;
}
void Flute :: clear()
{
jetDelay->clear();
boreDelay->clear();
filter->clear();
dcBlock->clear();
/* adsr->reset(); */
}
void Flute :: setFreq(MY_FLOAT frequency)
{
MY_FLOAT temp;
lastFreq = frequency * 0.66666; /* we're overblowing here */
temp = SRATE / lastFreq - 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 / 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(1.1 + (amp * 0.20),amp * 0.02);
outputGain = amp + 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 * 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 - 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 = 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 == MIDI_control1)
this->setJetDelay(0.08 + (0.48 * value * NORM_7));
else if (number == MIDI_control2)
noiseGain = (value * NORM_7 * 0.4);
else if (number == MIDI_control3)
vibr->setFreq((value * NORM_7 * 12.0));
else if (number == MIDI_mod_wheel)
vibrGain = (value * NORM_7 * 0.4);
else if (number == MIDI_after_touch)
adsr->setTarget(value * NORM_7);
else {
printf("Flute : Undefined Control Number!!\n");
}
}

64
Flute.h
View File

@@ -1,64 +0,0 @@
/******************************************/
/* WaveGuide Flute ala Karjalainen, */
/* Smith, Waryznyk, etc. */
/* with polynomial Jet ala Cook */
/* by Perry Cook, 1995-96 */
/* */
/* This is a waveguide model, and thus */
/* relates to various Stanford Univ. */
/* and possibly Yamaha and other patents.*/
/* */
/* Controls: CONTROL1 = jetDelay */
/* CONTROL2 = noiseGain */
/* CONTROL3 = vibFreq */
/* MOD_WHEEL= vibAmt */
/******************************************/
#if !defined(__Flute_h)
#define __Flute_h
#include "Instrmnt.h"
#include "JetTabl.h"
#include "DLineL.h"
#include "OnePole.h"
#include "DCBlock.h"
#include "Noise.h"
#include "ADSR.h"
#include "RawLoop.h"
class Flute : public Instrmnt
{
protected:
DLineL *jetDelay;
DLineL *boreDelay;
JetTabl *jetTable;
OnePole *filter;
DCBlock *dcBlock;
Noise *noise;
ADSR *adsr;
RawLoop *vibr;
MY_FLOAT lastFreq;
MY_FLOAT maxPressure;
MY_FLOAT jetRefl;
MY_FLOAT endRefl;
MY_FLOAT noiseGain;
MY_FLOAT vibrGain;
MY_FLOAT outputGain;
MY_FLOAT jetRatio;
public:
Flute(MY_FLOAT lowestFreq);
~Flute();
void clear();
void startBlowing(MY_FLOAT amplitude,MY_FLOAT rate);
void stopBlowing(MY_FLOAT rate);
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
virtual void noteOff(MY_FLOAT amp);
void setJetRefl(MY_FLOAT refl);
void setEndRefl(MY_FLOAT refl);
virtual void setFreq(MY_FLOAT frequency);
virtual MY_FLOAT tick();
virtual void controlChange(int number, MY_FLOAT value);
void setJetDelay(MY_FLOAT aLength);
};
#endif

View File

@@ -1,170 +0,0 @@
/*******************************************/
/* Sweepable Formant (2-pole) */
/* Filter Class, by Perry R. Cook, 1995-96*/
/* See books on filters to understand */
/* more about how this works. This drives*/
/* to a target at speed set by rate. */
/*******************************************/
#include "FormSwep.h"
FormSwep :: FormSwep() : Filter()
{
outputs = (MY_FLOAT *) malloc(2 * MY_FLOAT_SIZE);
poleCoeffs[0] = 0.0;
poleCoeffs[1] = 0.0;
gain = 1.0;
freq = 0.0;
reson = 0.0;
currentGain = 1.0;
currentFreq = 0.0;
currentReson = 0.0;
targetGain = 1.0;
targetFreq = 0.0;
targetReson = 0.0;
deltaGain = 0.0;
deltaFreq = 0.0;
deltaReson = 0.0;
sweepState = 0;
sweepRate = 0.002;
dirty = 0;
this->clear();
}
FormSwep :: ~FormSwep()
{
free(outputs);
}
void FormSwep :: clear()
{
outputs[0] = 0.0;
outputs[1] = 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] = 2.0 * reson * 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 = 0.0;
}
void FormSwep :: setSweepRate(MY_FLOAT aRate)
{
sweepRate = aRate;
}
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 = 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] = 2.0 * currentReson * cos(TWO_PI * currentFreq / SRATE);
}
temp = currentGain * sample;
temp += poleCoeffs[0] * outputs[0];
temp += poleCoeffs[1] * outputs[1];
outputs[1] = outputs[0];
outputs[0] = temp;
lastOutput = outputs[0];
return lastOutput;
}
/************ Test Main Program *****************/
/*
void main()
{
FormSwep filter;
FILE *fd;
MY_FLOAT temp;
short data;
long i;
fd = fopen("test.raw","wb");
filter.setTargets(100.0,0.99,0.01);
for (i=0;i<20000;i++) {
if (i%100 != 0) temp = 0.0; else temp = 1.0;
data = filter.tick(temp) * 32000.0;
fwrite(&data,2,1,fd);
}
filter.setTargets(1000.0,0.99,0.01);
for (i=0;i<20000;i++) {
if (i%100 != 0) temp = 0.0; else temp = 1.0;
data = filter.tick(temp) * 32000.0;
fwrite(&data,2,1,fd);
}
filter.setTargets(500.0,0.9999,0.001);
for (i=0;i<20000;i++) {
if (i%100 != 0) temp = 0.0; else temp = 1.0;
data = filter.tick(temp) * 32000.0;
fwrite(&data,2,1,fd);
}
fclose(fd);
}
*/

View File

@@ -1,45 +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);
MY_FLOAT tick(MY_FLOAT sample);
};
#endif

View File

@@ -1,125 +0,0 @@
Brief Descriptions of Classes in TK96CPP
A ToolKit of Sound Synthesis Classes
and Instruments in C++
Perry Cook, 1995-96, free distribution for
academic, instructional, tutorial, etc. purposes.
Please read README.txt for more information.
<-----Building Blocks----->|<----------------Instruments------------------>
SourcSink Filters Non-Lin ModalSyn FM Physical Sampling PhISM
& Formant
Object---------------------------Instrmnt----------.
| | | | | |
Envelope| Filter BowTabl | .------------------|---------------------.
| | | JetTabl | | | | | | | | |
ADSR | OneZero ReedTabl| Modal4 | FM4Op---.| | | | PhISEM
| OnePole | | | | || | | | |
._____| TwoZero .____| Marimba | FM4Alg3 || Plucked Sampler | Maracha
| | TwoPole | Vibraphn| | || Clarinet | | Whistle
Noise | DCBlock LipFilt AgogoBel| HeavyMtl|| Brass SamplFlt| VibraSlp
| | BiQuad | || Flute | | Tambourn
SubNoise| AllPass1 .____| .____|| Bowed Moog1 |
| DLineA | | || |
._____| DLineL VoicForm FM4Alg4 ||____. |
| | DLineN | | | |
RawWave | FormSwep PercFlut| Plucked2 |
| | | |
._____| .____| Mandolin .____|
| | | | |
RawLoop | FM4Alg5 | DrumSynt
| | |
._____| Rhodey |
| | Wurley |
NiWave1S| TubeBell |
| .____|
._____| | |
| | FM4Alg6 |
Modulatr| | |
| FMVoices|
._____| |
| | .____|
SingWave| |
| FM4Alg8
._____| |
| | BeeThree
RawWvOut|
|
._____|
| |
RawWvIn |
._____|
|
NIFileIn
********** 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,BiQuad
Clarinet.cpp Pretty Good Clarinet DLineL,ReedTabl,OneZero,Envelope,Noise.h
Flute.cpp Pretty Good Flute JetTabl,DLineL,OnePole,DCBlock,Noise,ADSR,RawWave
Modal4.cpp 4 Resonances Envelope,RawWave,BiQuad,OnePole
Marimba.cpp <<flavor of MODAL4>>
Vibraphn.cpp <<flavor of MODAL4>>
Agogobel.cpp <<flavor of MODAL4>>
FM4Op.cpp 4 Operator FM Master ADSR,RawLoop,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, RawWave (att), RawWave (loop), OnePole
SamplFlt.cpp Sampler with Swept Filt.<<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 NIFileIn, and OnePole
*********** Basic Unit Generators **************
Master Object: Object.cpp for compatibility with Objective C
Source&Sink: RawWave.cpp Lin-Interp Wavetable, Looped or 1 Shot
NIWave1S.cpp Non-Interp Wavetable, 1 Shot
RawLoop.cpp Lin-Interp Wavetable, Looping
RawWvIn.cpp Lin-Interp Wave In streaming 'device'
NIFileIn.cpp Non-Interp Wave In streamer, closes & opens
RawWvOut.cpp Non-Interp Wave Out streaming 'device'
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
Filters: Filter.cpp Filter Master Class
OneZero.cpp One Zero Filter
OnePole.cpp One Pole Filter
AllPass1.cpp 1st Order All-Pass (phase) 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
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

View File

@@ -1,60 +0,0 @@
/******************************************/
/* Heavy Metal Synth Subclass */
/* of Algorithm 3 (TX81Z) Subclass of */
/* 3 Operator FM Synth */
/* by Perry R. Cook, 1995-96 */
/******************************************/
#include "HeavyMtl.h"
HeavyMtl :: HeavyMtl() : FM4Alg3()
{
this->loadWaves("rawwaves/sinewave.raw",
"rawwaves/twopeaks.raw",
"rawwaves/twopeaks.raw",
"rawwaves/sinewave.raw");
this->setRatio(0,1.00 );
this->setRatio(1,4.00 * 0.999);
this->setRatio(2,3.00 * 1.001);
this->setRatio(3,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]->setAll(0.050,0.0100,1.0,0.001);
adsr[1]->setAll(0.050,0.0010,1.0,0.0001);
adsr[2]->setAll(0.001,0.0020,1.0,0.0002);
adsr[3]->setAll(0.050,0.0010,0.2,0.0002);
twozero->setGain(2.0);
vibWave->setFreq(5.5);
modDepth = 0.00;
}
HeavyMtl :: ~HeavyMtl()
{
}
void HeavyMtl :: setFreq(MY_FLOAT frequency)
{
baseFreq = frequency;
waves[0]->setFreq(baseFreq * ratios[0]);
waves[1]->setFreq(baseFreq * ratios[1]);
waves[2]->setFreq(baseFreq * ratios[2]);
waves[3]->setFreq(baseFreq * ratios[3]);
}
void HeavyMtl :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
{
gains[0] = amp * __FM4Op_gains[92];
gains[1] = amp * __FM4Op_gains[76];
gains[2] = amp * __FM4Op_gains[91];
gains[3] = amp * __FM4Op_gains[68];
this->setFreq(freq);
this->keyOn();
#if defined(_debug_)
printf("HeavyMtl : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
#endif
}

View File

@@ -1,22 +0,0 @@
/******************************************/
/* Heavy Metal Synth Subclass */
/* of Algorithm 3 (TX81Z) Subclass of */
/* 3 Operator FM Synth */
/* by Perry R. Cook, 1995-96 */
/******************************************/
#if !defined(__HeavyMtl_h)
#define __HeavyMtl_h
#include "FM4Alg3.h"
class HeavyMtl : public FM4Alg3
{
public:
HeavyMtl();
~HeavyMtl();
virtual void setFreq(MY_FLOAT frequency);
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
};
#endif

54
INSTALL.md Normal file
View File

@@ -0,0 +1,54 @@
# The Synthesis ToolKit in C++ (STK)
By Perry R. Cook and Gary P. Scavone, 1995-2019.
The Synthesis ToolKit in C++ can be used in a variety of ways, depending on your particular needs. Some people simply choose the classes they need for a particular project and copy those to their project directory. Others like to compile and link to a library of object files. STK was not designed with one particular style of use in mind.
## Unix systems and MinGW
1. If you downloaded the software from the git repository, first run autoconf,
autoconf
otherwise, if you downloaded the software from the STK source distribution, unpack the tar file,
tar -xzf stk-4.x.x.tar.gz
2. From within the directory containing this file, run configure:
./configure
3. From within each project directory, type `make`.
4. To compile a library of objects, type `make` from within the `src` directory.
Several options can be passed to configure, including:
--disable-realtime = only compile generic non-realtime classes
--enable-debug = enable various debug output
--with-alsa = choose native ALSA API support (default, linux only)
--with-oss = choose native OSS API support (unixes only)
--with-jack = choose native JACK server API support (linux and macintosh OS-X)
--with-core = choose OS-X CoreAudio API (macintosh OS-X only)
--with-asio = choose ASIO API support (windows only)
--with-ds = choose DirectSound API support (windows only)
--with-wasapi = choose Windows Audio Session API support (windows only)
It is now possible to specify more than one audio and MIDI API where supported. Note, however, that the ALSA library is required in order to compile the RtMidi class in Linux if the `--with-oss` option is provided (only the OSS audio API will be used, not the OSS MIDI API). Typing `./configure --help` will display all the available options. In addition, it is possible to specify the RAWWAVES and INCLUDE paths to configure as (e.g. to set to /home/me/rawwaves and /home/me/include):
./configure RAWWAVE_PATH='$(HOME)/rawwaves/'
./configure INCLUDE_PATH='$(HOME)/include/'
The ending "/" is required for the RAWWAVES path. The default behavior will set a relative path that works for the project files included with the distribution (assuming they are not moved). You can also change the RAWWAVE_PATH dynamically via the static Stk::setRawwavePath() function.
If you wish to use a different compiler than that selected by configure, specify that compiler in the command line (e.g. to use CC):
./configure CXX=CC
## Windows
MinGW support is provided in the configure script. In addition, Visual Studio 2017 project files are included for each of the example STK projects.
##iOS
You can integrate the STK in iOS projects either by using its iOS static library or CocoaPods. See the [iOS README file](iOS/README-iOS.md) for instructions.

View File

@@ -1,35 +0,0 @@
/******************************************/
/* Instrument SuperClass for Toolkit96 */
/* Perry R. Cook, Princeton University */
/******************************************/
#include "Instrmnt.h"
Instrmnt :: Instrmnt()
{
}
void Instrmnt :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
{
}
void Instrmnt :: noteOff(MY_FLOAT amp)
{
}
void Instrmnt :: setFreq(MY_FLOAT freq)
{
}
MY_FLOAT Instrmnt :: tick()
{
}
MY_FLOAT Instrmnt :: lastOut()
{
return lastOutput;
}
void Instrmnt :: controlChange(int number, MY_FLOAT value)
{
}

View File

@@ -1,25 +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();
MY_FLOAT lastOut();
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
virtual void noteOff(MY_FLOAT amp);
virtual void setFreq(MY_FLOAT frequency);
virtual MY_FLOAT tick();
virtual void controlChange(int number, MY_FLOAT value);
};
#endif

View File

@@ -1,36 +0,0 @@
/**********************************************/
/* Jet Table Object by Perry R. Cook, 1995-96 */
/* Consult Fletcher and Rossing, Karjalainen, */
/* Cook, more, for information. */
/* This, as with many other of my "tables", */
/* is not a table, but is computed by poly- */
/* nomial calculation. */
/**********************************************/
#include "JetTabl.h"
JetTabl :: JetTabl()
{
lastOutput = 0.0;
}
JetTabl :: ~JetTabl()
{
}
MY_FLOAT JetTabl :: lookup(double sample) /* Perform "Table Lookup" */
{ /* By Polynomial Calculation */
lastOutput = sample *
(sample*sample - 1.0); /* (x^3 - x) approximates sigmoid of jet */
if (lastOutput > 1.0)
lastOutput = 1.0; /* Saturation at +/- 1.0 */
if (lastOutput < -1.0)
lastOutput = -1.0;
return lastOutput;
}
MY_FLOAT JetTabl :: lastOut()
{
return lastOutput;
}

View File

@@ -1,22 +0,0 @@
/**********************************************/
/* Jet Table Object by Perry R. Cook, 1995-96 */
/* Consult Fletcher and Rossing, Karjalainen, */
/* Cook, more, for information. */
/* This, as with many other of my "tables", */
/* is not a table, but is computed by poly- */
/* nomial calculation. */
/**********************************************/
#include "Object.h"
class JetTabl : public Object
{
protected:
double lastOutput;
public:
JetTabl();
~JetTabl();
double lookup(double deltaP);
double lastOut();
};

27
LICENSE Normal file
View File

@@ -0,0 +1,27 @@
The Synthesis ToolKit in C++ (STK)
Copyright (c) 1995-2019 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.

View File

@@ -1 +0,0 @@
time textVoic =100.00 lll ahh ...... =133 .... xxx rrr + + eee .. mmm + ohh ..... sss ahh ..... ddd - eee .. - - ... + + ehh .. + ... sss - - - eee ..... lll =100.0 ahh .......

View File

@@ -1,66 +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] = 0.0;
coeffs[1] = 0.0;
filter->setZeroCoeffs(coeffs);
this->clear();
}
LipFilt :: ~LipFilt()
{
delete filter;
}
void LipFilt :: clear()
{
filter->clear();
lastOutput = 0.0;
}
void LipFilt :: setFreq(MY_FLOAT frequency)
{
MY_FLOAT coeffs[2];
coeffs[0] = 2.0 * 0.997 *
cos(TWO_PI * frequency / SRATE); /* damping should change with */
coeffs[1] = -0.997 * 0.997; /* lip parameters, but not yet.*/
filter->setPoleCoeffs(coeffs);
filter->setGain(0.03);
}
/* NOTE: Here we should add lip tension */
/* settings based on Mass/Spring/Damping */
/* Maybe in TookKit97 */
MY_FLOAT LipFilt :: tick(MY_FLOAT mouthSample,MY_FLOAT boreSample)
/* Perform "Table Lookup" By Polynomial Calculation */
{
MY_FLOAT temp;
temp = mouthSample - boreSample; /* Differential pressure */
temp = filter->tick(temp); /* Force -> position */
temp = temp*temp; /* Simple position to area mapping */
if (temp > 1.0) temp = 1.0; /* Saturation at + 1.0 */
lastOutput = temp * mouthSample; /* Assume mouth input = area */
lastOutput += (1.0 - temp) * boreSample; /* and Bore reflection is compliment. */
return lastOutput;
}
MY_FLOAT LipFilt :: lastOut()
{
return lastOutput;
}

View File

@@ -1,28 +0,0 @@
/**********************************************/
/* Lip Filter Object by Perry R. Cook, 1995-96*/
/* The lip of the brass player has dynamics */
/* which are controlled by the mass, spring */
/* constant, and damping of the lip. This */
/* filter simulates that behavior and the */
/* transmission/reflection properties as */
/* well. See Cook TBone and HosePlayer */
/* instruments and articles. */
/**********************************************/
#include "Object.h"
#include "BiQuad.h"
class LipFilt : public Object
{
protected:
BiQuad *filter;
MY_FLOAT lastOutput;
public:
LipFilt();
~LipFilt();
void clear();
void setFreq(MY_FLOAT frequency);
MY_FLOAT tick(MY_FLOAT mouthSample,MY_FLOAT boreSample);
MY_FLOAT lastOut();
};

View File

@@ -1,188 +0,0 @@
/******************************************/
/* Simple RealTime MIDI Input Object, */
/* by Perry R. Cook, 1996 */
/* */
/* This object takes MIDI from the input */
/* , parses it, turns it into TSIDI */
/* messages, and buffers it up for use by*/
/* any object that asks for it later. */
/* */
/* TSIDI (ToolKit Synthesis Instrument */
/* Digital Interfaceis like MIDI, but */
/* allows for floating point control */
/* changes, note numbers, etc. Example: */
/* noteOn(1,60.01,111.132) plays a sharp */
/* middle C with a velocity of 111.132 */
/* */
/******************************************/
#include "MIDIInpt.h"
int onePending;
MDport inport;
MDevent lastEvent;
// void pollMessage(void *)
// {
// int status;
// while (1) {
// while (onePending == 0) {
// mdReceive(inport, &lastEvent, 1);
// status = mdGetStatus(lastEvent.msg);
// if (status==MD_NOTEON || status==MD_NOTEOFF)
// onePending = 1;
// }
// }
// }
MIDIInpt :: MIDIInpt()
{
int nports;
nports = mdInit();
printf("%d MIDI devices available\n", nports);
inport = mdOpenInPort(0);
if (inport == NULL) {
printf("open failed\n");
exit(0);
}
mdSetStampMode(inport, MD_NOSTAMP);
onePending = 0;
// midi_pid = sproc(pollMessage, PR_SALL);
// if (midi_pid == -1)
// {
// fprintf(stderr, "unable to create midi input thread...aborting.\n");
// exit(-1);
// }
}
#define _BSD_SIGNALS
#include <signal.h>
MIDIInpt :: ~MIDIInpt()
{
mdClosePort(inport);
// kill(midi_pid, SIGKILL);
}
/* MIDI File Code
if (byte > 15) {
if (byte == 248) printf("MIDI Clock,");
else if (byte == 249) printf("Undefined,");
else if (byte == 250) printf("Song Start,");
else if (byte == 251) printf("Continue,");
else if (byte == 252) printf("Song Stop,");
else if (byte == 253) printf("Undefined,");
else if (byte == 254) printf("ActiveSen,");
else if (byte == 255) printf("SystReset,");
else printf("BEATSME");
}
else {
if (byte == 8) printf("NoteOff");
if (byte == 9) printf("NoteOn");
if (byte == 10) printf("Poly Pressure");
if (byte == 11) printf("Control Change");
if (byte == 12) printf("Program Change");
if (byte == 13) printf("Channel Pressure");
if (byte == 14) printf("Pitch Wheel");
}
*/
int MIDIInpt :: nextMessage()
{
int status;
int byte1;
int byte2;
messageType = -1;
mdReceive(inport, &lastEvent, 1);
// if (onePending == 1) {
status = mdGetStatus(lastEvent.msg);
byte1 = mdGetByte1(lastEvent.msg);
byte2 = mdGetByte2(lastEvent.msg);
channel = mdGetChannel(lastEvent.msg);
if (status==MD_NOTEON) {
byteTwo = (float) byte1;
byteThree = (float) byte2;
if (byte2==0)
messageType = 8;
else
messageType = 9;
}
else if (status==MD_NOTEOFF) {
byteTwo = (float) byte1;
byteThree = (float) byte2;
messageType = 8;
}
else if (status==MD_CONTROLCHANGE) {
byteTwo = (float) byte1;
byteThree = (float) byte2;
messageType = 11;
}
else if (status==MD_PROGRAMCHANGE) {
byteTwo = (float) byte1;
messageType = 12;
}
else if (status==MD_CHANNELPRESSURE) {
byteTwo = (float) byte1;
messageType = 13;
}
else if (status==MD_PITCHBENDCHANGE) {
byteTwo = (float) byte1;
byteTwo += (float) byte2 * NORM_7;
messageType = 14;
}
else {
messageType = -1;
}
// onePending = 0;
// }
return messageType;
}
void MIDIInpt :: printMessage()
{
char buffer[128];
mdPrintEvent(buffer,&lastEvent,1);
printf(buffer);
}
int MIDIInpt :: getType()
{
return messageType;
}
int MIDIInpt :: getChannel()
{
return channel;
}
MY_FLOAT MIDIInpt :: getByteTwo()
{
return byteTwo;
}
MY_FLOAT MIDIInpt :: getByteThree()
{
return byteThree;
}
/************ Test Main Program *****************/
/*
void main(int argc,char *argv[])
{
MIDIInpt testMIDI;
while(1) {
if (testMIDI.nextMessage() > 0)
testMIDI.printMessage();
}
}
*/

View File

@@ -1,48 +0,0 @@
/******************************************/
/* Simple MIDI Text File Reader Class, */
/* by Perry R. Cook, 1996 */
/* This Object can open a MIDI Text File */
/* and parse it. The file spec is mine */
/* and mine alone, but it's all text so */
/* you should be able to figure it out. */
/* */
/* TSIDI (ToolKit Synthesis Instrument */
/* Digital Interfaceis like MIDI, but */
/* allows for floating point control */
/* changes, note numbers, etc. Example: */
/* noteOn(1,60.01,111.132) plays a sharp */
/* middle C with a velocity of 111.132 */
/* */
/* Warning: Obey column spacing in the */
/* text file if you try to edit it or */
/* create your own files. */
/******************************************/
#if !defined(__MIDIInpt_h)
#define __MIDIInpt_h
#include "Object.h"
#include "dmedia/midi.h"
#include <sys/types.h>
#include <sys/prctl.h>
class MIDIInpt : public Object
{
protected:
int midi_pid;
int messageType;
int channel;
float byteTwo;
float byteThree;
public:
MIDIInpt();
~MIDIInpt();
void printMessage();
int nextMessage();
int getType();
int getChannel();
MY_FLOAT getByteTwo();
MY_FLOAT getByteThree();
};
#endif

View File

@@ -1,133 +0,0 @@
/******************************************/
/* Simple MIDI Text File Reader Class, */
/* by Perry R. Cook, 1996 */
/* This Object can open a MIDI Text File */
/* and parse it. The file spec is mine */
/* and mine alone, but it's all text so */
/* you should be able to figure it out. */
/* */
/* SKINI (Synthesis toolKit Instrument */
/* Network Interface) is like MIDI, but */
/* allows for floating point control */
/* changes, note numbers, etc. Example: */
/* noteOn 60.01 111.132 plays a sharp */
/* middle C with a velocity of 111.132 */
/* See SKINI.txt for more information */
/* Warning: Obey columns in the text */
/* file if you try to edit it or create */
/* your own files. */
/******************************************/
#include "MIDIText.h"
MIDIText :: MIDIText(char *fileName)
{
myFile = fopen(fileName,"r");
this->nextMessage();
}
MIDIText :: ~MIDIText()
{
}
/* MIDI File Codes
if (byte > 15) {
if (byte == 248) printf("MIDI Clock,");
else if (byte == 249) printf("Undefined,");
else if (byte == 250) printf("Song Start,");
else if (byte == 251) printf("Continue,");
else if (byte == 252) printf("Song Stop,");
else if (byte == 253) printf("Undefined,");
else if (byte == 254) printf("ActiveSen,");
else if (byte == 255) printf("SystReset,");
else printf("BEATSME");
}
else { // these are all nybbles of status bytes //
if (byte == 8) printf("NoteOff");
if (byte == 9) printf("NoteOn");
if (byte == 10) printf("Poly Pressure");
if (byte == 11) printf("Control Change");
if (byte == 12) printf("Program Change");
if (byte == 13) printf("Channel Pressure");
if (byte == 14) printf("Pitch Wheel");
}
*/
int MIDIText :: nextMessage()
{
int notDone = 1,point;
char inputString[1024];
char tempString[32];
while (notDone) {
notDone = 0;
if (fgets(inputString,1000,myFile)) {
sscanf(inputString,"%s %lf %i %f %f",tempString,&deltaTime,&channel,&byteTwo,&byteThree);
point = 5;
if (tempString[0]=='%') point = 1;
if (tempString[point] == 'n') { // NoteO'n'
messageType = 9;
}
else if (inputString[point] == 'f') { // NoteO'f'f
messageType = 8;
}
else if (inputString[point] == 'B') { // Pitch'B'end
byteThree = byteTwo;
messageType = 14;
}
else if (inputString[point] == 'a') { // Progr'a'mChange
messageType = 12;
}
else if (inputString[point] == 'T') { // After'T'ouch
messageType = 11;
}
else if (inputString[point] == 'o') { // Contr'o'lChange
messageType = 11;
}
else if (inputString[0] == '/' || inputString[0] == ' ') {
notDone = 1;
}
}
else {
messageType = -1;
}
}
return messageType;
}
int MIDIText :: getType()
{
return messageType;
}
int MIDIText :: getChannel()
{
return channel;
}
MY_FLOAT MIDIText :: getDelta()
{
return deltaTime;
}
MY_FLOAT MIDIText :: getByteTwo()
{
return byteTwo;
}
MY_FLOAT MIDIText :: getByteThree()
{
return byteThree;
}
/************ Test Main Program *****************/
/*
void main(int argc,char *argv[])
{
MIDIText testFile(argv[1]);
while(testFile.nextMessage() > 0) ;
}
*/

View File

@@ -1,46 +0,0 @@
/******************************************/
/* Simple MIDI Text File Reader Class, */
/* by Perry R. Cook, 1996 */
/* This Object can open a MIDI Text File */
/* and parse it. The file spec is mine */
/* and mine alone, but it's all text so */
/* you should be able to figure it out. */
/* */
/* SKINI (Synthesis toolKit Instrument */
/* Network Interface) is like MIDI, but */
/* allows for floating point control */
/* changes, note numbers, etc. Example: */
/* noteOn 60.01 111.132 plays a sharp */
/* middle C with a velocity of 111.132 */
/* See SKINI.txt for more information */
/* Warning: Obey columns in the text */
/* file if you try to edit it or create */
/* your own files. */
/******************************************/
#if !defined(__MIDIText_h)
#define __MIDIText_h
#include "Object.h"
class MIDIText : public Object
{
protected:
FILE *myFile;
int messageType;
int channel;
MY_FLOAT deltaTime;
float byteTwo;
float byteThree;
public:
MIDIText(char *fileName);
~MIDIText();
int nextMessage();
int getType();
int getChannel();
MY_FLOAT getDelta();
MY_FLOAT getByteTwo();
MY_FLOAT getByteThree();
};
#endif

247
Makefile
View File

@@ -1,247 +0,0 @@
O_FILES = Object.o Envelope.o ADSR.o Noise.o SubNoise.o RawWave.o RawLoop.o \
NIWave1S.o Modulatr.o SingWave.o RawWvOut.o RawWvIn.o Filter.o \
OneZero.o OnePole.o TwoZero.o TwoPole.o DCBlock.o BiQuad.o AllPass1.o \
DLineA.o DLineL.o DLineN.o FormSwep.o BowTabl.o JetTabl.o ReedTabl.o \
LipFilt.o Modal4.o FM4Op.o FM4Alg3.o FM4Alg4.o FM4Alg5.o FM4Alg6.o \
FM4Alg8.o Plucked2.o SamplFlt.o Sampler.o VoicForm.o\
MIDIText.o Reverb.o VoicMang.o \
\
Instrmnt.o Marimba.o Vibraphn.o AgogoBel.o Plucked.o Mandolin.o \
Clarinet.o Flute.o Brass.o Bowed.o Rhodey.o Wurley.o TubeBell.o \
HeavyMtl.o PercFlut.o BeeThree.o FMVoices.o Moog1.o
RM = /bin/rm
# This is for NeXT
# CC = cc -O
# INSTR = testMono testMult DrumSynt textVoic
# These are for SGI
INSTR = testTextIn testMono testMIDI testMult DrumSynt textVoic
CC = gcc -O
MEDIALINK = -lmd
TCLLIB = /usr/local/lib/libtcl.so.7.4 /usr/local/lib/libtk.so.4.0 /usr/lib/libX11.so
LIBRARY = /usr/lib/libmx.so /usr/lib/libaudio.a
# .cpp.o:
# $(CC) -c $*.cpp
all: $(INSTR)
testTextIn: $(LIBRARY) testTextIn.cpp $(O_FILES) MIDIInpt.o
$(CC) $(MEDIALINK) -o testTextIn testTextIn.cpp $(O_FILES) $(LIBRARY)
testMono: $(LIBRARY) testMono.cpp $(O_FILES)
$(CC) $(MEDIALINK) -o testMono testMono.cpp $(O_FILES) $(LIBRARY)
testMIDI: $(LIBRARY) testMIDI.cpp Object.o MIDIInpt.o
$(CC) $(MEDIALINK) -o testMIDI testMIDI.cpp Object.o MIDIInpt.o $(LIBRARY) /usr/lib/libmidi.so
testMult: $(LIBRARY) testMult.cpp $(O_FILES)
$(CC) $(MEDIALINK) -o testMult testMult.cpp $(O_FILES) $(LIBRARY)
textVoic: $(LIBRARY) textVoic.cpp $(O_FILES)
$(CC) $(MEDIALINK) -o textVoic textVoic.cpp $(O_FILES) $(LIBRARY)
Instrmnt.o: Instrmnt.cpp
$(CC) -c Instrmnt.cpp
Marimba.o: Marimba.cpp
$(CC) -c Marimba.cpp
Vibraphn.o: Vibraphn.cpp
$(CC) -c Vibraphn.cpp
AgogoBel.o: AgogoBel.cpp
$(CC) -c AgogoBel.cpp
Plucked.o: Plucked.cpp
$(CC) -c Plucked.cpp
Mandolin.o: Mandolin.cpp
$(CC) -c Mandolin.cpp
Clarinet.o: Clarinet.cpp
$(CC) -c Clarinet.cpp
Flute.o: Flute.cpp
$(CC) -c Flute.cpp
Brass.o: Brass.cpp
$(CC) -c Brass.cpp
Bowed.o: Bowed.cpp
$(CC) -c Bowed.cpp
Rhodey.o: Rhodey.cpp
$(CC) -c Rhodey.cpp
Wurley.o: Wurley.cpp
$(CC) -c Wurley.cpp
TubeBell.o: TubeBell.cpp
$(CC) -c TubeBell.cpp
HeavyMtl.o: HeavyMtl.cpp
$(CC) -c HeavyMtl.cpp
PercFlut.o: PercFlut.cpp
$(CC) -c PercFlut.cpp
BeeThree.o: BeeThree.cpp
$(CC) -c BeeThree.cpp
FMVoices.o: FMVoices.cpp
$(CC) -c FMVoices.cpp
Moog1.o: Moog1.cpp
$(CC) -c Moog1.cpp
DrumSynt: $(LIBRARY) DrumSynt.cpp $(O_FILES)
$(CC) -o DrumSynt DrumSynt.cpp $(O_FILES) $(LIBRARY)
testVoic: $(LIBRARY) testVoic.cpp $(O_FILES)
$(CC) -o testVoic testVoic.cpp $(O_FILES) $(LIBRARY)
# $(O_FILES) :
# $(CC) -c -o $@ $*.cpp
Object.o : Object.cpp
$(CC) -c Object.cpp
Envelope.o : Envelope.cpp
$(CC) -c Envelope.cpp
ADSR.o : ADSR.cpp
$(CC) -c ADSR.cpp
Noise.o : Noise.cpp
$(CC) -c Noise.cpp
SubNoise.o : SubNoise.cpp
$(CC) -c SubNoise.cpp
RawWave.o : RawWave.cpp
$(CC) -c RawWave.cpp
RawLoop.o : RawLoop.cpp
$(CC) -c RawLoop.cpp
NIWave1S.o : NIWave1S.cpp
$(CC) -c NIWave1S.cpp
Modulatr.o : Modulatr.cpp
$(CC) -c Modulatr.cpp
SingWave.o : SingWave.cpp
$(CC) -c SingWave.cpp
RawWvOut.o : RawWvOut.cpp
$(CC) -c RawWvOut.cpp
RawWvIn.o : RawWvIn.cpp
$(CC) -c RawWvIn.cpp
Filter.o : Filter.cpp
$(CC) -c Filter.cpp
OneZero.o : OneZero.cpp
$(CC) -c OneZero.cpp
OnePole.o : OnePole.cpp
$(CC) -c OnePole.cpp
TwoZero.o : TwoZero.cpp
$(CC) -c TwoZero.cpp
TwoPole.o : TwoPole.cpp
$(CC) -c TwoPole.cpp
DCBlock.o : DCBlock.cpp
$(CC) -c DCBlock.cpp
BiQuad.o : BiQuad.cpp
$(CC) -c BiQuad.cpp
AllPass1.o : AllPass1.cpp
$(CC) -c AllPass1.cpp
DLineA.o : DLineA.cpp
$(CC) -c DLineA.cpp
DLineL.o : DLineL.cpp
$(CC) -c DLineL.cpp
DLineN.o : DLineN.cpp
$(CC) -c DLineN.cpp
FormSwep.o : FormSwep.cpp
$(CC) -c FormSwep.cpp
BowTabl.o : BowTabl.cpp
$(CC) -c BowTabl.cpp
JetTabl.o : JetTabl.cpp
$(CC) -c JetTabl.cpp
ReedTabl.o : ReedTabl.cpp
$(CC) -c ReedTabl.cpp
LipFilt.o : LipFilt.cpp
$(CC) -c LipFilt.cpp
Modal4.o : Modal4.cpp
$(CC) -c Modal4.cpp
FM4Op.o : FM4Op.cpp
$(CC) -c FM4Op.cpp
FM4Alg3.o : FM4Alg3.cpp
$(CC) -c FM4Alg3.cpp
FM4Alg4.o : FM4Alg4.cpp
$(CC) -c FM4Alg4.cpp
FM4Alg5.o : FM4Alg5.cpp
$(CC) -c FM4Alg5.cpp
FM4Alg6.o : FM4Alg6.cpp
$(CC) -c FM4Alg6.cpp
FM4Alg8.o : FM4Alg8.cpp
$(CC) -c FM4Alg8.cpp
Plucked2.o : Plucked2.cpp
$(CC) -c Plucked2.cpp
SamplFlt.o : SamplFlt.cpp
$(CC) -c SamplFlt.cpp
Sampler.o : Sampler.cpp
$(CC) -c Sampler.cpp
VoicForm.o : VoicForm.cpp
$(CC) -c VoicForm.cpp
MIDIText.o : MIDIText.cpp
$(CC) -c MIDIText.cpp
MIDIInpt.o : MIDIInpt.cpp
$(CC) -c MIDIInpt.cpp
VoicMang.o : VoicMang.cpp
$(CC) -c VoicMang.cpp
Reverb.o : Reverb.cpp
$(CC) -c Reverb.cpp
clean :
rm $(INSTR)
rm *.o
cleanIns :
rm $(INSTR)
strip :
strip $(INSTR)

41
Makefile.in Normal file
View File

@@ -0,0 +1,41 @@
### Do not edit -- Generated by 'configure --with-whatever' from Makefile.in
RM = /bin/rm
REALTIME = @realtime@
all :
cd src && $(MAKE)
cd projects/demo && $(MAKE) libdemo
ifeq ($(REALTIME),yes)
cd projects/effects && $(MAKE) libeffects
cd projects/ragamatic && $(MAKE) libragamat
cd projects/eguitar && $(MAKE) libeguitar
endif
cd projects/examples && $(MAKE) -f libMakefile
clean :
$(RM) -f *~
cd src && $(MAKE) clean
cd projects/demo && $(MAKE) clean
ifeq ($(REALTIME),yes)
cd projects/effects && $(MAKE) clean
cd projects/ragamatic && $(MAKE) clean
cd projects/eguitar && $(MAKE) clean
endif
cd projects/examples && $(MAKE) clean
distclean: clean
$(RM) -rf config.log config.status autom4te.cache Makefile
cd src && $(MAKE) distclean
cd projects/demo && $(MAKE) distclean
ifeq ($(REALTIME),yes)
cd projects/effects && $(MAKE) distclean
cd projects/ragamatic && $(MAKE) distclean
cd projects/eguitar && $(MAKE) distclean
endif
cd projects/examples && $(MAKE) distclean
install:
$(MAKE) -C src install

View File

@@ -1,116 +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"
Mandolin :: Mandolin(MY_FLOAT lowestFreq) : Plucked2(lowestFreq)
{
soundfile = new RawWave("rawwaves/mandpluk.raw");
soundfile->normalize(0.05); /* Empirical hack here */
soundfile->setLooping(0);
dampTime = 0;
waveDone = 1;
}
void Mandolin :: pluck(MY_FLOAT amplitude)
{ /* this function gets interesting here, */
soundfile->reset(); /* because pluck may be longer than */
pluckAmp = amplitude; /* string length, so we just reset the */
/* soundfile and add in the pluck in */
/* the tick method. */
combDelay->setDelay(
0.5 * pluckPos * lastLength); /* Set Pick Position */
/* which puts zeroes at pos*length */
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)
{
soundfile->setRate(size);
}
MY_FLOAT Mandolin :: tick()
{
MY_FLOAT temp = 0;
if (!waveDone) {
waveDone = soundfile->informTick(); /* as long as it goes . . . */
temp = soundfile->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() * 0.7)));
lastOutput += delayLine2->tick( /* and 2nd delay */
filter2->tick( /* just like the 1st */
temp +
(delayLine2->lastOut() * 0.7))); /* that's the whole thing!! */
}
else { /* No damping hack after 1 period */
lastOutput = delayLine->tick( /* Calculate 1st delay */
filter->tick( /* filtered reflection */
temp + /* plus pluck excitation */
(delayLine->lastOut()
* loopGain)));
lastOutput += delayLine2->tick( /* and 2nd delay */
filter2->tick( /* just like the 1st */
temp +
(delayLine2->lastOut()
* loopGain)));
}
lastOutput *= 2.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 == MIDI_control1)
this->setBodySize(value * NORM_7 * 2.0);
else if (number == MIDI_control2)
this->setPluckPos(value * NORM_7);
else if (number == MIDI_control3)
this->setBaseLoopGain(0.97 + (value * NORM_7 * 0.03));
else if (number == MIDI_mod_wheel)
this->setDetune(1.0 - (value * NORM_7 * 0.1));
else if (number == MIDI_after_touch)
this->pluck(value * NORM_7);
else {
printf("Mandolin : Undefined Control Number!!\n");
}
}

View File

@@ -1,41 +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 "RawWave.h"
class Mandolin : public Plucked2
{
protected:
RawWave *soundfile;
long dampTime;
int waveDone;
public:
Mandolin(MY_FLOAT lowestFreq);
void pluck(MY_FLOAT amplitude);
void pluck(MY_FLOAT amplitude,MY_FLOAT position);
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
void setBodySize(MY_FLOAT size);
virtual void controlChange(int number, MY_FLOAT value);
virtual MY_FLOAT tick();
};
#endif

View File

@@ -1,111 +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"
Marimba :: Marimba() : Modal4()
{
wave = new RawWave("rawwaves/marmstk1.raw");
wave->normalize();
wave->setRate(0.5); /* normal stick */
this->setRatioAndReson(0, 1.00,0.9996); /* Set all 132.0 */
this->setRatioAndReson(1, 3.99,0.9994); /* of our 523.0 */
this->setRatioAndReson(2,10.65,0.9994); /* default 1405.0 */
this->setRatioAndReson(3,-18.50,0.999); /* resonances 2443.0 */
this->setFiltGain(0,0.08); /* and */
this->setFiltGain(1,0.02); /* gains */
this->setFiltGain(2,0.02); /* for each */
this->setFiltGain(3,0.015); /* resonance */
directGain = 0.1;
multiStrike = 0;
}
Marimba :: ~Marimba()
{
}
void Marimba :: setStickHardness(MY_FLOAT hardness)
{
stickHardness = hardness;
wave->setRate(0.25 * pow(4.0,stickHardness));
masterGain = 0.1 + (1.8 * stickHardness);
}
void Marimba :: setStrikePosition(MY_FLOAT position)
{
MY_FLOAT temp,temp2;
temp2 = position * PI;
strikePosition = position; /* Hack only first three modes */
temp = sin(temp2);
this->setFiltGain(0,0.12 * temp); /* 1st mode function of pos. */
temp = sin(0.05 + (3.9 * temp2));
this->setFiltGain(1,-0.03 * temp); /* 2nd mode function of pos. */
temp = sin(-0.05 + (11 * temp2));
this->setFiltGain(2,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 = random() >> 26;
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 == MIDI_control1)
this->setStickHardness(value * NORM_7);
else if (number == MIDI_control2)
this->setStrikePosition(value * NORM_7);
else if (number == MIDI_control3)
vibr->setFreq((value * NORM_7 * 12.0));
else if (number == MIDI_mod_wheel)
vibrGain = (value * NORM_7);
else if (number == MIDI_after_touch)
this->strike(value * NORM_7);
else {
printf("Marimba : Undefined Control Number!!\n");
}
}
MY_FLOAT Marimba :: tick()
{
if (multiStrike>0)
if (wave->isAllDone()) {
wave->reset();
multiStrike -= 1;
}
return Modal4::tick();
}

View File

@@ -1,32 +0,0 @@
/*******************************************/
/* Marimba SubClass of Modal4 Instrument, */
/* by Perry R. Cook, 1995-96 */
/* */
/* Controls: CONTROL1 = stickHardness */
/* CONTROL2 = strikePosition*/
/* CONTROL3 = vibFreq */
/* MOD_WHEEL= vibAmt */
/*******************************************/
#if !defined(__Marimba_h)
#define __Marimba_h
#include "Modal4.h"
class Marimba : public Modal4
{
private:
int multiStrike;
public:
Marimba();
~Marimba();
void setStickHardness(MY_FLOAT hardness);
void setStrikePosition(MY_FLOAT position);
void setModulationSpeed(MY_FLOAT mSpeed);
void setModulationDepth(MY_FLOAT mDepth);
virtual void strike(MY_FLOAT amplitude);
virtual void controlChange(int number, MY_FLOAT value);
virtual MY_FLOAT tick();
};
#endif

View File

@@ -1,187 +0,0 @@
/*******************************************/
/* 4 Resonance Modal Synthesis Instrument */
/* by Perry R. Cook, 1995-96 */
/* This instrument contains an excitation */
/* wavetable, an envelope, and four reso- */
/* nances (Non-Sweeping BiQuad Filters). */
/*******************************************/
#include "Modal4.h"
Modal4 :: Modal4()
{
envelope = new Envelope;
/* We don't make the excitation wave here yet, */
/* because we don't know what it's going to be. */
filters[0] = new BiQuad;
filters[1] = new BiQuad;
filters[2] = new BiQuad;
filters[3] = new BiQuad;
onepole = new OnePole;
vibr = new RawLoop("rawwaves/sinewave.raw");
vibr->normalize();
vibr->setFreq(6.0);
vibrGain = 0.05;
directGain = 0.0;
masterGain = 1.0;
baseFreq = 440.0;
this->setRatioAndReson(0,1.00,0.9997); /* Set some */
this->setRatioAndReson(1,1.30,0.9997); /* silly */
this->setRatioAndReson(2,1.77,0.9997); /* default */
this->setRatioAndReson(3,2.37,0.9997); /* values here */
this->setFiltGain(0,0.01);
this->setFiltGain(1,0.01);
this->setFiltGain(2,0.01);
this->setFiltGain(3,0.01);
this->clear();
filters[0]->setEqualGainZeroes();
filters[1]->setEqualGainZeroes();
filters[2]->setEqualGainZeroes();
filters[3]->setEqualGainZeroes();
stickHardness = 0.5;
strikePosition = 0.561;
}
Modal4 :: ~Modal4()
{
delete envelope;
delete wave;
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 *= 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(1.0);
envelope->setTarget(amplitude);
onepole->setPole(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(1.0 - (amp * 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 = 1.0 + (vibr->tick() * vibrGain); /* Calculate AM */
temp2 = temp * temp2; /* and apply to master out */
}
lastOutput = temp2 * 2.0;
return lastOutput;
}

View File

@@ -1,52 +0,0 @@
/*******************************************/
/* 4 Resonance Modal Synthesis Instrument */
/* by Perry R. Cook, 1995-96 */
/* This instrument contains an excitation */
/* wavetable, an envelope, and four reso- */
/* nances (Non-Sweeping BiQuad Filters). */
/*******************************************/
#if !defined(__Modal4_h)
#define __Modal4_h
#include "Instrmnt.h"
#include "Envelope.h"
#include "RawWave.h"
#include "RawLoop.h"
#include "BiQuad.h"
#include "OnePole.h"
class Modal4 : public Instrmnt
{
protected:
Envelope *envelope;
RawWave *wave;
BiQuad *filters[4];
OnePole *onepole;
RawLoop *vibr;
MY_FLOAT vibrGain;
MY_FLOAT masterGain;
MY_FLOAT directGain;
MY_FLOAT stickHardness;
MY_FLOAT strikePosition;
MY_FLOAT baseFreq;
MY_FLOAT ratios[4];
MY_FLOAT resons[4];
public:
Modal4();
~Modal4();
void clear();
virtual void setFreq(MY_FLOAT frequency);
void setRatioAndReson(int whichOne, MY_FLOAT ratio, MY_FLOAT reson);
void setMasterGain(MY_FLOAT aGain);
void setDirectGain(MY_FLOAT aGain);
void setFiltGain(int whichOne, MY_FLOAT gain);
virtual void strike(MY_FLOAT amplitude);
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
virtual void noteOff(MY_FLOAT amp);
void damp(MY_FLOAT amplitude);
virtual void controlChange(int number, MY_FLOAT value);
virtual MY_FLOAT tick();
};
#endif

View File

@@ -1,84 +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 0.999
#define RND_SCALE 10.0
#include "Modulatr.h"
Modulatr :: Modulatr()
{
vibwave = new RawWave("rawwaves/sinewave.raw");
vibwave->normalize();
vibwave->setFreq(6.0);
vibwave->setLooping(1);
vibAmt = 0.04;
noise = new SubNoise(330);
rndAmt = 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 = 0.0;
}
void Modulatr :: setVibFreq(double vibFreq)
{
vibwave->setFreq(vibFreq);
}
void Modulatr :: setVibAmt(double vibAmount)
{
vibAmt = vibAmount;
}
void Modulatr :: setRndAmt(double rndAmount)
{
rndAmt = rndAmount;
onepole->setGain(RND_SCALE * rndAmt);
}
double Modulatr :: tick()
{
lastOutput = vibAmt * vibwave->tick(); /* Compute periodic and */
lastOutput += onepole->tick(noise->tick()); /* random modulations */
return lastOutput;
}
double Modulatr :: lastOut()
{
return lastOutput;
}
/************ Test Main Program *****************/
/*
void main()
{
Modulatr testMod;
FILE *fd;
short data;
long i;
fd = fopen("test.raw","wb");
for (i=0;i<20000;i++) {
data = testMod.tick() * 32000.0;
fwrite(&data,2,1,fd);
}
fclose(fd);
}
*/

View File

@@ -1,36 +0,0 @@
/*******************************************/
/* Modulator Class, Perry R. Cook, 1995-96*/
/* This Object combines random and */
/* periodic modulations to give a nice */
/* natural human modulation function. */
/*******************************************/
#if !defined(__Modulatr_h)
#define __Modulatr_h
#include "Object.h"
#include "RawWave.h"
#include "SubNoise.h"
#include "OnePole.h"
class Modulatr : public Object
{
protected:
RawWave *vibwave;
SubNoise *noise;
OnePole *onepole;
double vibAmt;
double rndAmt;
double lastOutput;
public:
Modulatr();
~Modulatr();
void reset();
void setVibFreq(double vibFreq);
void setVibAmt(double vibAmount);
void setRndAmt(double rndAmount);
double tick();
double lastOut();
};
#endif

108
Moog1.cpp
View File

@@ -1,108 +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"
Moog1 :: Moog1() : SamplFlt()
{
attacks[0] = new RawWave("rawwaves/mandpluk.raw");
loops[0] = new RawWave("rawwaves/impuls20.raw");
loops[1] = new RawWave("rawwaves/sinewave.raw"); /* Steal one for vibrato */
attacks[0]->normalize();
loops[0]->normalize();
loops[0]->setLooping(1);
loops[1]->normalize();
loops[1]->setLooping(1);
loops[1]->setFreq(6.122);
adsr->setAll(0.05,0.00003,0.6,0.0002);
filterQ = 0.85;
filterRate = 0.0001;
modDepth = 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 * 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 * 0.5;
loopGain = amp;
temp = filterQ+0.05;
filters[0]->setStates(2000,temp,2.0 * (1.0 - temp));
filters[1]->setStates(2000,temp,2.0 * (1.0 - temp));
temp = filterQ+0.099;
filters[0]->setTargets( 0,temp,2.0 * (1.0 - temp));
filters[1]->setTargets( 0,temp,2.0 * (1.0 - temp));
filters[0]->setSweepRate(filterRate * RATE_NORM);
filters[1]->setSweepRate(filterRate * RATE_NORM);
#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 * 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 == MIDI_control1)
filterQ = 0.80 + (0.1 * value * NORM_7);
else if (number == MIDI_control2)
filterRate = (value * NORM_7 * 0.0002);
else if (number == MIDI_control3)
this->setModulationSpeed(value * NORM_7 * 12.0);
else if (number == MIDI_mod_wheel)
this->setModulationDepth(value * NORM_7);
else if (number == MIDI_after_touch)
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 * (1.0 + temp));
}
lastOutput = SamplFlt :: tick();
return lastOutput;
}

34
Moog1.h
View File

@@ -1,34 +0,0 @@
/******************************************/
/* Moog1 Subclass of */
/* Sampling Synthesizer Class */
/* by Perry R. Cook, 1995-96 */
/* */
/* Controls: CONTROL1 = filterQ */
/* CONTROL2 = filterRate */
/* CONTROL3 = vibFreq */
/* MOD_WHEEL= vibAmt */
/******************************************/
#if !defined(__Moog1_h)
#define __Moog1_h
#include "SamplFlt.h"
class Moog1 : public SamplFlt
{
private:
MY_FLOAT modDepth;
MY_FLOAT filterQ;
MY_FLOAT filterRate;
public:
Moog1();
~Moog1();
virtual void setFreq(MY_FLOAT frequency);
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
void setModulationSpeed(MY_FLOAT mSpeed);
void setModulationDepth(MY_FLOAT mDepth);
virtual void controlChange(int number, MY_FLOAT value);
virtual MY_FLOAT tick();
};
#endif

View File

@@ -1,163 +0,0 @@
/*******************************************/
/* NonInterpolating One-Shot Raw Sound- */
/* file Class, by Perry R. Cook, 1995-96 */
/* This Object can open a raw 16bit data */
/* (signed integers) file, and play back */
/* the data once, with no interpolation */
/* on playback. Once finished, it closes */
/* the file, the file is reopened with */
/* the reset() method. */
/* This is useful for small memory model, */
/* applications, or for streaming from */
/* disk (and generally non real-time */
/* applications). */
/*******************************************/
#include "NIFileIn.h"
NIFileIn :: NIFileIn(char *fileName)
{
long i;
strcpy(fileNm,fileName);
myFile = fopen(fileNm,"rb");
if (!myFile) {
printf("Couldn't find soundfile %s !!!!!!!!\n",fileName);
exit(0);
}
i = 0;
while (fread(&data,2,1,myFile)) i++;
length = i;
fseek(myFile,0,0);
time = 0.0;
rate = 1.0;
lastTime = 0;
finished = 0;
gain = 1.0;
lastOutput = 0.0;
}
NIFileIn :: ~NIFileIn()
{
this->finish();
}
void NIFileIn :: reset()
{
if (finished) {
myFile = fopen(fileNm,"rb");
}
fseek(myFile,0,0);
printf("Resetting\n");
time = 0.0;
lastTime = 0;
finished = 0;
lastOutput = 0.0;
}
void NIFileIn :: normalize()
{
this->normalize(1.0);
}
void NIFileIn :: normalize(MY_FLOAT newPeak)
{
long i;
FILE *fd;
gain = 0.0;
fd = fopen(fileNm,"rb");
for (i=0;i<length;i++) {
fread(&data,2,1,fd);
if (fabs(data) > gain)
gain = fabs(data);
}
if (gain > 0.0) {
gain = newPeak / gain;
}
fclose(fd);
}
void NIFileIn :: setRate(MY_FLOAT aRate)
{
rate = aRate;
}
void NIFileIn :: finish()
{
finished = 1;
lastOutput = 0.0;
if (myFile) {
fclose(myFile);
myFile = 0;
}
}
MY_FLOAT NIFileIn :: tick()
{
this->informTick();
return lastOutput;
}
int NIFileIn :: informTick()
{
long temp;
if (!finished) {
time += rate; /* Update current time */
if (time >= length) { /* Check for end of sound */
time = length - 1; /* stick at end */
finished = 1; /* Information for one-shot use */
fclose(myFile);
myFile = 0;
}
else {
temp = (long) time; /* Integer part of time address */
if (temp > lastTime) { /* If we cross next sample time */
lastTime = temp;
fread(&data,2,1,myFile); /* Snarf next sample from file */
lastOutput = data * gain; /* And save as non-interpolated data */
}
}
}
return finished;
}
MY_FLOAT NIFileIn :: lastOut()
{
return lastOutput;
}
/************ Test Main Program *****************/
/*
void main()
{
NIFileIn oneShot("rawwaves/mandpluk.raw");
FILE *fd;
short data;
long i;
fd = fopen("test.raw","wb");
oneShot.setRate(1.0);
while (!oneShot.informTick()) {
data = oneShot.lastOut();
fwrite(&data,2,1,fd);
}
oneShot.reset();
oneShot.setRate(0.5);
for (i=0;i<16384;i++) {
data = oneShot.tick();
fwrite(&data,2,1,fd);
}
fclose(fd);
}
*/

View File

@@ -1,47 +0,0 @@
/*******************************************/
/* NonInterpolating One-Shot Raw Sound- */
/* file Class, by Perry R. Cook, 1995-96 */
/* This Object can open a raw 16bit data */
/* (signed integers) file, and play back */
/* the data once, with no interpolation */
/* on playback. Once finished, it closes */
/* the file, the file is reopened with */
/* the reset() method. */
/* This is useful for small memory model, */
/* applications, or for streaming from */
/* disk (and generally non real-time */
/* applications). */
/*******************************************/
#if !defined(__NIFileIn_h)
#define __NIFileIn_h
#include "Object.h"
class NIFileIn : public Object
{
protected:
long length;
long lastTime;
int finished;
short data;
char fileNm[128];
FILE *myFile;
MY_FLOAT rate;
MY_FLOAT time;
MY_FLOAT gain;
MY_FLOAT lastOutput;
public:
NIFileIn(char *fileName);
~NIFileIn();
void reset();
void normalize();
void normalize(MY_FLOAT newPeak);
void setRate(MY_FLOAT aRate);
void finish();
MY_FLOAT tick();
int informTick();
MY_FLOAT lastOut();
};
#endif

View File

@@ -1,119 +0,0 @@
/*******************************************/
/* NonInterpolating One-Shot Raw Sound- */
/* file Class, by Perry R. Cook, 1995-96 */
/* This Object can open a raw 16bit data */
/* (signed integers) file, and play back */
/* the data once (again when reset), with */
/* no interpolation on playback. */
/*******************************************/
#include "NIWave1S.h"
NIWave1S :: NIWave1S(char *fileName)
{
long i;
short temp;
FILE *fd;
fd = fopen(fileName,"rb");
if (!fd) {
printf("Couldn't find soundfile %s !!!!!!!!\n",fileName);
exit(0);
}
i = 0;
while (fread(&temp,2,1,fd)) i++;
length = i;
fseek(fd,0,0);
data = (MY_FLOAT *) malloc(MY_FLOAT_SIZE * (length + 1));
i = 0;
while (fread(&temp,2,1,fd)) {
data[i] = temp;
i++;
}
data[length] = data[length-1];
fclose(fd);
time = 0.0;
rate = 1.0;
}
void NIWave1S :: reset()
{
time = 0.0;
lastOutput = 0.0;
}
void NIWave1S :: normalize()
{
this->normalize(1.0);
}
void NIWave1S :: normalize(MY_FLOAT newPeak)
{
long i;
MY_FLOAT max = 0.0;
for (i=0;i<=length;i++)
if (fabs(data[i]) > max)
max = fabs(data[i]);
if (max > 0.0) {
max = 1.0 / max;
max *= newPeak;
for (i=0;i<=length;i++)
data[i] *= max;
}
}
void NIWave1S :: setRate(MY_FLOAT aRate)
{
rate = aRate;
}
MY_FLOAT NIWave1S :: tick()
{
this->informTick();
return lastOutput;
}
int NIWave1S :: informTick()
{
int allDone = 0;
long temp;
time += rate; /* Update current time */
if (time >= length) { /* Check for end of sound */
time = length-1; /* stick at end */
allDone = 1; /* Information for one-shot use */
}
temp = (long) time; /* Integer part of time address */
lastOutput = data[temp]; /* Get non-interpolated data */
return allDone;
}
MY_FLOAT NIWave1S :: lastOut()
{
return lastOutput;
}
/************ Test Main Program *****************/
/*
void main()
{
NIWave1S oneShot("rawwaves/mandpluk.raw");
FILE *fd;
short data;
long i;
fd = fopen("test.raw","wb");
for (i=0;i<8192;i++) {
data = oneShot.tick();
fwrite(&data,2,1,fd);
}
oneShot.reset();
oneShot.setRate(0.5);
for (i=0;i<16384;i++) {
data = oneShot.tick();
fwrite(&data,2,1,fd);
}
fclose(fd);
}
*/

View File

@@ -1,34 +0,0 @@
/*******************************************/
/* NonInterpolating One-Shot Raw Sound- */
/* file Class, by Perry R. Cook, 1995-96 */
/* This Object can open a raw 16bit data */
/* (signed integers) file, and play back */
/* the data once (again when reset), with */
/* no interpolation on playback. */
/*******************************************/
#if !defined(__NIWave1S_h)
#define __NIWave1S_h
#include "Object.h"
class NIWave1S : public Object
{
protected:
long length;
MY_FLOAT *data;
MY_FLOAT rate;
MY_FLOAT time;
MY_FLOAT lastOutput;
public:
NIWave1S(char *fileName);
void reset();
void normalize();
void normalize(MY_FLOAT newPeak);
void setRate(MY_FLOAT aRate);
MY_FLOAT tick();
int informTick();
MY_FLOAT lastOut();
};
#endif

View File

@@ -1,52 +0,0 @@
/*******************************************/
/* Noise Generator Class, */
/* by Perry R. Cook, 1995-96 */
/* White noise as often as you like. */
/*******************************************/
#include "Noise.h"
Noise :: Noise() : Object()
{
lastOutput = 0.0;
}
Noise :: ~Noise()
{
}
/* THIS IS FOR TURBO C */
/* Constant = 1.0 / 16384.0 */
/* #define ONE_OVER_RANDLIMIT 0.00006103516 */
/* THIS IS FOR UNIX, NeXT and SGI */
#define ONE_OVER_RANDLIMIT 0.00000000093132258
MY_FLOAT Noise :: tick()
{
/* THIS ONE IS TURBO C */
/* lastOutput = (MY_FLOAT) random(32767) - 16384.0; */
/* THIS IS FOR UNIX, NeXT and SGI */
lastOutput = (MY_FLOAT) random() - 1073741823.0;
lastOutput *= ONE_OVER_RANDLIMIT;
return lastOutput;
}
MY_FLOAT Noise :: lastOut()
{
return lastOutput;
}
/************ Test Main ************************/
/*
void main()
{
long i;
Noise test;
for (i=0;i<20;i++) printf("%lf\n",test.tick());
}
*/

23
Noise.h
View File

@@ -1,23 +0,0 @@
/*******************************************/
/* Noise Generator Class, */
/* by Perry R. Cook, 1995-96 */
/* White noise as often as you like. */
/*******************************************/
#if !defined(__Noise_h)
#define __Noise_h
#include "Object.h"
class Noise : public Object
{
protected:
MY_FLOAT lastOutput;
public:
Noise();
~Noise();
virtual MY_FLOAT tick();
MY_FLOAT lastOut();
};
#endif

View File

@@ -1,29 +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"
/* 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()
{
MIDI_mod_wheel = 1; /* Controller # 1 */
MIDI_control1 = 2; /* Breath Pressure */
MIDI_control2 = 4; /* Foot Control */
MIDI_control3 = 11; /* Expression Pedal */
MIDI_after_touch = 128; /* Channel Pressure -> new controller */
}
Object :: ~Object()
{
}

View File

@@ -1,91 +0,0 @@
/*******************************************/
/* Object Class, by Perry R. Cook, 1995-96*/
/* This is mostly here for compatibility */
/* with Objective C. We'll also stick */
/* global defines here, so everyone will */
/* see them. */
/*******************************************/
#if !defined(__Object_h)
#define __Object_h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
class Object
{
public:
int MIDI_control1;
int MIDI_control2;
int MIDI_control3;
int MIDI_mod_wheel;
int MIDI_after_touch;
protected:
Object();
~Object();
};
/* Only use one of __SGI_ __NeXT_ __DOS_ */
/* And choice of __SGI_REALTIME or not */
#define __SGI_
#define __SGI_REALTIME
/* #define __NeXT_ */
/* SRATE here is 44100, others are derived accordingly */
/* #define SRATE 44100.0
#define SRATE_OVER_TWO 22050.0
#define ONE_OVER_SRATE 0.00002267573696
#define RATE_NORM 0.5
*/
/* SRATE here is 22050, others are derived accordingly */
#define SRATE 22050.0
#define SRATE_OVER_TWO 11025.0
#define ONE_OVER_SRATE 0.00004535147392
#define RATE_NORM 1.0
/* SRATE here is 8k, others are derived accordingly */
/* #define SRATE 8000.0
#define SRATE_OVER_TWO 4000
#define ONE_OVER_SRATE 0.00012500000000
#define RATE_NORM 2.75625
*/
/* RATE_NORM is 22050 / 8000 */
/* Yer Basic Trigonometric constants */
#define PI 3.14159265359
#define TWO_PI 6.28318530718
#define ONE_OVER_TWO_PI 0.15915494309
/* 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 float */
/* #define MY_FLOAT_SIZE 4 */
#define MY_FLOAT double
#define MY_FLOAT_SIZE 8
/* Debugging define, causes massive printf's to come out. */
/* Also enables timing calculations in WaveOut class, other stuff. */
/* #define _debug_ 1 */
#include <stdio.h>
#define NORM_7 0.0078125
/* this is 1/128 for MIDI normalization*/
#endif

View File

@@ -1,81 +0,0 @@
/*******************************************/
/* One Pole Filter Class, */
/* by Perry R. Cook, 1995-96 */
/* The parameter gain is an additional */
/* gain parameter applied to the filter */
/* on top of the normalization that takes */
/* place automatically. So the net max */
/* gain through the system equals the */
/* value of gain. sgain is the combina- */
/* tion of gain and the normalization */
/* parameter, so if you set the poleCoeff */
/* to alpha, sgain is always set to */
/* gain * (1.0 - fabs(alpha)). */
/*******************************************/
#include "OnePole.h"
OnePole :: OnePole() : Filter()
{
poleCoeff = 0.9;
gain = 1.0;
sgain = 0.1;
outputs = (MY_FLOAT *) malloc(MY_FLOAT_SIZE);
outputs[0] = 0.0;
}
OnePole :: ~OnePole()
{
free(outputs);
}
void OnePole :: clear()
{
outputs[0] = 0.0;
lastOutput = 0.0;
}
void OnePole :: setPole(MY_FLOAT aValue)
{
poleCoeff = aValue;
if (poleCoeff > 0.0) /* Normalize gain to 1.0 max */
sgain = gain * (1.0 - poleCoeff);
else
sgain = gain * (1.0 + poleCoeff);
}
void OnePole :: setGain(MY_FLOAT aValue)
{
gain = aValue;
if (poleCoeff > 0.0)
sgain = gain * (1.0 - poleCoeff); /* Normalize gain to 1.0 max */
else
sgain = gain * (1.0 + poleCoeff);
}
MY_FLOAT OnePole :: tick(MY_FLOAT sample) /* Perform Filter Operation */
{
outputs[0] = (sgain * sample) + (poleCoeff * outputs[0]);
lastOutput = outputs[0];
return lastOutput;
}
/************ Test Main ************************/
/*
#include <stdio.h>
void main()
{
long i;
OnePole test;
test.setPole(0.99);
for (i=0;i<150;i++) printf("%lf ",test.tick(1.0));
printf("\n\n");
test.clear();
test.setPole(0.9);
test.setGain(2.0);
for (i=0;i<150;i++) printf("%lf ",test.tick(0.5));
printf("\n\n");
}
*/

View File

@@ -1,35 +0,0 @@
/*******************************************/
/* One Pole Filter Class, */
/* by Perry R. Cook, 1995-96 */
/* The parameter gain is an additional */
/* gain parameter applied to the filter */
/* on top of the normalization that takes */
/* place automatically. So the net max */
/* gain through the system equals the */
/* value of gain. sgain is the combina- */
/* tion of gain and the normalization */
/* parameter, so if you set the poleCoeff */
/* to alpha, sgain is always set to */
/* gain * (1.0 - fabs(alpha)). */
/*******************************************/
#if !defined(__OnePole_h)
#define __OnePole_h
#include "Filter.h"
class OnePole : public Filter
{
protected:
MY_FLOAT poleCoeff;
MY_FLOAT sgain;
public:
OnePole();
~OnePole();
void clear();
void setPole(MY_FLOAT aValue);
void setGain(MY_FLOAT aValue);
MY_FLOAT tick(MY_FLOAT sample);
};
#endif

View File

@@ -1,64 +0,0 @@
/*******************************************/
/* One Zero Filter Class, */
/* by Perry R. Cook, 1995-96 */
/* The parameter gain is an additional */
/* gain parameter applied to the filter */
/* on top of the normalization that takes */
/* place automatically. So the net max */
/* gain through the system equals the */
/* value of gain. sgain is the combina- */
/* tion of gain and the normalization */
/* parameter, so if you set the poleCoeff */
/* to alpha, sgain is always set to */
/* gain / (1.0 - fabs(alpha)). */
/*******************************************/
#include "OneZero.h"
OneZero :: OneZero()
{
gain = 1.0;
zeroCoeff = 1.0;
sgain = 0.5;
inputs = (MY_FLOAT *) malloc(MY_FLOAT_SIZE);
this->clear();
}
OneZero :: ~OneZero()
{
free(inputs);
}
void OneZero :: clear()
{
inputs[0] = 0.0;
lastOutput = 0.0;
}
void OneZero :: setGain(MY_FLOAT aValue)
{
gain = aValue;
if (zeroCoeff > 0.0) /* Normalize gain to 1.0 max */
sgain = gain / (1.0 + zeroCoeff);
else
sgain = gain / (1.0 - zeroCoeff);
}
void OneZero :: setCoeff(MY_FLOAT aValue)
{
zeroCoeff = aValue;
if (zeroCoeff > 0.0) /* Normalize gain to 1.0 max */
sgain = gain / (1.0 + zeroCoeff);
else
sgain = gain / (1.0 - zeroCoeff);
}
MY_FLOAT OneZero :: tick(MY_FLOAT sample) /* Perform Filter Operation */
{
MY_FLOAT temp;
temp = sgain * sample;
lastOutput = (inputs[0] * zeroCoeff) + temp;
inputs[0] = temp;
return lastOutput;
}

View File

@@ -1,35 +0,0 @@
/*******************************************/
/* One Zero Filter Class, */
/* by Perry R. Cook, 1995-96 */
/* The parameter gain is an additional */
/* gain parameter applied to the filter */
/* on top of the normalization that takes */
/* place automatically. So the net max */
/* gain through the system equals the */
/* value of gain. sgain is the combina- */
/* tion of gain and the normalization */
/* parameter, so if you set the poleCoeff */
/* to alpha, sgain is always set to */
/* gain / (1.0 - fabs(alpha)). */
/*******************************************/
#if !defined(__OneZero_h)
#define __OneZero_h
#include "Filter.h"
class OneZero : public Filter
{
protected:
MY_FLOAT zeroCoeff;
MY_FLOAT sgain;
public:
OneZero();
~OneZero();
void clear();
void setGain(MY_FLOAT aValue);
void setCoeff(MY_FLOAT aValue);
MY_FLOAT tick(MY_FLOAT sample);
};
#endif

View File

@@ -1,50 +0,0 @@
/******************************************/
/* Percussive Flute Subclass */
/* of Algorithm 4 (TX81Z) Subclass of */
/* 4 Operator FM Synth */
/* by Perry R. Cook, 1995-96 */
/******************************************/
#include "PercFlut.h"
PercFlut :: PercFlut() : FM4Alg4()
{
this->loadWaves("rawwaves/sinewave.raw",
"rawwaves/sinewave.raw",
"rawwaves/sinewave.raw",
"rawwaves/sinewave.raw");
this->setRatio(0,1.50 );
this->setRatio(1,3.00 * 0.995);
this->setRatio(2,2.99 * 1.005);
this->setRatio(3,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]->setAll(0.001,0.001,__FM4Op_susLevels[14],0.001);
adsr[1]->setAll(0.05,0.0001,__FM4Op_susLevels[13],0.0001);
adsr[2]->setAll(0.05,0.0020,__FM4Op_susLevels[11],0.001);
adsr[3]->setAll(0.05,0.0010,__FM4Op_susLevels[13],0.005);
twozero->setGain(0.0);
modDepth = 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];
gains[1] = amp * __FM4Op_gains[71];
gains[2] = amp * __FM4Op_gains[93];
gains[3] = amp * __FM4Op_gains[85];
this->setFreq(freq);
this->keyOn();
#if defined(_debug_)
printf("PercFlut : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
#endif
}

View File

@@ -1,21 +0,0 @@
/******************************************/
/* Percussive Flute Subclass */
/* of Algorithm 4 (TX81Z) Subclass of */
/* 4 Operator FM Synth */
/* by Perry R. Cook, 1995-96 */
/******************************************/
#if !defined(__PercFlut_h)
#define __PercFlut_h
#include "FM4Alg4.h"
class PercFlut : public FM4Alg4
{
public:
PercFlut();
virtual void setFreq(MY_FLOAT frequency);
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
};
#endif

View File

@@ -1,189 +0,0 @@
double phonGains[32][2] =
{{1.0,0.0}, // eee
{1.0,0.0}, // ihh
{1.5,0.0}, // ehh
{1.0,0.0}, // aaa
{0.5,0.0}, // ahh
{0.5,0.0}, // aww
{0.5,0.0}, // ohh
{0.5,0.0}, // uhh
{0.5,0.0}, // uuu
{0.15,0.0}, // ooo
{0.15,0.0}, // rrr
{6.0,0.0}, // lll
{1.0,0.0}, // mmm
{1.0,0.0}, // nnn
{1.0,0.0}, // nng
{1.0,0.0}, // ngg
{0.0,1.0}, // fff
{0.0,1.0}, // sss
{0.0,1.0}, // thh
{0.0,1.0}, // shh
{0.0,0.2}, // xxx
{0.0,0.003}, // hee
{0.0,0.001}, // hoo
{0.0,0.002}, // hah
{1.0,0.4}, // bbb
{4.0,0.1}, // ddd
{1.0,0.4}, // jjj
{1.0,0.4}, // ggg
{1.0,0.1}, // vvv
{1.0,0.1}, // zzz
{1.0,0.1}, // thz
{1.0,0.1} // zhh
};
double phonParams[32][4][3] =
{{ { 273,0.996, 0}, // eee (beet)
{2086,0.945, -16},
{2754,0.979, -12},
{3270,0.440, -17}},
{ { 385,0.987, 0}, // ihh (bit)
{2056,0.930, -20},
{2587,0.890, -20},
{3150,0.400, -20}},
{ { 515,0.977, 0}, // ehh (bet)
{1805,0.810, -10},
{2526,0.875, -10},
{3103,0.400, -13}},
{ { 773,0.950, 0}, // aaa (bat)
{1676,0.830, -6},
{2380,0.880, -20},
{3027,0.600, -20}},
{ { 770,0.950, 0}, // ahh (father)
{1153,0.970, -3},
{2450,0.780, -20},
{3140,0.800, -32}},
{ { 637,0.910, 0}, // aww (bought)
{ 895,0.900, -3},
{2556,0.950, -17},
{3070,0.910, -20}},
{ { 637,0.910, 0}, // ohh (bone) NOTE:: same as aww (bought)
{ 895,0.900, -3},
{2556,0.950, -17},
{3070,0.910, -20}},
{ { 561,0.965, 0}, // uhh (but)
{1084,0.930, -10},
{2541,0.930, -15},
{3345,0.900, -20}},
{ { 515,0.976, 0}, // uuu (foot)
{1031,0.950, -3},
{2572,0.960, -11},
{3345,0.960, -20}},
{ { 349,0.986, 0}, // ooo (boot)
{ 918,0.940, -10},
{2350,0.960, -17},
{2731,0.950, -23}},
{ { 394,0.959, 0}, // rrr (bird)
{1297,0.780, -6},
{1441,0.980, -6},
{2754,0.950, -30}},
{ { 462,0.940, 0}, // lll (lull)
{2754,0.900, -30},
{3406,0.100, -30},
{3755,0.100, -30}},
{ { 265,0.987, 0}, // mmm (mom)
{1176,0.940, -22},
{2352,0.970, -20},
{3277,0.940, -31}},
{ { 204,0.980, 0}, // nnn (nun)
{1570,0.940, -15},
{2481,0.980, -12},
{3133,0.800, -30}},
{ { 204,0.980, 0}, // nng (sang) NOTE:: same as nnn
{1570,0.940, -15},
{2481,0.980, -12},
{3133,0.800, -30}},
{ { 204,0.980, 0}, // ngg (bong) NOTE:: same as nnn
{1570,0.940, -15},
{2481,0.980, -12},
{3133,0.800, -30}},
{ {1000,0.300, -10}, // fff
{2800,0.860, -10},
{7425,0.740, 0},
{8140,0.860, 0}},
{ {2000,0.700, -20}, // sss
{5257,0.750, -15},
{7171,0.840, -3},
{9000,0.900, 0}},
{ { 100,0.900, 0}, // thh
{4000,0.500, -20},
{5500,0.500, -15},
{8000,0.400, -20}},
{ {2693,0.940, 0}, // shh
{4000,0.720, -10},
{6123,0.870, -10},
{7755,0.750, -18}},
{ {1000,0.300, -10}, // xxx NOTE:: Not Really Done Yet
{2800,0.860, -10},
{7425,0.740, 0},
{8140,0.860, 0}},
{ { 273,0.996, 0}, // hee (beet) (noisy eee)
{2086,0.945, -16},
{2754,0.979, -12},
{3270,0.440, -17}},
{ { 349,0.986, 0}, // hoo (boot) (noisy ooo)
{ 918,0.940, -10},
{2350,0.960, -17},
{2731,0.950, -23}},
{ { 770,0.950, 0}, // hah (father) (noisy ahh)
{1153,0.970, -3},
{2450,0.780, -20},
{3140,0.800, -32}},
{ {2000,0.700, -20}, // bbb NOTE:: Not Really Done Yet
{5257,0.750, -15},
{7171,0.840, -3},
{9000,0.900, 0}},
{ { 100,0.900, 0}, // ddd NOTE:: Not Really Done Yet
{4000,0.500, -20},
{5500,0.500, -15},
{8000,0.400, -20}},
{ {2693,0.940, 0}, // jjj NOTE:: Not Really Done Yet
{4000,0.720, -10},
{6123,0.870, -10},
{7755,0.750, -18}},
{ {2693,0.940, 0}, // ggg NOTE:: Not Really Done Yet
{4000,0.720, -10},
{6123,0.870, -10},
{7755,0.750, -18}},
{ {2000,0.700, -20}, // vvv NOTE:: Not Really Done Yet
{5257,0.750, -15},
{7171,0.840, -3},
{9000,0.900, 0}},
{ { 100,0.900, 0}, // zzz NOTE:: Not Really Done Yet
{4000,0.500, -20},
{5500,0.500, -15},
{8000,0.400, -20}},
{ {2693,0.940, 0}, // thz NOTE:: Not Really Done Yet
{4000,0.720, -10},
{6123,0.870, -10},
{7755,0.750, -18}},
{ {2693,0.940, 0}, // zhh NOTE:: Not Really Done Yet
{4000,0.720, -10},
{6123,0.870, -10},
{7755,0.750, -18}}
};
char phonemes[32][4] =
{"eee","ihh","ehh","aaa",
"ahh","aww","ohh","uhh",
"uuu","ooo","rrr","lll",
"mmm","nnn","nng","ngg",
"fff","sss","thh","shh",
"xxx","hee","hoo","hah",
"bbb","ddd","jjj","ggg",
"vvv","zzz","thz","zhh"};

View File

@@ -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 = 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 = ((MY_FLOAT) SRATE / frequency) - 0.5; /* length - delays */
delayLine->setDelay(delay);
loopGain = 0.995 + (frequency * 0.000005);
if (loopGain>1.0) loopGain = 0.99999;
}
void Plucked :: pluck(MY_FLOAT amplitude)
{
long i;
pickFilt->setPole(0.999 - (amplitude*0.15));
pickFilt->setGain(amplitude * 0.5);
for (i=0;i<length;i++)
delayLine->tick(delayLine->lastOut() * 0.6 /* fill delay with noise */
+ pickFilt->tick(noise->tick())); /* additively with current */
/* contents */
}
void Plucked :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
{
this->setFreq(freq);
this->pluck(amp);
#if defined(_debug_)
printf("Plucked : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
#endif
}
void Plucked :: noteOff(MY_FLOAT amp)
{
loopGain = 1.0 - amp;
#if defined(_debug_)
printf("Plucked : NoteOff: Amp=%lf\n",amp);
#endif
}
MY_FLOAT Plucked :: tick()
{
lastOutput = delayLine->tick( /* check this out, */
loopFilt->tick( /* here's the whole inner */
delayLine->lastOut() /* loop of the instrument!! */
* loopGain));
lastOutput *= 3.0;
return lastOutput;
}

View File

@@ -1,40 +0,0 @@
/******************************************/
/* Karplus-Strong plucked string model */
/* by Perry Cook, 1995-96 */
/* */
/* There exist at least two patents, */
/* assigned to Stanford, bearing the */
/* names of Karplus and/or Strong. */
/******************************************/
#if !defined(__Plucked_h)
#define __Plucked_h
#include "Instrmnt.h"
#include "DLineA.h"
#include "OneZero.h"
#include "OnePole.h"
#include "Noise.h"
class Plucked : public Instrmnt
{
protected:
DLineA *delayLine;
OneZero *loopFilt;
OnePole *pickFilt;
Noise *noise;
long length;
MY_FLOAT loopGain;
public:
Plucked(MY_FLOAT lowestFreq);
~Plucked();
void clear();
virtual void setFreq(MY_FLOAT frequency);
void pluck(MY_FLOAT amplitude);
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
virtual void noteOff(MY_FLOAT amp);
virtual MY_FLOAT tick();
};
#endif

View File

@@ -1,90 +0,0 @@
/******************************************/
/* Enhanced (Jaffe-Smith, Smith, others) */
/* Karplus-Strong plucked model */
/* by Perry Cook, 1995-96 */
/* This is the super-class, with no */
/* excitation specified. So this one by */
/* itself doesn't make any sound. */
/******************************************/
#include "Plucked2.h"
Plucked2 :: Plucked2(MY_FLOAT lowestFreq)
{
length = (long) (SRATE / lowestFreq + 1);
baseLoopGain = 0.995;
loopGain = 0.999;
delayLine = new DLineA(length);
delayLine2 = new DLineA(length);
combDelay = new DLineL(length);
filter = new OneZero;
filter2 = new OneZero;
pluckAmp = 0.3;
pluckPos = 0.4;
detuning = 0.995;
lastFreq = lowestFreq * 2.0;
lastLength = length * 0.5;
}
Plucked2 :: ~Plucked2()
{
delete delayLine;
delete delayLine2;
delete combDelay;
delete filter;
delete filter2;
}
void Plucked2 :: clear()
{
delayLine->clear();
delayLine2->clear();
combDelay->clear();
filter->clear();
filter2->clear();
}
void Plucked2 :: setFreq(MY_FLOAT frequency)
{
lastFreq = frequency;
lastLength = ((MY_FLOAT) SRATE / lastFreq); /* length - delays */
delayLine->setDelay((lastLength / detuning) - 0.5);
delayLine2->setDelay((lastLength * detuning) - 0.5);
loopGain = baseLoopGain + (frequency * 0.000005);
if (loopGain>1.0) loopGain = 0.99999;
}
void Plucked2 :: setDetune(MY_FLOAT detune)
{
detuning = detune;
delayLine->setDelay((lastLength / detuning) - 0.5);
delayLine2->setDelay((lastLength * detuning) - 0.5);
}
void Plucked2 :: setFreqAndDetune(MY_FLOAT frequency,MY_FLOAT detune)
{
lastFreq = frequency;
detuning = detune;
this->setFreq(frequency);
}
void Plucked2 :: setPluckPos(MY_FLOAT position)
{
pluckPos = position;
}
void Plucked2 :: setBaseLoopGain(MY_FLOAT aGain)
{
baseLoopGain = aGain;
loopGain = baseLoopGain + (lastFreq * 0.000005);
if (loopGain>1.0) loopGain = 0.99999;
}
void Plucked2 :: noteOff(MY_FLOAT amp)
{
loopGain = (1.0 - amp) * 0.5;
#if defined(_debug_)
printf("Plucked2 : NoteOff: Amp=%lf\n",amp);
#endif
}

View File

@@ -1,46 +0,0 @@
/******************************************/
/* Enhanced (Jaffe-Smith, Smith, others) */
/* Karplus-Strong plucked model */
/* by Perry Cook, 1995-96 */
/* This is the super-class, with no */
/* excitation specified. So this one by */
/* itself doesn't make any sound. */
/******************************************/
#if !defined(__Plucked2_h)
#define __Plucked2_h
#include "Instrmnt.h"
#include "DLineL.h"
#include "DLineA.h"
#include "OneZero.h"
class Plucked2 : public Instrmnt
{
protected:
DLineA *delayLine;
DLineA *delayLine2;
DLineL *combDelay;
OneZero *filter;
OneZero *filter2;
long length;
MY_FLOAT loopGain;
MY_FLOAT baseLoopGain;
MY_FLOAT lastFreq;
MY_FLOAT lastLength;
MY_FLOAT detuning;
MY_FLOAT pluckAmp;
MY_FLOAT pluckPos;
public:
Plucked2(MY_FLOAT lowestFreq);
~Plucked2();
void clear();
virtual void setFreq(MY_FLOAT frequency);
void setDetune(MY_FLOAT detune);
void setFreqAndDetune(MY_FLOAT frequency, MY_FLOAT detune);
void setPluckPos(MY_FLOAT position);
void setBaseLoopGain(MY_FLOAT aGain);
virtual void noteOff(MY_FLOAT amp);
};
#endif

194
README.md Normal file
View File

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

View File

@@ -1,117 +0,0 @@
TK96CPP
A ToolKit of Audio Synthesis Classes
and Instruments in C++
Perry Cook, 1995-96
Please read the Legal and Ethical notes at the
bottom of this document.
For instant fun, if you get it to compile (see
below) type TestAllNext or TestAllSGIRT. The
former makes sound files of each instrument and
saves them under the instrument name. The latter
plays in real time from a SKINI scorefile.
For even more potential fun, try the GUI and MIDI
interface demos in the directory TCLSpecs. MIDI
is SGI specific for today, look for more support
later. TCL works on SGI, maybe elsewhere, but
you must have and install Tcl/TK.
For more documentation on this ToolKit, the classes,
etc, read the file HIERARCH.txt and the individual
class definitions.
SGI vs. NeXT vs. Intel vs. the world:
See Object.h and Makefile for machine-specific
items.
Initial public release. Some objects still beta.
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 (see Adrian Freed's home page for some
nice experience-based thoughts on that topic).
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++ unitgenerators 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 . . .
***********************************************************
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 me some.
If you make compositions with it, put me in the
program notes.
Some of the concepts are covered by various patents,
some known to me and likely others which are unknown.
Many of the ones known to me 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, I'll not state what's freely useable here,
but I'll try to note within the various classes
where certain things are likely to be protected by
patents.
***********************************************************

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