207 Commits
3.1 ... v4.6.0

Author SHA1 Message Date
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
744 changed files with 93117 additions and 25736 deletions

188
.gitignore vendored Normal file
View File

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

View File

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

58
INSTALL.md Normal file
View File

@@ -0,0 +1,58 @@
% The Synthesis ToolKit in C++ (STK)
% Perry R. Cook and Gary P. Scavone
% 1995--2017
# The Synthesis ToolKit in C++ (STK)
By Perry R. Cook and Gary P. Scavone, 1995--2017.
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 Core Audio API (macintosh OS-X only)
--with-asio = choose ASIO API support (windows only)
--with-ds = choose DirectSound API support (windows only)
--with-wasapi = choose Windows Audio Session API support (windows only)
It is now possible to specify more than one audio and MIDI API where supported. Note, however, that the ALSA library is required in order to compile the RtMidi class in Linux if the `--with-oss` option is provided (only the OSS audio API will be used, not the OSS MIDI API). Typing `./configure --help` will display all the available options. In addition, it is possible to specify the RAWWAVES and INCLUDE paths to configure as (ex. to set to /home/me/rawwaves and /home/me/include):
./configure RAWWAVE_PATH='$(HOME)/rawwaves/'
./configure INCLUDE_PATH='$(HOME)/include/'
The ending "/" is required for the RAWWAVES path. The default behavior will set a relative path that works for the project files included with the distribution (assuming they are not moved). You can also change the RAWWAVE_PATH dynamically via the static Stk::setRawwavePath() function.
If you wish to use a different compiler than that selected by configure, specify that compiler in the command line (ex. to use CC):
./configure CXX=CC
## Windows
MinGW support is provided in the configure script. In addition, Visual C++ 6.0 project files are included for each of the example STK projects, though these may not work with more recent versions of Visual Studio.
##iOS
You can integrate the STK in iOS projects either by using its iOS static library or Cocoapods. See the [iOS README file](iOS/README-iOS.md) for instructions.

27
LICENSE Normal file
View File

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

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,17 +0,0 @@
STK: A ToolKit of Audio Synthesis Classes and Instruments in C++
Version 3.1
By Perry R. Cook, 1995-2000
and Gary P. Scavone, 1997-2000.
Please read the file README.txt for more general STK information.
STK for Linux is currently using the OSS sound and MIDI API. The free version of OSS will probably work, though it doesn't work with as many soundcards as the commercial version (which costs about $20). The Advanced Linux Sound Architecture (ALSA) drivers seem to perform well, though I've done only minimal testing with them. You'll need to install the OSS compatability library. You can read more about ALSA at http://www.alsa-project.org/. ALSA is open source and holds great promise for audio under Linux.
STK should compile without much trouble under Linux. Since all Linux distributions typically include the GNU makefile utilities, you should be able to use the default Makefile. Typing "make" will initiate the compilation process.
NOTE REGARDING PTHREADS:
The only issue which seems to crop up on different versions of Linux concerns threads. I am using the MIT pthreads API. Under RedHat Linux 4.x, I had to specifically include <pthread/mit/pthread.h> (the default pthread library didn't work). However, under RedHat Linux 5.0 and higher, the default works and the <pthread/mit/> path doesn't exist. I've decided to assume the default works. If you get errors with regard to pthreads when you compile, you'll have to search your system for the MIT pthread distribution and change the appropriate include statements in MIDIIO.cpp, MD2SKINI.cpp, and threads.cpp.

View File

@@ -1,15 +0,0 @@
STK: A ToolKit of Audio Synthesis Classes and Instruments in C++
Version 3.1
By Perry R. Cook, 1995-2000
and Gary P. Scavone, 1997-2000.
Please read the file README.txt for more general STK information.
It seems that SGI systems are not distributed with the GNU Makefile utilities. The default Make utility has very limited functionality, so your safest bet is to download the GNU Makefile utilities from the Internet and use STK's default Makefile. If this is not possible, try using Makefile.sgi (make -f Makefile.sgi).
Aside from the Makefile issues, STK should compile and run on SGI platforms without any problems.
NOTE REGARDING PTHREADS:
With release 3.1, STK is now using the pthread API under Irix. It appears that pthread functionality is standard on SGI, so this change shouldn't cause any problems. If I'm wrong, let me know!

View File

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

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

View File

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

View File

@@ -1,197 +0,0 @@
/*******************************************/
/* ADSR Subclass of the Envelope Class, */
/* by Perry R. Cook, 1995-96 */
/* This is the traditional ADSR (Attack */
/* Decay, Sustain, Release) ADSR. */
/* It responds to simple KeyOn and KeyOff */
/* messages, keeping track of it's state. */
/* There are two tick (update value) */
/* methods, one returns the value, and */
/* other returns the state (0 = A, 1 = D, */
/* 2 = S, 3 = R) */
/*******************************************/
#include "ADSR.h"
ADSR :: ADSR() : Envelope()
{
target = (MY_FLOAT) 0.0;
value = (MY_FLOAT) 0.0;
attackRate = (MY_FLOAT) 0.001;
decayRate = (MY_FLOAT) 0.001;
sustainLevel = (MY_FLOAT) 0.5;
releaseRate = (MY_FLOAT) 0.01;
state = 0;
}
ADSR :: ~ADSR()
{
/* Nothing to do here */
}
void ADSR :: keyOn()
{
target = (MY_FLOAT) 1.0;
rate = attackRate;
state = 0;
}
void ADSR :: keyOff()
{
target = (MY_FLOAT) 0.0;
rate = releaseRate;
state = 3;
}
void ADSR :: setAttackRate(MY_FLOAT aRate)
{
if (aRate < 0.0) {
printf("negative rates not allowed!!, correcting\n");
attackRate = -aRate;
}
else attackRate = aRate;
}
void ADSR :: setDecayRate(MY_FLOAT aRate)
{
if (aRate < 0.0) {
printf("negative rates not allowed!!, correcting\n");
decayRate = -aRate;
}
else decayRate = aRate;
}
void ADSR :: setSustainLevel(MY_FLOAT aLevel)
{
if (aLevel < 0.0 ) {
printf("Sustain level out of range!!, correcting\n");
sustainLevel = (MY_FLOAT) 0.0;
}
else sustainLevel = aLevel;
}
void ADSR :: setReleaseRate(MY_FLOAT aRate)
{
if (aRate < 0.0) {
printf("negative rates not allowed!!, correcting\n");
releaseRate = -aRate;
}
else releaseRate = aRate;
}
void ADSR :: setAttackTime(MY_FLOAT aTime)
{
if (aTime < 0.0) {
printf("negative times not allowed!!, correcting\n");
attackRate = ONE_OVER_SRATE / -aTime;
}
else attackRate = ONE_OVER_SRATE / aTime;
}
void ADSR :: setDecayTime(MY_FLOAT aTime)
{
if (aTime < 0.0) {
printf("negative times not allowed!!, correcting\n");
decayRate = ONE_OVER_SRATE / -aTime;
}
else decayRate = ONE_OVER_SRATE / aTime;
}
void ADSR :: setReleaseTime(MY_FLOAT aTime)
{
if (aTime < 0.0) {
printf("negative times not allowed!!, correcting\n");
releaseRate = ONE_OVER_SRATE / -aTime;
}
else releaseRate = ONE_OVER_SRATE / aTime;
}
void ADSR :: setAllTimes(MY_FLOAT attTime, MY_FLOAT decTime, MY_FLOAT susLevel, MY_FLOAT relTime)
{
this->setAttackTime(attTime);
this->setDecayTime(decTime);
this->setSustainLevel(susLevel);
this->setReleaseTime(relTime);
}
void ADSR :: setTarget(MY_FLOAT aTarget)
{
target = aTarget;
if (value < target) {
state = ATTACK;
this->setSustainLevel(target);
rate = attackRate;
}
if (value > target) {
this->setSustainLevel(target);
state = DECAY;
rate = decayRate;
}
}
void ADSR :: setValue(MY_FLOAT aValue)
{
state = SUSTAIN;
target = aValue;
value = aValue;
this->setSustainLevel(aValue);
rate = (MY_FLOAT) 0.0;
}
MY_FLOAT ADSR :: tick()
{
if (state==ATTACK) {
value += rate;
if (value >= target) {
value = target;
rate = decayRate;
target = sustainLevel;
state = DECAY;
}
}
else if (state==DECAY) {
value -= decayRate;
if (value <= sustainLevel) {
value = sustainLevel;
rate = (MY_FLOAT) 0.0;
state = SUSTAIN;
}
}
else if (state==RELEASE) {
value -= releaseRate;
if (value <= 0.0) {
value = (MY_FLOAT) 0.0;
state = 4;
}
}
return value;
}
int ADSR :: informTick()
{
this->tick();
return state;
}
MY_FLOAT ADSR :: lastOut()
{
return value;
}
/************ Test Main ************************/
/*
void main()
{
long i;
ADSR test;
test.setAttackRate(0.15);
test.keyOn();
while(test.informTick()==ATTACK) printf("%lf\n",test.tick());
test.setDecayRate(0.1);
while (test.informTick()==DECAY) printf("%lf\n",test.lastOut());
test.setReleaseRate(0.05);
test.keyOff();
while(test.informTick()==RELEASE) printf("%lf\n",test.lastOut());
}
*/

View File

@@ -1,46 +0,0 @@
/*******************************************/
/* ADSR Subclass of the Envelope Class, */
/* by Perry R. Cook, 1995-96 */
/* This is the traditional ADSR (Attack */
/* Decay, Sustain, Release) envelope. */
/* It responds to simple KeyOn and KeyOff */
/* messages, keeping track of it's state. */
/* There are two tick (update value) */
/* methods, one returns the value, and */
/* other returns the state (0 = A, 1 = D, */
/* 2 = S, 3 = R) */
/*******************************************/
#if !defined(__ADSR_h)
#define __ADSR_h
#include "Envelope.h"
class ADSR : public Envelope
{
protected:
MY_FLOAT attackRate;
MY_FLOAT decayRate;
MY_FLOAT sustainLevel;
MY_FLOAT releaseRate;
public:
ADSR();
~ADSR();
void keyOn();
void keyOff();
void setAttackRate(MY_FLOAT aRate);
void setDecayRate(MY_FLOAT aRate);
void setSustainLevel(MY_FLOAT aLevel);
void setReleaseRate(MY_FLOAT aRate);
void setAttackTime(MY_FLOAT aTime);
void setDecayTime(MY_FLOAT aTime);
void setReleaseTime(MY_FLOAT aTime);
void setAllTimes(MY_FLOAT attTime, MY_FLOAT decTime, MY_FLOAT susLevel, MY_FLOAT relTime);
void setTarget(MY_FLOAT aTarget);
void setValue(MY_FLOAT aValue);
MY_FLOAT tick();
int informTick();
MY_FLOAT lastOut();
};
#endif

View File

@@ -1,79 +0,0 @@
/*******************************************/
/* AgogoBell SubClass of Modal4 Instrument*/
/* by Perry R. Cook, 1995-96 */
/* */
/* Controls: CONTROL1 = stickHardness */
/* CONTROL2 = strikePosition */
/* CONTROL3 = vibFreq */
/* MOD_WHEEL= vibAmt */
/*******************************************/
/* Modes measured from my Agogo Bell by FFT: */
/* 360, 1470, 2401, 4600 */
#include "AgogoBel.h"
#include "SKINI11.msg"
AgogoBel :: AgogoBel() : Modal4()
{
// Concatenate the STK RAWWAVE_PATH to the rawwave file
char file[128];
strcpy(file, RAWWAVE_PATH);
wave = new RawWvIn(strcat(file,"rawwaves/britestk.raw"), "oneshot");
wave->normalize();
wave->setRate((MY_FLOAT) 7.0); // hardstick
this->setRatioAndReson(0, (MY_FLOAT) 1.00,(MY_FLOAT) 0.999); // Set our
this->setRatioAndReson(1, (MY_FLOAT) 4.08,(MY_FLOAT) 0.999); // resonances
this->setRatioAndReson(2,(MY_FLOAT) 6.669,(MY_FLOAT) 0.999); // here
this->setRatioAndReson(3,(MY_FLOAT) -3725.0, (MY_FLOAT)0.999); // (One fixed)
this->setFiltGain(0,(MY_FLOAT) 0.06); // And filter
this->setFiltGain(1,(MY_FLOAT) 0.05); // gains too
this->setFiltGain(2,(MY_FLOAT) 0.03);
this->setFiltGain(3,(MY_FLOAT) 0.02);
directGain = (MY_FLOAT) 0.25;
}
AgogoBel :: ~AgogoBel()
{
delete wave;
}
void AgogoBel :: setStickHardness(MY_FLOAT hardness)
{
stickHardness = hardness; /* To an approximation, */
wave->setRate((MY_FLOAT) 3.0 + ((MY_FLOAT) 8.0 * stickHardness)); /* hardness <-> center */
masterGain = (MY_FLOAT) 1.0; /* freq and amplitude */
}
void AgogoBel :: setStrikePosition(MY_FLOAT position)
{
MY_FLOAT temp,temp2;
temp2 = position * PI;
strikePosition = position; /* Hack only first */
temp = (MY_FLOAT) sin(0.7 * temp2); /* three modes, */
this->setFiltGain(0,(MY_FLOAT) 0.08 * temp); /* leave the other */
temp = (MY_FLOAT) sin(0.1 + (5.0 * temp2)); /* fixed. Why? */
this->setFiltGain(1,(MY_FLOAT) 0.07 * temp); /* So it doesn't */
temp = (MY_FLOAT) sin(0.2 + (7.0 * temp2)); /* sound like a */
this->setFiltGain(2,(MY_FLOAT) 0.04 * temp); /* sample! */
}
void AgogoBel :: controlChange(int number, MY_FLOAT value)
{
#if defined(_debug_)
printf("AgogoBel : ControlChange: Number=%i Value=%f\n",number,value);
#endif
if (number == __SK_StickHardness_)
this->setStickHardness(value * NORM_7);
else if (number == __SK_StrikePosition_)
this->setStrikePosition(value * NORM_7);
else if (number == __SK_ModFrequency_)
vibr->setFreq((value * NORM_7 * (MY_FLOAT) 12.0));
else if (number == __SK_ModWheel_)
vibrGain = (value * NORM_7);
else if (number == __SK_AfterTouch_Cont_)
this->strike(value * NORM_7);
else {
printf("AgogoBel : Undefined Control Number!!\n");
}
}

View File

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

View File

@@ -1,81 +0,0 @@
/******************************************/
/* Hammond(OID) Organ Subclass */
/* of Algorithm 8 (TX81Z) Subclass of */
/* 4 Operator FM Synth */
/* by Perry R. Cook, 1995-96 */
/******************************************/
#include "BeeThree.h"
BeeThree :: BeeThree() : FM4Alg8()
{
// Concatenate the STK RAWWAVE_PATH to the rawwave file
char file1[128];
char file2[128];
char file3[128];
char file4[128];
strcpy(file1, RAWWAVE_PATH);
strcpy(file2, RAWWAVE_PATH);
strcpy(file3, RAWWAVE_PATH);
strcpy(file4, RAWWAVE_PATH);
this->loadWaves(strcat(file1,"rawwaves/sinewave.raw"),
strcat(file2,"rawwaves/sinewave.raw"),
strcat(file3,"rawwaves/sinewave.raw"),
strcat(file4,"rawwaves/fwavblnk.raw"));
this->setRatio(0,(MY_FLOAT) 0.999);
this->setRatio(1,(MY_FLOAT) 1.997);
this->setRatio(2,(MY_FLOAT) 3.006);
this->setRatio(3,(MY_FLOAT) 6.009);
gains[0] = __FM4Op_gains[95];
gains[1] = __FM4Op_gains[95];
gains[2] = __FM4Op_gains[99];
gains[3] = __FM4Op_gains[95];
adsr[0]->setAllTimes((MY_FLOAT) 0.005,(MY_FLOAT) 0.003,(MY_FLOAT) 1.0,(MY_FLOAT) 0.01);
adsr[1]->setAllTimes((MY_FLOAT) 0.005,(MY_FLOAT) 0.003,(MY_FLOAT) 1.0,(MY_FLOAT) 0.01);
adsr[2]->setAllTimes((MY_FLOAT) 0.005,(MY_FLOAT) 0.003,(MY_FLOAT) 1.0,(MY_FLOAT) 0.01);
adsr[3]->setAllTimes((MY_FLOAT) 0.005,(MY_FLOAT) 0.001,(MY_FLOAT) 0.4,(MY_FLOAT) 0.03);
twozero->setGain((MY_FLOAT) 0.1);
}
BeeThree :: ~BeeThree()
{
}
void BeeThree :: setFreq(MY_FLOAT frequency)
{
baseFreq = frequency;
waves[0]->setFreq(baseFreq * ratios[0]);
waves[1]->setFreq(baseFreq * ratios[1]);
waves[2]->setFreq(baseFreq * ratios[2]);
waves[3]->setFreq(baseFreq * ratios[3]);
}
MY_FLOAT BeeThree :: tick()
{
MY_FLOAT temp;
if (modDepth > 0.0) {
temp = (MY_FLOAT) 1.0 + (modDepth * vibWave->tick() * (MY_FLOAT) 0.1);
waves[0]->setFreq(baseFreq * ratios[0] * temp);
waves[1]->setFreq(baseFreq * ratios[1] * temp);
waves[2]->setFreq(baseFreq * ratios[2] * temp);
waves[3]->setFreq(baseFreq * ratios[3] * temp);
}
lastOutput = FM4Alg8 :: tick();
return lastOutput;
}
void BeeThree :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
{
gains[0] = amp * __FM4Op_gains[95];
gains[1] = amp * __FM4Op_gains[95];
gains[2] = amp * __FM4Op_gains[99];
gains[3] = amp * __FM4Op_gains[95];
this->setFreq(freq);
this->keyOn();
#if defined(_debug_)
printf("BeeThree : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
#endif
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,166 +0,0 @@
/******************************************/
/* Bowed String model ala Smith */
/* after McIntyre, Schumacher, Woodhouse */
/* by Perry Cook, 1995-96 */
/* */
/* This is a waveguide model, and thus */
/* relates to various Stanford Univ. */
/* and possibly Yamaha and other patents.*/
/* */
/* Controls: CONTROL1 = bowPressure */
/* CONTROL2 = bowPosition */
/* CONTROL3 = vibrFreq */
/* MOD_WHEEL= vibrGain */
/* */
/******************************************/
#include "Bowed.h"
#include "SKINI11.msg"
Bowed :: Bowed(MY_FLOAT lowestFreq)
{
long length;
length = (long) (SRATE / lowestFreq + 1);
neckDelay = new DLineL(length);
length >>= 1;
bridgeDelay = new DLineL(length);
bowTabl = new BowTabl;
reflFilt = new OnePole;
bodyFilt = new BiQuad;
// Concatenate the STK RAWWAVE_PATH to the rawwave file
char file[128];
strcpy(file, RAWWAVE_PATH);
vibr = new RawWvIn(strcat(file,"rawwaves/sinewave.raw"),"looping");
adsr = new ADSR;
vibrGain = (MY_FLOAT) 0.0;
neckDelay->setDelay((MY_FLOAT) 100.0);
bridgeDelay->setDelay((MY_FLOAT) 29.0);
bowTabl->setSlope((MY_FLOAT) 3.0);
reflFilt->setPole((MY_FLOAT) (0.6 - (0.1 * 22050.0 / SRATE)));
reflFilt->setGain((MY_FLOAT) 0.95);
bodyFilt->setFreqAndReson((MY_FLOAT) 500.0, (MY_FLOAT) 0.85);
bodyFilt->setEqualGainZeroes();
bodyFilt->setGain((MY_FLOAT) 0.2);
vibr->normalize();
vibr->setFreq((MY_FLOAT) 6.12723);
adsr->setAllTimes((MY_FLOAT) 0.02,(MY_FLOAT) 0.005,(MY_FLOAT) 0.9,(MY_FLOAT) 0.01);
betaRatio = (MY_FLOAT) 0.127236;
}
Bowed :: ~Bowed()
{
delete neckDelay;
delete bridgeDelay;
delete bowTabl;
delete reflFilt;
delete bodyFilt;
delete vibr;
delete adsr;
}
void Bowed :: clear()
{
neckDelay->clear();
bridgeDelay->clear();
}
void Bowed :: setFreq(MY_FLOAT frequency)
{
baseDelay = SRATE / frequency - (MY_FLOAT) 4.0; /* delay - approx. filter delay */
bridgeDelay->setDelay(baseDelay * betaRatio); /* bow to bridge length */
neckDelay->setDelay(baseDelay * ((MY_FLOAT) 1.0 - betaRatio)); /* bow to nut (finger) length */
}
void Bowed :: startBowing(MY_FLOAT amplitude, MY_FLOAT rate)
{
adsr->setRate(rate);
adsr->keyOn();
maxVelocity = (MY_FLOAT) 0.03 + ((MY_FLOAT) 0.2 * amplitude);
}
void Bowed :: stopBowing(MY_FLOAT rate)
{
adsr->setRate(rate);
adsr->keyOff();
}
void Bowed :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
{
this->startBowing(amp,amp * (MY_FLOAT) 0.001);
this->setFreq(freq);
#if defined(_debug_)
printf("Bowed : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
#endif
}
void Bowed :: noteOff(MY_FLOAT amp)
{
this->stopBowing(((MY_FLOAT) 1.0 - amp) * (MY_FLOAT) 0.005);
#if defined(_debug_)
printf("Bowed : NoteOff: Amp=%lf\n",amp);
#endif
}
void Bowed :: setVibrato(MY_FLOAT amount)
{
vibrGain = amount;
}
MY_FLOAT Bowed :: tick()
{
MY_FLOAT bowVelocity;
MY_FLOAT bridgeRefl=(MY_FLOAT) 0,nutRefl=(MY_FLOAT) 0;
MY_FLOAT newVel=(MY_FLOAT) 0,velDiff=(MY_FLOAT) 0,stringVel=(MY_FLOAT) 0;
bowVelocity = maxVelocity * adsr->tick();
bridgeRefl = -reflFilt->tick(
bridgeDelay->lastOut()); /* Bridge Reflection */
nutRefl = -neckDelay->lastOut(); /* Nut Reflection */
stringVel = bridgeRefl + nutRefl; /* Sum is String Velocity */
velDiff = bowVelocity - stringVel; /* Differential Velocity */
newVel = velDiff * bowTabl->lookup(velDiff); /* Non-Lin Bow Function */
neckDelay->tick(bridgeRefl + newVel); /* Do string */
bridgeDelay->tick(nutRefl + newVel); /* propagations */
if (vibrGain > 0.0) {
neckDelay->setDelay((baseDelay * ((MY_FLOAT) 1.0 - betaRatio)) +
(baseDelay * vibrGain*vibr->tick()));
}
lastOutput = bodyFilt->tick(bridgeDelay->lastOut());
return lastOutput;
}
void Bowed :: controlChange(int number, MY_FLOAT value)
{
#if defined(_debug_)
printf("Bowed : ControlChange: Number=%i Value=%f\n",number,value);
#endif
if (number == __SK_BowPressure_)
bowTabl->setSlope((MY_FLOAT) 5.0 - ((MY_FLOAT) 4.0 * value * NORM_7));
else if (number == __SK_BowPosition_) {
betaRatio = (MY_FLOAT) 0.027236 + ((MY_FLOAT) 0.2 * value * NORM_7);
bridgeDelay->setDelay(baseDelay * betaRatio); /* bow to bridge length */
neckDelay->setDelay(baseDelay * ((MY_FLOAT) 1.0 - betaRatio)); /* bow to nut (finger) length */
}
else if (number == __SK_ModFrequency_)
vibr->setFreq((value * NORM_7 * (MY_FLOAT) 12.0));
else if (number == __SK_ModWheel_)
vibrGain = (value * NORM_7 * (MY_FLOAT) 0.4);
else if (number == __SK_AfterTouch_Cont_)
adsr->setTarget(value * NORM_7);
else {
printf("Bowed : Undefined Control Number!!\n");
}
}

View File

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

View File

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

View File

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

View File

@@ -1,135 +0,0 @@
/******************************************/
/* Waveguide Brass Instrument Model ala */
/* Cook (TBone, HosePlayer) */
/* by Perry R. Cook, 1995-96 */
/* */
/* This is a waveguide model, and thus */
/* relates to various Stanford Univ. */
/* and possibly Yamaha and other patents.*/
/* */
/* Controls: CONTROL1 = lipTension */
/* CONTROL2 = slideLength */
/* CONTROL3 = vibFreq */
/* MOD_WHEEL= vibAmt */
/******************************************/
#include "Brass.h"
#include "SKINI11.msg"
Brass :: Brass(MY_FLOAT lowestFreq)
{
length = (long) (SRATE / lowestFreq + 1);
delayLine = new DLineA(length);
lipFilter = new LipFilt;
dcBlock = new DCBlock;
adsr = new ADSR;
adsr->setAllTimes((MY_FLOAT) 0.005, (MY_FLOAT) 0.001, (MY_FLOAT) 1.0, (MY_FLOAT) 0.010);
// Concatenate the STK RAWWAVE_PATH to the rawwave file
char file[128];
strcpy(file, RAWWAVE_PATH);
vibr = new RawWvIn(strcat(file,"rawwaves/sinewave.raw"),"looping");
this->clear();
vibr->normalize();
vibr->setFreq((MY_FLOAT) 6.137);
vibrGain = (MY_FLOAT) 0.05; /* breath periodic vibrato component */
maxPressure = (MY_FLOAT) 0.0;
}
Brass :: ~Brass()
{
delete delayLine;
delete lipFilter;
delete dcBlock;
delete adsr;
delete vibr;
}
void Brass :: clear()
{
delayLine->clear();
lipFilter->clear();
dcBlock->clear();
}
void Brass :: setFreq(MY_FLOAT frequency)
{
slideTarget = (SRATE / frequency * (MY_FLOAT) 2.0) + (MY_FLOAT) 3.0;
/* fudge correction for filter delays */
delayLine->setDelay(slideTarget); /* we'll play a harmonic */
lipTarget = frequency;
lipFilter->setFreq(frequency);
}
void Brass :: setLip(MY_FLOAT frequency)
{
lipFilter->setFreq(frequency);
}
void Brass :: startBlowing(MY_FLOAT amplitude,MY_FLOAT rate)
{
adsr->setAttackRate(rate);
maxPressure = amplitude;
adsr->keyOn();
}
void Brass :: stopBlowing(MY_FLOAT rate)
{
adsr->setReleaseRate(rate);
adsr->keyOff();
}
void Brass :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
{
this->setFreq(freq);
this->startBlowing(amp, amp * (MY_FLOAT) 0.001);
#if defined(_debug_)
printf("Brass : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
#endif
}
void Brass :: noteOff(MY_FLOAT amp)
{
this->stopBlowing(amp * (MY_FLOAT) 0.005);
#if defined(_debug_)
printf("Brass : NoteOff: Amp=%lf\n",amp);
#endif
}
MY_FLOAT Brass :: tick()
{
MY_FLOAT breathPressure;
breathPressure = maxPressure * adsr->tick();
breathPressure += vibrGain * vibr->tick();
lastOutput = delayLine->tick( /* bore delay */
dcBlock->tick( /* block DC */
lipFilter->tick((MY_FLOAT) 0.3 * breathPressure, /* mouth input */
(MY_FLOAT) 0.85 * delayLine->lastOut()))); /* and bore reflection */
return lastOutput;
}
void Brass :: controlChange(int number, MY_FLOAT value)
{
MY_FLOAT temp;
#if defined(_debug_)
printf("Brass : ControlChange: Number=%i Value=%f\n",number,value);
#endif
if (number == __SK_LipTension_) {
temp = lipTarget * (MY_FLOAT) pow(4.0,(2.0*value*NORM_7) - 1.0);
this->setLip(temp);
}
else if (number == __SK_SlideLength_)
delayLine->setDelay(slideTarget * ((MY_FLOAT) 0.5 + (value * NORM_7)));
else if (number == __SK_ModFrequency_)
vibr->setFreq((value * NORM_7 * (MY_FLOAT) 12.0));
else if (number == __SK_ModWheel_ )
vibrGain = (value * NORM_7 * (MY_FLOAT) 0.4);
else if (number == __SK_AfterTouch_Cont_)
adsr->setTarget(value * NORM_7);
else {
printf("Brass : Undefined Control Number!!\n");
}
}

View File

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

View File

@@ -1,130 +0,0 @@
/******************************************/
/* Waveguide Clarinet model ala Smith */
/* after McIntyre, Schumacher, Woodhouse */
/* by Perry Cook, 1995-96 */
/* */
/* This is a waveguide model, and thus */
/* relates to various Stanford Univ. */
/* and possibly Yamaha and other patents.*/
/* */
/* Controls: CONTROL1 = reedStiffns */
/* CONTROL2 = noiseGain */
/* CONTROL3 = vibFreq */
/* MOD_WHEEL= vibAmt */
/******************************************/
#include "Clarinet.h"
#include "SKINI11.msg"
Clarinet :: Clarinet(MY_FLOAT lowestFreq)
{
length = (long) (SRATE / lowestFreq + 1);
delayLine = new DLineL(length);
reedTable = new ReedTabl;
reedTable->setOffset((MY_FLOAT) 0.7);
reedTable->setSlope((MY_FLOAT) -0.3);
filter = new OneZero;
envelope = new Envelope;
noise = new Noise;
// Concatenate the STK RAWWAVE_PATH to the rawwave file
char file[128];
strcpy(file, RAWWAVE_PATH);
vibr = new RawWvIn(strcat(file,"rawwaves/sinewave.raw"),"looping");
vibr->normalize();
vibr->setFreq((MY_FLOAT) 5.735);
outputGain = (MY_FLOAT) 1.0;
noiseGain = (MY_FLOAT) 0.2;
vibrGain = (MY_FLOAT) 0.1;
}
Clarinet :: ~Clarinet()
{
delete delayLine;
delete reedTable;
delete filter;
delete envelope;
delete noise;
delete vibr;
}
void Clarinet :: clear()
{
delayLine->clear();
filter->tick((MY_FLOAT) 0.0);
}
void Clarinet :: setFreq(MY_FLOAT frequency)
{
delayLine->setDelay /* length - approx filter delay */
((SRATE / frequency) * (MY_FLOAT) 0.5 - (MY_FLOAT) 1.5);
}
void Clarinet :: startBlowing(MY_FLOAT amplitude,MY_FLOAT rate)
{
envelope->setRate(rate);
envelope->setTarget(amplitude);
}
void Clarinet :: stopBlowing(MY_FLOAT rate)
{
envelope->setRate(rate);
envelope->setTarget((MY_FLOAT) 0.0);
}
void Clarinet :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
{
this->setFreq(freq);
this->startBlowing((MY_FLOAT) 0.55 + (amp * (MY_FLOAT) 0.30),amp * (MY_FLOAT) 0.005);
outputGain = amp + (MY_FLOAT) 0.001;
#if defined(_debug_)
printf("Clarinet : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
#endif
}
void Clarinet :: noteOff(MY_FLOAT amp)
{
this->stopBlowing(amp * (MY_FLOAT) 0.01);
#if defined(_debug_)
printf("Clarinet : NoteOff: Amp=%lf\n",amp);
#endif
}
MY_FLOAT Clarinet :: tick()
{
MY_FLOAT pressureDiff;
MY_FLOAT breathPressure;
breathPressure = envelope->tick();
breathPressure += breathPressure *
noiseGain * noise->tick();
breathPressure += breathPressure *
vibrGain * vibr->tick();
pressureDiff = filter->tick(delayLine->lastOut()); /* differential pressure */
pressureDiff = (pressureDiff * (MY_FLOAT) -0.95) - breathPressure; /* of reflected and mouth */
lastOutput = delayLine->tick(breathPressure + /* perform scattering */
pressureDiff * reedTable->lookup(pressureDiff)); /* in economical way */
lastOutput *= outputGain;
return lastOutput;
}
void Clarinet :: controlChange(int number, MY_FLOAT value)
{
#if defined(_debug_)
printf("Clarinet : ControlChange: Number=%i Value=%f\n",number,value);
#endif
if (number == __SK_ReedStiffness_)
reedTable->setSlope((MY_FLOAT) -0.44 + ((MY_FLOAT) 0.26 * value * NORM_7));
else if (number == __SK_NoiseLevel_)
noiseGain = (value * NORM_7 * (MY_FLOAT) 0.4);
else if (number == __SK_ModFrequency_)
vibr->setFreq((value * NORM_7 * (MY_FLOAT) 12.0));
else if (number == __SK_ModWheel_)
vibrGain = (value * NORM_7 * (MY_FLOAT) 0.5);
else if (number == __SK_AfterTouch_Cont_) {
envelope->setValue(value * NORM_7);
}
else {
printf("Clarinet : Undefined Control Number!!\n");
}
}

View File

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

View File

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

View File

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

View File

@@ -1,107 +0,0 @@
/*******************************************/
/* AllPass Interpolating Delay Line */
/* Object by Perry R. Cook 1995-96. */
/* Revised by Gary P. Scavone, 1999. */
/* */
/* This one uses a delay line of maximum */
/* length specified on creation, and */
/* interpolates fractional length using */
/* an all-pass filter. This version is */
/* more efficient for computing static */
/* length delay lines (alpha and coeff */
/* are computed only when the length */
/* is set, there probably is a more */
/* efficient computational form if alpha */
/* is changed often (each sample)). */
/* */
/*******************************************/
#include "DLineA.h"
DLineA :: DLineA()
{
long i;
// Default max delay length set to 2047.
length = 2048;
inputs = (MY_FLOAT *) malloc(length * sizeof(MY_FLOAT));
for (i=0;i<length;i++) inputs[i] = (MY_FLOAT) 0;
this->clear();
inPoint = 0;
outPoint = length >> 1;
}
DLineA :: DLineA(long max_length)
{
long i;
length = max_length;
inputs = (MY_FLOAT *) malloc(length * sizeof(MY_FLOAT));
for (i=0;i<length;i++) inputs[i] = (MY_FLOAT) 0;
this->clear();
inPoint = 0;
outPoint = length >> 1;
}
DLineA :: ~DLineA()
{
free(inputs);
}
void DLineA :: clear()
{
long i;
for (i=0;i<length;i++) inputs[i] = (MY_FLOAT) 0.0;
lastIn = (MY_FLOAT) 0;
lastOutput = (MY_FLOAT) 0;
}
void DLineA :: setDelay(MY_FLOAT lag)
{
MY_FLOAT outPointer;
if (lag > length-1) { // if delay is too big,
printf("DLineA: Delay length too big.\n");
printf("Setting to maximum length of %ld.\n",length-1);
outPointer = inPoint + 1.0; // force delay to max_length
}
else if (lag < 0.1) {
printf("DLineA: Delays < 0.1 not possible with current structure.\n");
printf("Setting delay length to 0.1.\n");
outPointer = inPoint + 0.8999999999;
}
else
outPointer = inPoint - lag + 1.0; // outPoint chases inpoint
if (outPointer < 0)
outPointer += length; // modulo table length
outPoint = (long) outPointer; // Integer part of delay
alpha = 1.0 + outPoint - outPointer; // fractional part of delay
if (alpha == 0.0) { // exact integer delay
outPoint -= 1;
if (outPoint < 0) outPoint += length;
}
if (alpha<0.1) { // Hack to avoid pole/zero
outPoint += 1; // cancellation. Keeps allpass
if (outPoint >= length) outPoint -= length;
alpha += (MY_FLOAT) 1.0; // delay in range of .1 to 1.1
}
coeff = ((MY_FLOAT) 1.0 - alpha) /
((MY_FLOAT) 1.0 + alpha); // coefficient for all pass
}
MY_FLOAT DLineA :: tick(MY_FLOAT sample) // Take sample, yield sample
{
MY_FLOAT temp;
inputs[inPoint++] = sample; // Write input sample
if (inPoint == length) // Increment input pointer
inPoint -= length; // modulo length
temp = inputs[outPoint++]; // filter input
if (outPoint == length) // Increment output pointer
outPoint -= length; // modulo length
lastOutput = -coeff * lastOutput; // delayed output
lastOutput += lastIn + (coeff * temp); // input + delayed Input
lastIn = temp;
return lastOutput; // save output and return
}

View File

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

View File

@@ -1,77 +0,0 @@
/*******************************************/
/* Linearly Interpolating Delay Line */
/* Object by Perry R. Cook 1995-96 */
/* This one uses a delay line of maximum */
/* length specified on creation, and */
/* linearly interpolates fractional */
/* length. It is designed to be more */
/* efficient if the delay length is not */
/* changed very often. */
/*******************************************/
#include "DLineL.h"
DLineL :: DLineL()
{
// Default max delay length set to 2047.
length = 2048;
inputs = (MY_FLOAT *) malloc(length * sizeof(MY_FLOAT));
this->clear();
inPoint = 0;
outPoint = length >> 1;
}
DLineL :: DLineL(long max_length)
{
length = max_length;
inputs = (MY_FLOAT *) malloc(length * sizeof(MY_FLOAT));
this->clear();
inPoint = 0;
outPoint = length >> 1;
}
DLineL :: ~DLineL()
{
free(inputs);
}
void DLineL :: clear()
{
long i;
for (i=0;i<length;i++) inputs[i] = (MY_FLOAT) 0.0;
lastOutput = (MY_FLOAT) 0;
}
void DLineL :: setDelay(MY_FLOAT lag)
{
MY_FLOAT outPointer;
if (lag > length-1) { // if delay is too big,
printf("DLineL: Delay length too big.\n");
printf("Setting to maximum length of %ld.\n",length-1);
outPointer = inPoint + 1; // force delay to max_length
}
else
outPointer = inPoint - lag; // read chases write
while (outPointer<0)
outPointer += length; // modulo maximum length
outPoint = (long) outPointer; // integer part
alpha = outPointer - outPoint; // fractional part
omAlpha = (MY_FLOAT) 1.0 - alpha; // 1.0 - fractional part (more efficient)
}
MY_FLOAT DLineL :: tick(MY_FLOAT sample) // Take one, yield one
{
inputs[inPoint++] = sample; // Input next sample
if (inPoint == length) // Check for end condition
inPoint -= length;
lastOutput = inputs[outPoint++] * omAlpha; // first 1/2 of interpolation
if (outPoint<length) { // Check for end condition
lastOutput += inputs[outPoint] * alpha; // second 1/2 of interpolation
}
else { // if at end . . .
lastOutput += inputs[0] * alpha; // second 1/2 of interpolation
outPoint -= length;
}
return lastOutput;
}

View File

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

View File

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

View File

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

View File

@@ -1,184 +0,0 @@
/*******************************************/
/* Master Class for Drum Synthesizer */
/* by Perry R. Cook, 1995-96 */
/* */
/* This instrument contains a bunch of */
/* RawWvIn objects, run through a bunch */
/* of one-pole filters. All the */
/* corresponding rawwave files have been */
/* sampled at 22050 Hz. Thus, if the */
/* compile-time SRATE = 22050, then */
/* no interpolation is used. Otherwise, */
/* the rawwave data is appropriately */
/* interpolated for the current SRATE. */
/* You can specify the maximum Polyphony */
/* (maximum number of simultaneous voices)*/
/* in a #define in the .h file. */
/* */
/* Modified for RawWvIn class */
/* by Gary P. Scavone (4/99) */
/*******************************************/
#include "DrumSynt.h"
#include <string.h>
/* Not really General MIDI yet. Coming soon. */
unsigned char genMIDIMap[128] = { 0,0,0,0,0,0,0,0, // 0-7
0,0,0,0,0,0,0,0, // 8-15
0,0,0,0,0,0,0,0, // 16-23
0,0,0,0,0,0,0,0, // 24-31
0,0,0,0,1,0,2,0, // 32-39
2,3,6,3,6,4,7,4, // 40-47
5,8,5,0,0,0,10,0, // 48-55
9,0,0,0,0,0,0,0, // 56-63
0,0,0,0,0,0,0,0, // 64-71
0,0,0,0,0,0,0,0, // 72-79
0,0,0,0,0,0,0,0, // 80-87
0,0,0,0,0,0,0,0, // 88-95
0,0,0,0,0,0,0,0, // 96-103
0,0,0,0,0,0,0,0, // 104-111
0,0,0,0,0,0,0,0, // 112-119
0,0,0,0,0,0,0,0}; // 120-127
char waveNames[DRUM_NUMWAVES][16] = {
"dope.raw",
"bassdrum.raw",
"snardrum.raw",
"tomlowdr.raw",
"tommiddr.raw",
"tomhidrm.raw",
"hihatcym.raw",
"ridecymb.raw",
"crashcym.raw",
"cowbell1.raw",
"tambourn.raw"
};
DrumSynt :: DrumSynt() : Instrmnt()
{
int i;
for (i=0;i<DRUM_POLYPHONY;i++) {
filters[i] = new OnePole;
sounding[i] = -1;
}
/* This counts the number of sounding voices */
numSounding = 0;
/* Print warning about aliasing if SRATE < 22050 */
if (SRATE < 22050) {
printf("\nWarning: DrumSynt is designed for sampling rates of\n");
printf("22050 Hz or greater. You will likely encounter aliasing\n");
printf("at the current sampling rate of %.0f Hz.\n\n", SRATE);
}
}
DrumSynt :: ~DrumSynt()
{
int i;
for ( i=0; i<numSounding-1; i++ ) delete waves[i];
for ( i=0; i<DRUM_POLYPHONY; i++ ) delete filters[i];
}
void DrumSynt :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
{
int i, notDone;
int noteNum;
int vel;
char tempString[64];
RawWvIn *tempWv;
OnePole *tempFilt;
/* Yes I know, this is tres kludgey */
noteNum = (int) ((12*log(freq/220)/log(2)) + 57.01);
vel = (int) (amp * 127);
#if defined(_debug_)
printf("NoteOn: %s vel=%i\n",waveNames[genMIDIMap[noteNum]],vel);
#endif
notDone = -1;
for (i=0;i<DRUM_POLYPHONY;i++) { /* Check first to see */
if (sounding[i] == noteNum) notDone = i; /* if there's already */
} /* one like this sounding */
if (notDone<0) { /* If not, then */
if (numSounding == DRUM_POLYPHONY) { /* If we're already */
delete waves[0]; /* at max polyphony, */
filters[0]->clear(); /* then */
tempWv = waves[0];
tempFilt = filters[0];
for (i=0;i<DRUM_POLYPHONY-1;i++) { /* preempt oldest */
waves[i] = waves[i+1]; /* voice and */
filters[i] = filters[i+1]; /* ripple all down */
}
waves[DRUM_POLYPHONY-1] = tempWv;
filters[DRUM_POLYPHONY-1] = tempFilt;
} else {
numSounding += 1; /* otherwise just add one */
}
sounding[numSounding-1] = noteNum; /* allocate new wave */
// Concatenate the STK RAWWAVE_PATH to the rawwave file
strcpy(tempString, RAWWAVE_PATH);
strcat(tempString,"rawwaves/");
strcat(tempString,waveNames[genMIDIMap[noteNum]]);
waves[numSounding-1] = new RawWvIn(tempString, "oneshot");
if (SRATE != 22050) {
waves[numSounding-1]->setRate((MY_FLOAT) (22050.0/SRATE));
}
waves[numSounding-1]->normalize((MY_FLOAT) 0.4);
filters[numSounding-1]->setPole((MY_FLOAT) 0.999 - ((MY_FLOAT) vel * NORM_7 * 0.6));
filters[numSounding-1]->setGain(vel / (MY_FLOAT) 128.0);
}
else {
waves[notDone]->reset();
filters[notDone]->setPole((MY_FLOAT) 0.999 - ((MY_FLOAT) vel * NORM_7 * 0.6));
filters[notDone]->setGain(vel / (MY_FLOAT) 128.0);
}
#if defined(_debug_)
printf("Number Sounding = %i\n",numSounding);
for (i=0;i<numSounding;i++) printf(" %i ",sounding[i]);
printf("\n");
#endif
}
void DrumSynt :: noteOff(MY_FLOAT amp)
{ /* Set all sounding wave filter gains low */
int i = 0;
while(i<numSounding) {
filters[i]->setGain(amp*0.01);
i++;
}
}
MY_FLOAT DrumSynt :: tick()
{
int j, i = 0;
MY_FLOAT output = 0.0;
OnePole *tempFilt;
while (i < numSounding) {
output += filters[i]->tick(waves[i]->lastOut());
if (waves[i]->informTick() == 1) {
delete waves[i];
tempFilt = filters[i];
for (j=i;j<numSounding-1;j++) {
sounding[j] = sounding[j+1];
waves[j] = waves[j+1];
filters[j] = filters[j+1];
}
filters[j] = tempFilt;
filters[j]->clear();
sounding[j] = -1;
numSounding -= 1;
i -= 1;
}
i++;
}
return output;
}

View File

@@ -1,47 +0,0 @@
/*******************************************/
/* Master Class for Drum Synthesizer */
/* by Perry R. Cook, 1995-96 */
/* */
/* This instrument contains a bunch of */
/* RawWvIn objects, run through a bunch */
/* of one-pole filters. All the */
/* corresponding rawwave files have been */
/* sampled at 22050 Hz. Thus, if the */
/* compile-time SRATE = 22050, then */
/* no interpolation is used. Otherwise, */
/* the rawwave data is appropriately */
/* interpolated for the current SRATE. */
/* You can specify the maximum Polyphony */
/* (maximum number of simultaneous voices)*/
/* in a #define in the .h file. */
/* */
/* Modified for RawWvIn class */
/* by Gary P. Scavone (4/99) */
/*******************************************/
#if !defined(__DrumSynt_h)
#define __DrumSynt_h
#include "Instrmnt.h"
#include "RawWvIn.h"
#include "OnePole.h"
#define DRUM_NUMWAVES 11
#define DRUM_POLYPHONY 4
class DrumSynt : public Instrmnt
{
protected:
RawWvIn *waves[DRUM_POLYPHONY];
OnePole *filters[DRUM_POLYPHONY];
int sounding[DRUM_POLYPHONY];
int numSounding;
public:
DrumSynt();
~DrumSynt();
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
void noteOff(MY_FLOAT amp);
virtual MY_FLOAT tick();
};
#endif

View File

@@ -1,122 +0,0 @@
/*******************************************/
/* Envelope Class, Perry R. Cook, 1995-96 */
/* */
/* This is the base class for envelopes. */
/* This one is capable of ramping state */
/* from where it is to a target value by */
/* a rate. It also responds to simple */
/* KeyOn and KeyOff messages, ramping to */
/* 1.0 on keyon and to 0.0 on keyoff. */
/* There are two tick (update value) */
/* methods, one returns the value, and */
/* other returns 0 if the envelope is at */
/* the target value (the state bit). */
/*******************************************/
#include "Envelope.h"
Envelope :: Envelope() : Object()
{
target = (MY_FLOAT) 0.0;
value = (MY_FLOAT) 0.0;
rate = (MY_FLOAT) 0.001;
state = 0;
}
Envelope :: ~Envelope()
{
}
void Envelope :: keyOn()
{
target = (MY_FLOAT) 1.0;
if (value != target) state = 1;
}
void Envelope :: keyOff()
{
target = (MY_FLOAT) 0.0;
if (value != target) state = 1;
}
void Envelope :: setRate(MY_FLOAT aRate)
{
if (aRate < 0.0) {
printf("negative rates not allowed!!, correcting\n");
rate = -aRate;
}
else rate = aRate;
}
void Envelope :: setTime(MY_FLOAT aTime)
{
if (aTime < 0.0) {
printf("negative times not allowed!!, correcting\n");
rate = ONE_OVER_SRATE / -aTime ;
}
else rate = ONE_OVER_SRATE / aTime ;
}
void Envelope :: setTarget(MY_FLOAT aTarget)
{
target = aTarget;
if (value != target) state = 1;
}
void Envelope :: setValue(MY_FLOAT aValue)
{
state = 0;
target = aValue;
value = aValue;
}
MY_FLOAT Envelope :: tick()
{
if (state) {
if (target > value) {
value += rate;
if (value >= target) {
value = target;
state = 0;
}
}
else {
value -= rate;
if (value <= target) {
value = target;
state = 0;
}
}
}
return value;
}
int Envelope :: informTick()
{
this->tick();
return state;
}
MY_FLOAT Envelope :: lastOut()
{
return value;
}
/************ Test Main ************************/
/*
void main()
{
long i;
Envelope test;
test.setRate(0.15);
test.keyOn();
for (i=0;i<10;i++) printf("%lf\n",test.tick());
test.setRate(0.1);
test.setTarget(0.5);
while (test.informTick()) printf("%lf\n",test.lastOut());
test.setRate(0.05);
test.keyOff();
while(test.informTick()) printf("%lf\n",test.lastOut());
}
*/

View File

@@ -1,41 +0,0 @@
/*******************************************/
/* Envelope Class, Perry R. Cook, 1995-96 */
/* This is the base class for envelopes. */
/* This one is capable of ramping state */
/* from where it is to a target value by */
/* a rate. It also responds to simple */
/* KeyOn and KeyOff messages, ramping to */
/* 1.0 on keyon and to 0.0 on keyoff. */
/* There are two tick (update value) */
/* methods, one returns the value, and */
/* other returns 0 if the envelope is at */
/* the target value (the state bit). */
/*******************************************/
#if !defined(__Envelope_h)
#define __Envelope_h
#include "Object.h"
class Envelope : public Object
{
protected:
MY_FLOAT value;
MY_FLOAT target;
MY_FLOAT rate;
int state;
public:
Envelope();
virtual ~Envelope();
void keyOn();
void keyOff();
void setRate(MY_FLOAT aRate);
void setTime(MY_FLOAT aTime);
void setTarget(MY_FLOAT aTarget);
void setValue(MY_FLOAT aValue);
MY_FLOAT tick();
int informTick();
MY_FLOAT lastOut();
};
#endif

View File

@@ -1,56 +0,0 @@
/******************************************/
/* Algorithm 3 (TX81Z) Subclass of */
/* 4 Operator FM Synth */
/* by Perry R. Cook, 1995-96 */
/* */
/* Alg 3 is : 4--\ */
/* 3-->2-- + -->1-->Out */
/* */
/* Controls: control1 = total mod index */
/* control2 = crossfade of two */
/* modulators */
/* control3 = LFO speed */
/* modWheel = LFO amount */
/* */
/******************************************/
#include "FM4Alg3.h"
FM4Alg3 :: FM4Alg3() : FM4Op()
{
/* We still don't make the waves here yet, because */
/* we still don't know what they will be. */
}
FM4Alg3 :: ~FM4Alg3()
{
}
MY_FLOAT FM4Alg3 :: tick()
{
MY_FLOAT temp;
temp = vibWave->tick() * modDepth * (MY_FLOAT) 0.2;
waves[0]->setFreq(baseFreq * ((MY_FLOAT) 1.0 + temp) * ratios[0]);
waves[1]->setFreq(baseFreq * ((MY_FLOAT) 1.0 + temp) * ratios[1]);
waves[2]->setFreq(baseFreq * ((MY_FLOAT) 1.0 + temp) * ratios[2]);
waves[3]->setFreq(baseFreq * ((MY_FLOAT) 1.0 + temp) * ratios[3]);
temp = gains[2] * adsr[2]->tick() * waves[2]->tick();
waves[1]->addPhaseOffset(temp);
waves[3]->addPhaseOffset(twozero->lastOut());
temp = ((MY_FLOAT) 1.0 - (control2 * (MY_FLOAT) 0.5)) *
gains[3] * adsr[3]->tick() * waves[3]->tick();
twozero->tick(temp);
temp += control2 * (MY_FLOAT) 0.5 * gains[1] * adsr[1]->tick() * waves[1]->tick();
temp = temp * control1;
waves[0]->addPhaseOffset(temp);
temp = gains[0] * adsr[0]->tick() * waves[0]->tick();
lastOutput = temp * (MY_FLOAT) 0.5;
return lastOutput;
}

View File

@@ -1,30 +0,0 @@
/******************************************/
/* Algorithm 3 (TX81Z) Subclass of */
/* 4 Operator FM Synth */
/* by Perry R. Cook, 1995-96 */
/* */
/* Alg 3 is : 4--\ */
/* 3-->2-- + -->1-->Out */
/* */
/* Controls: control1 = total mod index */
/* control2 = crossfade of two */
/* modulators */
/* control3 = LFO speed */
/* modWheel = LFO amount */
/* */
/******************************************/
#if !defined(__FM4Alg3_h)
#define __FM4Alg3_h
#include "FM4Op.h"
class FM4Alg3 : public FM4Op
{
public:
FM4Alg3();
virtual ~FM4Alg3();
MY_FLOAT tick();
};
#endif

View File

@@ -1,53 +0,0 @@
/******************************************/
/* Algorithm 4 (TX81Z) Subclass of */
/* 4 Operator FM Synth */
/* by Perry R. Cook, 1995-96 */
/* */
/* Alg 4 is : 4->3--\ */
/* 2-- + -->1-->Out */
/* */
/* Controls: control1 = total mod index */
/* control2 = crossfade of two */
/* modulators */
/* control3 = LFO speed */
/* modWheel = LFO amount */
/* */
/******************************************/
#include "FM4Alg4.h"
FM4Alg4 :: FM4Alg4() : FM4Op()
{
/* We still don't make the waves here yet, because */
/* we still don't know what they will be. */
}
FM4Alg4 :: ~FM4Alg4()
{
}
MY_FLOAT FM4Alg4 :: tick()
{
MY_FLOAT temp;
temp = vibWave->tick() * modDepth * (MY_FLOAT) 0.2;
waves[0]->setFreq(baseFreq * ((MY_FLOAT) 1.0 + temp) * ratios[0]);
waves[1]->setFreq(baseFreq * ((MY_FLOAT) 1.0 + temp) * ratios[1]);
waves[2]->setFreq(baseFreq * ((MY_FLOAT) 1.0 + temp) * ratios[2]);
waves[3]->setFreq(baseFreq * ((MY_FLOAT) 1.0 + temp) * ratios[3]);
waves[3]->addPhaseOffset(twozero->lastOut());
temp = gains[3] * adsr[3]->tick() * waves[3]->tick();
twozero->tick(temp);
waves[2]->addPhaseOffset(temp);
temp = ((MY_FLOAT) 1.0 - (control2 * (MY_FLOAT) 0.5)) *
gains[2] * adsr[2]->tick() * waves[2]->tick();
temp += control2 * (MY_FLOAT) 0.5 * gains[1] * adsr[1]->tick() * waves[1]->tick();
temp = temp * control1;
waves[0]->addPhaseOffset(temp);
temp = gains[0] * adsr[0]->tick() * waves[0]->tick();
lastOutput = temp * (MY_FLOAT) 0.5;
return lastOutput;
}

View File

@@ -1,30 +0,0 @@
/******************************************/
/* Algorithm 4 (TX81Z) Subclass of */
/* 4 Operator FM Synth */
/* by Perry R. Cook, 1995-96 */
/* */
/* Alg 4 is : 4->3--\ */
/* 2-- + -->1-->Out */
/* */
/* Controls: control1 = total mod index */
/* control2 = crossfade of two */
/* modulators */
/* control3 = LFO speed */
/* modWheel = LFO amount */
/* */
/******************************************/
#if !defined(__FM4Alg4_h)
#define __FM4Alg4_h
#include "FM4Op.h"
class FM4Alg4 : public FM4Op
{
public:
FM4Alg4();
virtual ~FM4Alg4();
MY_FLOAT tick();
};
#endif

View File

@@ -1,53 +0,0 @@
/******************************************/
/* Algorithm 5 (TX81Z) Subclass of */
/* 4 Operator FM Synth */
/* by Perry R. Cook, 1995-96 */
/* This connection topology is 2 simple */
/* FM Pairs summed together, like: */
/* */
/* Alg 5 is : 4->3--\ */
/* + --> Out */
/* 2->1--/ */
/* */
/* Controls: control1 = mod index 1 */
/* control2 = crossfade of two */
/* outputs */
/* control3 = LFO speed */
/* modWheel = LFO amount */
/* */
/******************************************/
#include "FM4Alg5.h"
FM4Alg5 :: FM4Alg5() : FM4Op()
{
/* We still don't make the waves here yet, because */
/* we still don't know what they will be. */
}
FM4Alg5 :: ~FM4Alg5()
{
}
MY_FLOAT FM4Alg5 :: tick()
{
MY_FLOAT temp,temp2;
temp = gains[1] * adsr[1]->tick() * waves[1]->tick();
temp = temp * control1;
waves[0]->addPhaseOffset(temp);
waves[3]->addPhaseOffset(twozero->lastOut());
temp = gains[3] * adsr[3]->tick() * waves[3]->tick();
twozero->tick(temp);
waves[2]->addPhaseOffset(temp);
temp = ((MY_FLOAT) 1.0 - (control2 * (MY_FLOAT) 0.5)) *
gains[0] * adsr[0]->tick() * waves[0]->tick();
temp += control2 * (MY_FLOAT) 0.5 * gains[2] * adsr[2]->tick() * waves[2]->tick();
temp2 = vibWave->tick() * modDepth; /* Calculate amplitude mod */
temp = temp * ((MY_FLOAT) 1.0 + temp2); /* and apply it to output */
lastOutput = temp * (MY_FLOAT) 0.5;
return lastOutput;
}

View File

@@ -1,33 +0,0 @@
/******************************************/
/* Algorithm 5 (TX81Z) Subclass of */
/* 4 Operator FM Synth */
/* by Perry R. Cook, 1995-96 */
/* This connection topology is 2 simple */
/* FM Pairs summed together, like: */
/* */
/* 1 -> 2 -\ */
/* +-> Out */
/* 3 -> 4 -/ */
/* */
/* Controls: control1 = mod index 1 */
/* control2 = crossfade of two */
/* outputs */
/* control3 = LFO speed */
/* modWheel = LFO amount */
/* */
/******************************************/
#if !defined(__FM4Alg5_h)
#define __FM4Alg5_h
#include "FM4Op.h"
class FM4Alg5 : public FM4Op
{
public:
FM4Alg5();
virtual ~FM4Alg5();
MY_FLOAT tick();
};
#endif

View File

@@ -1,58 +0,0 @@
/******************************************/
/* Algorithm 6 (TX81Z) Subclass of */
/* 4 Operator FM Synth */
/* by Perry R. Cook, 1995-96 */
/* This connection topology is three */
/* Carriers and a common Modulator */
/* */
/* /->1 -\ */
/* 4-|-->2 - +-> Out */
/* \->3 -/ */
/* */
/* Controls: control1 = vowel */
/* control2 = spectral tilt */
/* control3 = LFO speed */
/* modWheel = LFO amount */
/* */
/******************************************/
#include "FM4Alg6.h"
FM4Alg6 :: FM4Alg6() : FM4Op()
{
/* We still don't make the waves here yet, because */
/* we still don't know what they will be. */
}
FM4Alg6 :: ~FM4Alg6()
{
}
MY_FLOAT FM4Alg6 :: tick()
{
MY_FLOAT temp,temp2;
temp = gains[3] * adsr[3]->tick() * waves[3]->tick();
temp2 = vibWave->tick() * modDepth * (MY_FLOAT) 0.1; /* Calculate frequency mod */
waves[0]->setFreq(baseFreq * ((MY_FLOAT) 1.0 + temp2) * ratios[0]);
waves[1]->setFreq(baseFreq * ((MY_FLOAT) 1.0 + temp2) * ratios[1]);
waves[2]->setFreq(baseFreq * ((MY_FLOAT) 1.0 + temp2) * ratios[2]);
waves[3]->setFreq(baseFreq * ((MY_FLOAT) 1.0 + temp2) * ratios[3]);
waves[0]->addPhaseOffset(temp * mods[0]);
waves[1]->addPhaseOffset(temp * mods[1]);
waves[2]->addPhaseOffset(temp * mods[2]);
waves[3]->addPhaseOffset(twozero->lastOut());
twozero->tick(temp);
temp = gains[0] * tilt[0] * adsr[0]->tick() * waves[0]->tick();
temp += gains[1] * tilt[1] * adsr[1]->tick() * waves[1]->tick();
temp += gains[2] * tilt[2] * adsr[2]->tick() * waves[2]->tick();
return temp * (MY_FLOAT) 0.33;
}
void FM4Alg6 :: controlChange(int number, MY_FLOAT value)
{
}

View File

@@ -1,36 +0,0 @@
/******************************************/
/* Algorithm 6 (TX81Z) Subclass of */
/* 4 Operator FM Synth */
/* by Perry R. Cook, 1995-96 */
/* This connection topology is three */
/* Carriers and a common Modulator */
/* */
/* /->1 -\ */
/* 4-|-->2 - +-> Out */
/* \->3 -/ */
/* */
/* Controls: control1 = vowel */
/* control2 = spectral tilt */
/* control3 = LFO speed */
/* modWheel = LFO amount */
/* */
/******************************************/
#if !defined(__FM4Alg6_h)
#define __FM4Alg6_h
#include "FM4Op.h"
class FM4Alg6 : public FM4Op
{
protected:
MY_FLOAT tilt[3];
MY_FLOAT mods[3];
public:
FM4Alg6();
virtual ~FM4Alg6();
MY_FLOAT tick();
virtual void controlChange(int number, MY_FLOAT value);
};
#endif

View File

@@ -1,47 +0,0 @@
/******************************************/
/* Algorithm 8 (TX81Z) Subclass of */
/* 4 Operator FM Synth */
/* by Perry R. Cook, 1995-96 */
/* This connection topology is simple */
/* Additive Synthesis, like: */
/* */
/* 1 --. */
/* 2 -\| */
/* +-> Out */
/* 3 -/| */
/* 4 -- */
/* */
/* Controls: control1 = op4 (fb) gain */
/* control2 = op3 gain */
/* control3 = LFO speed */
/* modWheel = LFO amount */
/* */
/******************************************/
#include "FM4Alg8.h"
FM4Alg8 :: FM4Alg8() : FM4Op()
{
/* We still don't make the waves here yet, because */
/* we still don't know what they will be. */
}
FM4Alg8 :: ~FM4Alg8()
{
}
MY_FLOAT FM4Alg8 :: tick()
{
MY_FLOAT temp;
waves[3]->addPhaseOffset(twozero->lastOut());
temp = control1 * (MY_FLOAT) 2.0 * gains[3] * adsr[3]->tick() * waves[3]->tick();
twozero->tick(temp);
temp += control2 * (MY_FLOAT) 2.0 * gains[2] * adsr[2]->tick() * waves[2]->tick();
temp += gains[1] * adsr[1]->tick() * waves[1]->tick();
temp += gains[0] * adsr[0]->tick() * waves[0]->tick();
lastOutput = temp * (MY_FLOAT) 0.125;
return lastOutput;
}

View File

@@ -1,34 +0,0 @@
/******************************************/
/* Algorithm 8 (TX81Z) Subclass of */
/* 4 Operator FM Synth */
/* by Perry R. Cook, 1995-96 */
/* This connection topology is simple */
/* Additive Synthesis, like: */
/* */
/* 1 --. */
/* 2 -\| */
/* +-> Out */
/* 3 -/| */
/* 4 -- */
/* */
/* Controls: control1 = op4 (fb) gain */
/* control2 = op3 gain */
/* control3 = LFO speed */
/* modWheel = LFO amount */
/* */
/******************************************/
#if !defined(__FM4Alg8_h)
#define __FM4Alg8_h
#include "FM4Op.h"
class FM4Alg8 : public FM4Op
{
public:
FM4Alg8();
virtual ~FM4Alg8();
virtual MY_FLOAT tick();
};
#endif

View File

@@ -1,184 +0,0 @@
/*******************************************/
/* Master Class for 4 Operator FM Synth */
/* by Perry R. Cook, 1995-96 */
/* This instrument contains 4 waves, */
/* 4 adsr, and various state vars. */
/* */
/* The basic Chowning/Stanford FM patent */
/* expired April 1995, but there exist */
/* follow-on patents, mostly assigned to */
/* Yamaha. If you are of the type who */
/* should worry about this (making money) */
/* worry away. */
/* */
/*******************************************/
#include "FM4Op.h"
#include "SKINI11.msg"
FM4Op :: FM4Op()
{
int i;
MY_FLOAT temp;
MY_FLOAT tempCoeffs[2] = {(MY_FLOAT) 0.0, (MY_FLOAT) -1.0};
adsr[0] = new ADSR;
adsr[1] = new ADSR;
adsr[2] = new ADSR;
adsr[3] = new ADSR;
twozero = new TwoZero;
// Concatenate the STK RAWWAVE_PATH to the rawwave file
char file[128];
strcpy(file, RAWWAVE_PATH);
vibWave = new RawWvIn(strcat(file,"rawwaves/sinewave.raw"),"looping");
vibWave->normalize();
vibWave->setFreq((MY_FLOAT) 6.0); /* should make this random?? */
modDepth = (MY_FLOAT) 0.0;
/* We don't make the waves here yet, because */
/* we don't know what they will be. */
baseFreq = (MY_FLOAT) 440.0;
ratios[0] = (MY_FLOAT) 1.0;
ratios[1] = (MY_FLOAT) 1.0;
ratios[2] = (MY_FLOAT) 1.0;
ratios[3] = (MY_FLOAT) 1.0;
gains[0] = (MY_FLOAT) 1.0;
gains[1] = (MY_FLOAT) 1.0;
gains[2] = (MY_FLOAT) 1.0;
gains[3] = (MY_FLOAT) 1.0;
twozero->setZeroCoeffs(tempCoeffs);
twozero->setGain((MY_FLOAT) 0.0);
control1 = (MY_FLOAT) 1.0;
control2 = (MY_FLOAT) 1.0;
temp = (MY_FLOAT) 1.0;
for (i=99;i>=0;i--) {
__FM4Op_gains[i] = temp;
temp *= (MY_FLOAT) 0.933033;
}
temp = (MY_FLOAT) 1.0;
for (i=15;i>=0;i--) {
__FM4Op_susLevels[i] = temp;
temp *= (MY_FLOAT) 0.707101;
}
temp = (MY_FLOAT) 8.498186;
for (i=0;i<32;i++) {
__FM4Op_attTimes[i] = temp;
temp *= (MY_FLOAT) 0.707101;
}
}
FM4Op :: ~FM4Op()
{
delete adsr[0];
delete adsr[1];
delete adsr[2];
delete adsr[3];
delete waves[0];
delete waves[1];
delete waves[2];
delete waves[3];
delete vibWave;
delete twozero;
}
void FM4Op :: loadWaves(char* wave1, char* wave2, char* wave3, char* wave4)
{
int i;
waves[0] = new RawWvIn(wave1,"looping");
waves[1] = new RawWvIn(wave2,"looping");
waves[2] = new RawWvIn(wave3,"looping");
waves[3] = new RawWvIn(wave4,"looping");
for (i=0;i<4;i++) {
waves[i]->normalize();
}
}
void FM4Op :: setFreq(MY_FLOAT frequency)
{
baseFreq = frequency;
waves[0]->setFreq(baseFreq * ratios[0]);
waves[1]->setFreq(baseFreq * ratios[1]);
waves[2]->setFreq(baseFreq * ratios[2]);
waves[3]->setFreq(baseFreq * ratios[3]);
}
void FM4Op :: setRatio(int whichOne, MY_FLOAT ratio)
{
ratios[whichOne] = ratio;
if (ratio>0.0)
waves[whichOne]->setFreq(baseFreq * ratio);
else
waves[whichOne]->setFreq(ratio);
}
void FM4Op :: setGain(int whichOne, MY_FLOAT gain)
{
gains[whichOne]=gain;
}
void FM4Op :: keyOn()
{
adsr[0]->keyOn();
adsr[1]->keyOn();
adsr[2]->keyOn();
adsr[3]->keyOn();
}
void FM4Op :: keyOff()
{
adsr[0]->keyOff();
adsr[1]->keyOff();
adsr[2]->keyOff();
adsr[3]->keyOff();
}
void FM4Op :: noteOff(MY_FLOAT amp)
{
this->keyOff();
#if defined(_debug_)
printf("FM4Op : NoteOff: Amp=%lf\n",amp);
#endif
}
void FM4Op :: setModulationSpeed(MY_FLOAT mSpeed)
{
vibWave->setFreq(mSpeed);
}
void FM4Op :: setModulationDepth(MY_FLOAT mDepth)
{
modDepth = mDepth;
}
void FM4Op :: setControl1(MY_FLOAT cVal)
{
control1 = cVal * (MY_FLOAT) 2.0;
}
void FM4Op :: setControl2(MY_FLOAT cVal)
{
control2 = cVal * (MY_FLOAT) 2.0;
}
void FM4Op :: controlChange(int number, MY_FLOAT value)
{
#if defined(_debug_)
printf("FM4Op : ControlChange: Number=%i Value=%f\n",number,value);
#endif
if (number == __SK_Breath_) /* Control Change 2 */
this->setControl1(value * NORM_7);
else if (number == __SK_FootControl_) /* Control Change 4 */
this->setControl2(value * NORM_7);
else if (number == __SK_ModFrequency_) /* Control Change 11 */
this->setModulationSpeed(value * NORM_7 * (MY_FLOAT) 12.0); /* 0 to 12 Hz */
else if (number == __SK_ModWheel_) /* Control Change 1 */
this->setModulationDepth(value * NORM_7);
else if (number == __SK_AfterTouch_Cont_) {
//adsr[0]->setTarget(value * NORM_7);
adsr[1]->setTarget(value * NORM_7);
//adsr[2]->setTarget(value * NORM_7);
adsr[3]->setTarget(value * NORM_7);
}
else {
printf("FM4Op : Undefined Control Number!!\n");
}
}

View File

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

View File

@@ -1,136 +0,0 @@
/******************************************/
/* Singing Voice Synthesis Subclass */
/* of Algorithm 6 (TX81Z) Subclass of */
/* 4 Operator FM Synth */
/* by Perry R. Cook, 1996 */
/******************************************/
#include "FMVoices.h"
#include "SKINI11.msg"
FMVoices :: FMVoices() : FM4Alg6()
{
// Concatenate the STK RAWWAVE_PATH to the rawwave file
char file1[128];
char file2[128];
char file3[128];
char file4[128];
strcpy(file1, RAWWAVE_PATH);
strcpy(file2, RAWWAVE_PATH);
strcpy(file3, RAWWAVE_PATH);
strcpy(file4, RAWWAVE_PATH);
this->loadWaves(strcat(file1,"rawwaves/sinewave.raw"),
strcat(file2,"rawwaves/sinewave.raw"),
strcat(file3,"rawwaves/sinewave.raw"),
strcat(file4,"rawwaves/fwavblnk.raw"));
this->setRatio(0,(MY_FLOAT) 2.00);
this->setRatio(1,(MY_FLOAT) 4.00);
this->setRatio(2,(MY_FLOAT) 12.0);
this->setRatio(3,(MY_FLOAT) 1.00);
gains[3] = __FM4Op_gains[80];
adsr[0]->setAllTimes((MY_FLOAT) 0.050,(MY_FLOAT) 0.050,
__FM4Op_susLevels[15],(MY_FLOAT) 0.050);
adsr[1]->setAllTimes((MY_FLOAT) 0.050,(MY_FLOAT) 0.050,
__FM4Op_susLevels[15],(MY_FLOAT) 0.050);
adsr[2]->setAllTimes((MY_FLOAT) 0.050,(MY_FLOAT) 0.050,
__FM4Op_susLevels[15],(MY_FLOAT) 0.050);
adsr[3]->setAllTimes((MY_FLOAT) 0.010,(MY_FLOAT) 0.010,
__FM4Op_susLevels[15],(MY_FLOAT) 0.500);
twozero->setGain((MY_FLOAT) 0.0);
modDepth = (MY_FLOAT) 0.005;
currentVowel = 0;
tilt[0] = (MY_FLOAT) 1.0;
tilt[1] = (MY_FLOAT) 0.5;
tilt[2] = (MY_FLOAT) 0.2;
mods[0] = (MY_FLOAT) 1.0;
mods[1] = (MY_FLOAT) 1.1;
mods[2] = (MY_FLOAT) 1.1;
baseFreq = (MY_FLOAT) 110.0;
this->setFreq((MY_FLOAT) 110.0);
}
/* #include "phonTabl.h" */
extern double phonGains[32][2];
extern double phonParams[32][4][3];
extern char phonemes[32][4];
void FMVoices :: setFreq(MY_FLOAT frequency)
{
MY_FLOAT temp, temp2 = 0.0;
int tempi, tempi2 = 0;
if (currentVowel < 32) {
tempi2 = currentVowel;
temp2 = (MY_FLOAT) 0.9;
}
else if (currentVowel < 64) {
tempi2 = currentVowel - 32;
temp2 = (MY_FLOAT) 1.0;
}
else if (currentVowel < 96) {
tempi2 = currentVowel - 64;
temp2 = (MY_FLOAT) 1.1;
}
else if (currentVowel <= 128) {
tempi2 = currentVowel - 96;
temp2 = (MY_FLOAT) 1.2;
}
baseFreq = frequency;
temp = (temp2 * (MY_FLOAT) phonParams[tempi2][0][0] / baseFreq) + (MY_FLOAT) 0.5;
tempi = (int) temp;
this->setRatio(0,(MY_FLOAT) tempi);
temp = (temp2 * (MY_FLOAT) phonParams[tempi2][1][0] / baseFreq) + (MY_FLOAT) 0.5;
tempi = (int) temp;
this->setRatio(1,(MY_FLOAT) tempi);
temp = (temp2 * (MY_FLOAT) phonParams[tempi2][2][0] / baseFreq) + (MY_FLOAT) 0.5;
tempi = (int) temp;
this->setRatio(2,(MY_FLOAT) tempi);
gains[0] = (MY_FLOAT) 1.0; // pow(10.0,phonParams[tempi2][0][2] * 0.05);
gains[1] = (MY_FLOAT) 1.0; // pow(10.0,phonParams[tempi2][1][2] * 0.05);
gains[2] = (MY_FLOAT) 1.0; // pow(10.0,phonParams[tempi2][2][2] * 0.05);
}
void FMVoices :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
{
this->setFreq(freq);
tilt[0] = amp;
tilt[1] = amp * amp;
tilt[2] = amp * amp * amp;
this->keyOn();
#if defined(_debug_)
printf("FMVoices : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
#endif
}
void FMVoices :: controlChange(int number, MY_FLOAT value)
{
MY_FLOAT temp;
int tempi;
#if defined(_debug_)
printf("FM4Op : ControlChange: Number=%i Value=%f\n",number,value);
#endif
if (number == __SK_Breath_)
gains[3] = __FM4Op_gains[(int) (value * 0.78125)];
else if (number == __SK_FootControl_) {
tempi = (int) value;
currentVowel = tempi;
this->setFreq(baseFreq);
}
else if (number == __SK_ModFrequency_)
this->setModulationSpeed(value * NORM_7 * (MY_FLOAT) 12.0); /* 0 to 12 Hz */
else if (number == __SK_ModWheel_)
this->setModulationDepth(value * NORM_7);
else if (number == __SK_AfterTouch_Cont_) {
temp = value * NORM_7;
tilt[0] = temp;
tilt[1] = temp * temp;
tilt[2] = temp * temp * temp;
}
else {
printf("FM4Op : Undefined Control Number!!\n");
}
}

View File

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

View File

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

View File

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

View File

@@ -1,178 +0,0 @@
/******************************************/
/* WaveGuide Flute ala Karjalainen, */
/* Smith, Waryznyk, etc. */
/* with polynomial Jet ala Cook */
/* by Perry Cook, 1995-96 */
/* */
/* This is a waveguide model, and thus */
/* relates to various Stanford Univ. */
/* and possibly Yamaha and other patents.*/
/* */
/* Controls: CONTROL1 = jetDelay */
/* CONTROL2 = noiseGain */
/* CONTROL3 = vibFreq */
/* MOD_WHEEL= vibAmt */
/******************************************/
#include "Flute.h"
#include "SKINI11.msg"
Flute :: Flute(MY_FLOAT lowestFreq)
{
long length;
length = (long) (SRATE / lowestFreq + 1);
boreDelay = new DLineL(length);
length >>= 1;
jetDelay = new DLineL(length);
jetTable = new JetTabl;
filter = new OnePole;
dcBlock = new DCBlock;
noise = new Noise;
adsr = new ADSR;
// Concatenate the STK RAWWAVE_PATH to the rawwave file
char file[128];
strcpy(file, RAWWAVE_PATH);
vibr = new RawWvIn(strcat(file,"rawwaves/sinewave.raw"),"looping");
this->clear();
boreDelay->setDelay((MY_FLOAT) 100.0);
jetDelay->setDelay((MY_FLOAT) 49.0);
filter->setPole((MY_FLOAT) 0.7 - ((MY_FLOAT) 0.1 * (MY_FLOAT) 22050.0 / SRATE));
filter->setGain((MY_FLOAT) -1.0);
vibr->normalize();
vibr->setFreq((MY_FLOAT) 5.925);
adsr->setAllTimes((MY_FLOAT) 0.005, (MY_FLOAT) 0.01, (MY_FLOAT) 0.8, (MY_FLOAT) 0.010);
endRefl = (MY_FLOAT) 0.5;
jetRefl = (MY_FLOAT) 0.5;
noiseGain = (MY_FLOAT) 0.15; /* Breath pressure random component */
vibrGain = (MY_FLOAT) 0.05; /* breath periodic vibrato component */
jetRatio = (MY_FLOAT) 0.32;
maxPressure = (MY_FLOAT) 0.0;
}
Flute :: ~Flute()
{
delete jetDelay;
delete boreDelay;
delete jetTable;
delete filter;
delete dcBlock;
delete noise;
delete adsr;
delete vibr;
}
void Flute :: clear()
{
jetDelay->clear();
boreDelay->clear();
filter->clear();
dcBlock->clear();
}
void Flute :: setFreq(MY_FLOAT frequency)
{
MY_FLOAT temp;
lastFreq = frequency * (MY_FLOAT) 0.66666; /* we're overblowing here */
temp = SRATE / lastFreq - (MY_FLOAT) 2.0; /* Length - approx. filter delay */
boreDelay->setDelay(temp); /* Length of bore tube */
jetDelay->setDelay(temp * jetRatio); /* jet delay shorter */
}
void Flute :: startBlowing(MY_FLOAT amplitude, MY_FLOAT rate)
{
adsr->setAttackRate(rate);
maxPressure = amplitude / (MY_FLOAT) 0.8;
adsr->keyOn();
}
void Flute :: stopBlowing(MY_FLOAT rate)
{
adsr->setReleaseRate(rate);
adsr->keyOff();
}
void Flute :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
{
this->setFreq(freq);
this->startBlowing((MY_FLOAT) 1.1 + (amp * (MY_FLOAT) 0.20),amp * (MY_FLOAT) 0.02);
outputGain = amp + (MY_FLOAT) 0.001;
#if defined(_debug_)
printf("Flute : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
#endif
}
void Flute :: noteOff(MY_FLOAT amp)
{
this->stopBlowing(amp * (MY_FLOAT) 0.02);
#if defined(_debug_)
printf("Flute : NoteOff: Amp=%lf\n",amp);
#endif
}
void Flute :: setJetRefl(MY_FLOAT refl)
{
jetRefl = refl;
}
void Flute :: setEndRefl(MY_FLOAT refl)
{
endRefl = refl;
}
void Flute :: setJetDelay(MY_FLOAT aRatio)
{
MY_FLOAT temp;
temp = SRATE / lastFreq - (MY_FLOAT) 2.0; /* Length - approx. filter delay */
jetRatio = aRatio;
jetDelay->setDelay(temp * aRatio); /* Scaled by ratio */
}
MY_FLOAT Flute :: tick()
{
MY_FLOAT temp;
MY_FLOAT pressureDiff;
MY_FLOAT randPressure;
MY_FLOAT breathPressure;
breathPressure = maxPressure * adsr->tick(); /* Breath Pressure */
randPressure = noiseGain * noise->tick(); /* Random Deviation */
randPressure += vibrGain * vibr->tick(); /* + breath vibrato */
randPressure *= breathPressure; /* All scaled by Breath Pressure */
temp = filter->tick(boreDelay->lastOut());
temp = dcBlock->tick(temp); /* Block DC on reflection */
pressureDiff = breathPressure + randPressure - /* Breath Pressure */
(jetRefl * temp); /* - reflected */
pressureDiff = jetDelay->tick(pressureDiff); /* Jet Delay Line */
pressureDiff = jetTable->lookup(pressureDiff) /* Non-Lin Jet + reflected */
+ (endRefl * temp);
lastOutput = (MY_FLOAT) 0.3 * boreDelay->tick(pressureDiff); /* Bore Delay and "bell" filter */
lastOutput *= outputGain;
return lastOutput;
}
void Flute :: controlChange(int number, MY_FLOAT value)
{
#if defined(_debug_)
printf("Flute : ControlChange: Number=%i Value=%f\n",number,value);
#endif
if (number == __SK_JetDelay_)
this->setJetDelay((MY_FLOAT) 0.08 + ((MY_FLOAT) 0.48 * value * NORM_7));
else if (number == __SK_NoiseLevel_)
noiseGain = (value * NORM_7 * (MY_FLOAT) 0.4);
else if (number == __SK_ModFrequency_)
vibr->setFreq((value * NORM_7 * (MY_FLOAT) 12.0));
else if (number == __SK_ModWheel_)
vibrGain = (value * NORM_7 * (MY_FLOAT) 0.4);
else if (number == __SK_AfterTouch_Cont_)
adsr->setTarget(value * NORM_7);
else {
printf("Flute : Undefined Control Number!!\n");
}
}

View File

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

View File

@@ -1,139 +0,0 @@
/*******************************************/
/* Sweepable Formant (2-pole) */
/* Filter Class, by Perry R. Cook, 1995-96*/
/* See books on filters to understand */
/* more about how this works. This drives*/
/* to a target at speed set by rate. */
/*******************************************/
#include "FormSwep.h"
FormSwep :: FormSwep() : Filter()
{
outputs = (MY_FLOAT *) malloc(2 * sizeof(MY_FLOAT));
poleCoeffs[0] = (MY_FLOAT) 0.0;
poleCoeffs[1] = (MY_FLOAT) 0.0;
gain = (MY_FLOAT) 1.0;
freq = (MY_FLOAT) 0.0;
reson = (MY_FLOAT) 0.0;
currentGain = (MY_FLOAT) 1.0;
currentFreq = (MY_FLOAT) 0.0;
currentReson = (MY_FLOAT) 0.0;
targetGain = (MY_FLOAT) 1.0;
targetFreq = (MY_FLOAT) 0.0;
targetReson = (MY_FLOAT) 0.0;
deltaGain = (MY_FLOAT) 0.0;
deltaFreq = (MY_FLOAT) 0.0;
deltaReson = (MY_FLOAT) 0.0;
sweepState = (MY_FLOAT) 0.0;
sweepRate = (MY_FLOAT) 0.002;
dirty = 0;
this->clear();
}
FormSwep :: ~FormSwep()
{
free(outputs);
}
void FormSwep :: clear()
{
outputs[0] = (MY_FLOAT) 0.0;
outputs[1] = (MY_FLOAT) 0.0;
}
void FormSwep :: setPoleCoeffs(MY_FLOAT *coeffs)
{
dirty = 0;
poleCoeffs[0] = coeffs[0];
poleCoeffs[1] = coeffs[1];
}
void FormSwep :: setFreqAndReson(MY_FLOAT aFreq, MY_FLOAT aReson)
{
dirty = 0;
reson = aReson;
freq = aFreq;
currentReson = aReson;
currentFreq = aFreq;
poleCoeffs[1] = - (reson * reson);
poleCoeffs[0] = (MY_FLOAT) 2.0 * reson * (MY_FLOAT) cos(TWO_PI * freq / SRATE);
}
void FormSwep :: setStates(MY_FLOAT aFreq, MY_FLOAT aReson, MY_FLOAT aGain)
{
dirty = 0;
freq = aFreq;
reson = aReson;
gain = aGain;
targetFreq = aFreq;
targetReson = aReson;
targetGain = aGain;
currentFreq = aFreq;
currentReson = aReson;
currentGain = aGain;
}
void FormSwep :: setTargets(MY_FLOAT aFreq, MY_FLOAT aReson, MY_FLOAT aGain)
{
dirty = 1;
targetFreq = aFreq;
targetReson = aReson;
targetGain = aGain;
deltaFreq = aFreq - currentFreq;
deltaReson = aReson - currentReson;
deltaGain = aGain - currentGain;
sweepState = (MY_FLOAT) 0.0;
}
void FormSwep :: setSweepRate(MY_FLOAT aRate)
{
sweepRate = aRate;
}
void FormSwep :: setSweepTime(MY_FLOAT aTime)
{
sweepRate = ONE_OVER_SRATE / aTime;
}
void FormSwep :: setGain(MY_FLOAT aValue)
{
gain = aValue;
}
MY_FLOAT FormSwep :: tick(MY_FLOAT sample) // Perform Filter Operation
{
MY_FLOAT temp;
if (dirty) {
sweepState += sweepRate;
if (sweepState>= 1.0) {
sweepState = (MY_FLOAT) 1.0;
dirty = 0;
currentReson = targetReson;
reson = targetReson;
currentFreq = targetFreq;
freq = targetFreq;
currentGain = targetGain;
gain = targetGain;
}
else {
currentReson = reson + (deltaReson * sweepState);
currentFreq = freq + (deltaFreq * sweepState);
currentGain = gain + (deltaGain * sweepState);
}
poleCoeffs[1] = - (currentReson * currentReson);
poleCoeffs[0] = (MY_FLOAT) 2.0 * currentReson *
(MY_FLOAT) cos(TWO_PI * currentFreq / SRATE);
}
temp = currentGain * sample;
temp += poleCoeffs[0] * outputs[0];
temp += poleCoeffs[1] * outputs[1];
outputs[1] = outputs[0];
outputs[0] = temp;
lastOutput = outputs[0];
return lastOutput;
}

View File

@@ -1,46 +0,0 @@
/*******************************************/
/* Sweepable Formant (2-pole) */
/* Filter Class, by Perry R. Cook, 1995-96*/
/* See books on filters to understand */
/* more about how this works. Nothing */
/* out of the ordinary in this version. */
/*******************************************/
#if !defined(__FormSwep_h)
#define __FormSwep_h
#include "Filter.h"
class FormSwep : public Filter
{
protected:
MY_FLOAT poleCoeffs[2];
MY_FLOAT freq;
MY_FLOAT reson;
int dirty;
MY_FLOAT targetFreq;
MY_FLOAT targetReson;
MY_FLOAT targetGain;
MY_FLOAT currentFreq;
MY_FLOAT currentReson;
MY_FLOAT currentGain;
MY_FLOAT deltaFreq;
MY_FLOAT deltaReson;
MY_FLOAT deltaGain;
MY_FLOAT sweepState;
MY_FLOAT sweepRate;
public:
FormSwep();
~FormSwep();
void clear();
void setPoleCoeffs(MY_FLOAT *coeffs);
void setGain(MY_FLOAT aValue);
void setFreqAndReson(MY_FLOAT aFreq, MY_FLOAT aReson);
void setStates(MY_FLOAT aFreq, MY_FLOAT aReson, MY_FLOAT aGain);
void setTargets(MY_FLOAT aFreq, MY_FLOAT aReson, MY_FLOAT aGain);
void setSweepRate(MY_FLOAT aRate);
void setSweepTime(MY_FLOAT aTime);
MY_FLOAT tick(MY_FLOAT sample);
};
#endif

View File

@@ -1,68 +0,0 @@
/******************************************/
/* Heavy Metal Synth Subclass */
/* of Algorithm 3 (TX81Z) Subclass of */
/* 3 Operator FM Synth */
/* by Perry R. Cook, 1995-96 */
/******************************************/
#include "HeavyMtl.h"
HeavyMtl :: HeavyMtl() : FM4Alg3()
{
char file1[128];
char file2[128];
char file3[128];
char file4[128];
strcpy(file1, RAWWAVE_PATH);
strcpy(file2, RAWWAVE_PATH);
strcpy(file3, RAWWAVE_PATH);
strcpy(file4, RAWWAVE_PATH);
this->loadWaves(strcat(file1,"rawwaves/sinewave.raw"),
strcat(file2,"rawwaves/sinewave.raw"),
strcat(file3,"rawwaves/sinewave.raw"),
strcat(file4,"rawwaves/fwavblnk.raw"));
this->setRatio(0,(MY_FLOAT) (1.00 * 1.000));
this->setRatio(1,(MY_FLOAT) (4.00 * 0.999));
this->setRatio(2,(MY_FLOAT) (3.00 * 1.001));
this->setRatio(3,(MY_FLOAT) (0.50 * 1.002));
gains[0] = __FM4Op_gains[92];
gains[1] = __FM4Op_gains[76];
gains[2] = __FM4Op_gains[91];
gains[3] = __FM4Op_gains[68];
adsr[0]->setAllTimes((MY_FLOAT) 0.001,(MY_FLOAT) 0.001,(MY_FLOAT) 1.0,(MY_FLOAT) 0.01);
adsr[1]->setAllTimes((MY_FLOAT) 0.001,(MY_FLOAT) 0.010,(MY_FLOAT) 1.0,(MY_FLOAT) 0.50);
adsr[2]->setAllTimes((MY_FLOAT) 0.010,(MY_FLOAT) 0.005,(MY_FLOAT) 1.0,(MY_FLOAT) 0.20);
adsr[3]->setAllTimes((MY_FLOAT) 0.030,(MY_FLOAT) 0.010,(MY_FLOAT) 0.2,(MY_FLOAT) 0.20);
twozero->setGain((MY_FLOAT) 2.0);
vibWave->setFreq((MY_FLOAT) 5.5);
modDepth = (MY_FLOAT) 0.00;
}
HeavyMtl :: ~HeavyMtl()
{
}
void HeavyMtl :: setFreq(MY_FLOAT frequency)
{
baseFreq = frequency;
waves[0]->setFreq(baseFreq * ratios[0]);
waves[1]->setFreq(baseFreq * ratios[1]);
waves[2]->setFreq(baseFreq * ratios[2]);
waves[3]->setFreq(baseFreq * ratios[3]);
}
void HeavyMtl :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
{
gains[0] = amp * __FM4Op_gains[92];
gains[1] = amp * __FM4Op_gains[76];
gains[2] = amp * __FM4Op_gains[91];
gains[3] = amp * __FM4Op_gains[68];
this->setFreq(freq);
this->keyOn();
#if defined(_debug_)
printf("HeavyMtl : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
#endif
}

View File

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

View File

@@ -1,45 +0,0 @@
/******************************************/
/* Instrument SuperClass for Toolkit96 */
/* Perry R. Cook, Princeton University */
/******************************************/
#include "Instrmnt.h"
Instrmnt :: Instrmnt()
{
}
Instrmnt :: ~Instrmnt()
{
}
void Instrmnt :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
{
printf("Warning!! Instrument Class noteOn here!! %f %f\n",freq,amp);
}
void Instrmnt :: noteOff(MY_FLOAT amp)
{
printf("Warning!! Instrument Class noteOff here!! %f\n",amp);
}
void Instrmnt :: setFreq(MY_FLOAT freq)
{
printf("Warning!! Instrument Class setFreq here!! %f\n",freq);
}
MY_FLOAT Instrmnt :: tick()
{
printf("Warning!! Instrument Class tick here!!\n");
return lastOutput;
}
MY_FLOAT Instrmnt :: lastOut()
{
return lastOutput;
}
void Instrmnt :: controlChange(int number, MY_FLOAT value)
{
printf("Warning!! Instrument Class Control Change here!! %i %f\n",number,value);
}

View File

@@ -1,26 +0,0 @@
/******************************************/
/* Instrument SuperClass for Toolkit96 */
/* Perry R. Cook, Princeton University */
/******************************************/
#if !defined(__Instrmnt_h)
#define __Instrmnt_h
#include "Object.h"
class Instrmnt : public Object
{
protected:
MY_FLOAT lastOutput;
public:
Instrmnt();
virtual ~Instrmnt();
MY_FLOAT lastOut();
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
virtual void noteOff(MY_FLOAT amp);
virtual void setFreq(MY_FLOAT frequency);
virtual MY_FLOAT tick();
virtual void controlChange(int number, MY_FLOAT value);
};
#endif

View File

@@ -1,166 +0,0 @@
/*******************************************/
/* JVRev Reverb Subclass */
/* by Tim Stilson, 1998 */
/* based on CLM JCRev */
/* Integrated into STK by Gary Scavone */
/* */
/* This is based on some of the famous */
/* Stanford CCRMA reverbs (NRev, KipRev) */
/* all based on the Chowning/Moorer/ */
/* Schroeder reverberators, which use */
/* networks of simple allpass and comb */
/* delay filters. This particular */
/* arrangement consists of 3 allpass */
/* filters in series, followed by 4 comb */
/* filters in parallel, an optional */
/* lowpass filter, and two decorrelation */
/* delay lines in parallel at the output. */
/*******************************************/
#include "JCRev.h"
//#define LOWPASS
JCRev :: JCRev(MY_FLOAT T60)
{
/* These are the values from CLM's JCRev.ins ... I found that the
impulse response sounded better with the shorter delay lengths.
--Gary Scavone, 2/1998
int lens[9] = {4799,4999,5399,5801,1051,337,113,573,487};
*/
int lens[9] = {1777,1847,1993,2137,389,127,43,211,179};
int val, i;
if (SRATE < 44100.0) {
double srscale = SRATE / 44100.0;
for (i=0; i<9; i++) {
val = (int) floor(srscale * lens[i]);
if ((val & 1) == 0) val++;
while (!this->isprime(val)) val += 2;
lens[i] = val;
}
}
for (i=0; i<3; i++)
{
APdelayLine[i] = new DLineN(lens[i+4] + 2);
APdelayLine[i]->setDelay(lens[i+4]);
}
for (i=0; i<4; i++)
{
CdelayLine[i] = new DLineN(lens[i] + 2);
CdelayLine[i]->setDelay(lens[i]);
combCoeff[i] = pow(10,(-3 * lens[i] / (T60 * SRATE)));
// printf("combCoeff[%d] = %f\n", i, combCoeff[i]);
}
outLdelayLine = new DLineN(lens[7] + 2);
outLdelayLine->setDelay(lens[7]);
outRdelayLine = new DLineN(lens[8] + 2);
outRdelayLine->setDelay(lens[8]);
allPassCoeff = 0.7;
effectMix = 0.3;
this->clear();
}
JCRev :: ~JCRev()
{
delete APdelayLine[0];
delete APdelayLine[1];
delete APdelayLine[2];
delete CdelayLine[0];
delete CdelayLine[1];
delete CdelayLine[2];
delete CdelayLine[3];
delete outLdelayLine;
delete outRdelayLine;
}
void JCRev :: clear()
{
APdelayLine[0]->clear();
APdelayLine[1]->clear();
APdelayLine[2]->clear();
CdelayLine[0]->clear();
CdelayLine[1]->clear();
CdelayLine[2]->clear();
CdelayLine[3]->clear();
outRdelayLine->clear();
outLdelayLine->clear();
lastOutL = 0.0;
lastOutR = 0.0;
combsum1=0.0;
combsum2=0.0;
combsum=0.0;
}
void JCRev :: setEffectMix(MY_FLOAT mix)
{
effectMix = mix;
}
MY_FLOAT JCRev :: lastOutput()
{
return (lastOutL + lastOutR) * 0.5;
}
MY_FLOAT JCRev :: lastOutputL()
{
return lastOutL;
}
MY_FLOAT JCRev :: lastOutputR()
{
return lastOutR;
}
MY_FLOAT JCRev :: tick(MY_FLOAT input)
{
MY_FLOAT temp,temp0,temp1,temp2,temp3,temp4,temp5,temp6;
MY_FLOAT filtout;
temp = APdelayLine[0]->lastOut();
temp0 = allPassCoeff * temp;
temp0 += input;
APdelayLine[0]->tick(temp0);
temp0 = -(allPassCoeff * temp0) + temp;
temp = APdelayLine[1]->lastOut();
temp1 = allPassCoeff * temp;
temp1 += temp0;
APdelayLine[1]->tick(temp1);
temp1 = -(allPassCoeff * temp1) + temp;
temp = APdelayLine[2]->lastOut();
temp2 = allPassCoeff * temp;
temp2 += temp1;
APdelayLine[2]->tick(temp2);
temp2 = -(allPassCoeff * temp2) + temp;
temp3 = temp2 + (combCoeff[0] * CdelayLine[0]->lastOut());
temp4 = temp2 + (combCoeff[1] * CdelayLine[1]->lastOut());
temp5 = temp2 + (combCoeff[2] * CdelayLine[2]->lastOut());
temp6 = temp2 + (combCoeff[3] * CdelayLine[3]->lastOut());
CdelayLine[0]->tick(temp3);
CdelayLine[1]->tick(temp4);
CdelayLine[2]->tick(temp5);
CdelayLine[3]->tick(temp6);
#ifdef LOWPASS
combsum2=combsum1;
combsum1=combsum;
combsum = temp3+temp4+temp5+temp6;
filtout= 0.5*combsum1+0.25*(combsum+combsum2);
#else
filtout = temp3+temp4+temp5+temp6;
#endif
lastOutL = effectMix * (outLdelayLine->tick(filtout));
lastOutR = effectMix * (outRdelayLine->tick(filtout));
temp = (1.0 - effectMix) * input;
lastOutL += temp;
lastOutR += temp;
return (lastOutL + lastOutR) * 0.5;
}

View File

@@ -1,52 +0,0 @@
/*******************************************/
/* JVRev Reverb Subclass */
/* by Tim Stilson, 1998 */
/* based on CLM JCRev */
/* Integrated into STK by Gary Scavone */
/* */
/* This is based on some of the famous */
/* Stanford CCRMA reverbs (NRev, KipRev) */
/* all based on the Chowning/Moorer/ */
/* Schroeder reverberators, which use */
/* networks of simple allpass and comb */
/* delay filters. This particular */
/* arrangement consists of 3 allpass */
/* filters in series, followed by 4 comb */
/* filters in parallel, an optional */
/* lowpass filter, and two decorrelation */
/* delay lines in parallel at the output. */
/*******************************************/
#if !defined(__JCRev_h)
#define __JCRev_h
#include "Object.h"
#include "Reverb.h"
#include "DLineN.h"
class JCRev : public Reverb
{
protected:
DLineN *APdelayLine[3];
DLineN *CdelayLine[4];
DLineN *outLdelayLine;
DLineN *outRdelayLine;
MY_FLOAT allPassCoeff;
MY_FLOAT combCoeff[4];
MY_FLOAT combsum,combsum1,combsum2;
MY_FLOAT lastOutL;
MY_FLOAT lastOutR;
MY_FLOAT effectMix;
public:
JCRev(MY_FLOAT T60);
~JCRev();
void clear();
void setEffectMix(MY_FLOAT mix);
MY_FLOAT lastOutput();
MY_FLOAT lastOutputL();
MY_FLOAT lastOutputR();
MY_FLOAT tick(MY_FLOAT input);
};
#endif

View File

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

View File

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

View File

@@ -1,65 +0,0 @@
/************************************************/
/* Lip Filter Object by Perry R. Cook, 1995-96 */
/* The lip of the brass player has dynamics */
/* which are controlled by the mass, spring */
/* constant, and damping of the lip. This */
/* filter simulates that behavior and the */
/* transmission/reflection properties as */
/* well. See Cook TBone and HosePlayer */
/* instruments and articles. */
/************************************************/
#include "LipFilt.h"
LipFilt :: LipFilt()
{
MY_FLOAT coeffs[2];
filter = new BiQuad;
coeffs[0] = (MY_FLOAT) 0.0;
coeffs[1] = (MY_FLOAT) 0.0;
filter->setZeroCoeffs(coeffs);
this->clear();
}
LipFilt :: ~LipFilt()
{
delete filter;
}
void LipFilt :: clear()
{
filter->clear();
lastOutput = (MY_FLOAT) 0.0;
}
void LipFilt :: setFreq(MY_FLOAT frequency)
{
MY_FLOAT coeffs[2];
coeffs[0] = (MY_FLOAT) 2.0 * (MY_FLOAT) 0.997 *
(MY_FLOAT) cos(TWO_PI * frequency / SRATE); /* damping should change with */
coeffs[1] = (MY_FLOAT) (-0.997 * 0.997); /* lip parameters, but not yet.*/
filter->setPoleCoeffs(coeffs);
filter->setGain((MY_FLOAT) 0.03);
}
/* NOTE: Here we should add lip tension */
/* settings based on Mass/Spring/Damping */
MY_FLOAT LipFilt :: tick(MY_FLOAT mouthSample,MY_FLOAT boreSample)
/* Perform "Table Lookup" By Polynomial Calculation */
{
MY_FLOAT temp;
temp = mouthSample - boreSample; /* Differential pressure */
temp = filter->tick(temp); /* Force -> position */
temp = temp*temp; /* Simple position to area mapping */
if (temp > 1.0) temp = (MY_FLOAT) 1.0; /* Saturation at + 1.0 */
lastOutput = temp * mouthSample; /* Assume mouth input = area */
lastOutput += ((MY_FLOAT) 1.0 - temp) * boreSample; /* and Bore reflection is compliment. */
return lastOutput;
}
MY_FLOAT LipFilt :: lastOut()
{
return lastOutput;
}

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,404 +0,0 @@
/*******************************************/
/* Simple Realtime MIDI to SKINI Parser */
/* Gary P. Scavone, February 1998. */
/* Revised for sockets, May & June 1998. */
/* SKINI/MIDI merge added August 1999. */
/* */
/* This object takes MIDI from the input */
/* stream (via the MIDIIO class), */
/* parses it, and turns it into SKINI */
/* messages. */
/*******************************************/
#include "MIDIIO.h"
#include "SKINI11.msg"
#if defined(__STK_REALTIME_)
int outAHere = 0;
// Do OS dependent declarations and includes
#if (defined(__OS_IRIX_) || defined(__OS_Linux_))
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <pthread.h>
pthread_t exit_thread;
#elif defined(__OS_Win_)
#include <process.h>
#include <winsock.h>
unsigned long exit_thread;
#endif
// The thread function protocols are slightly different
// under Windoze ... but of course!
#if (defined(__OS_IRIX_) || defined(__OS_Linux_))
void *monitorStdin(void *)
#elif defined(__OS_Win_)
void monitorStdin(void *)
#endif
{
char inputString[128];
printf("Type 'Exit<cr>' to quit.\n");
while (!outAHere) {
fgets(inputString, 128, stdin);
if (inputString[3] == 't' && inputString[1] == 'x'
&& inputString[2] == 'i' && inputString[0] == 'E') {
outAHere = 1;
}
else {
printf(inputString);
fflush(stdout);
}
}
#if (defined(__OS_IRIX_) || defined(__OS_Linux_))
pthread_exit(NULL);
return NULL;
#elif defined(__OS_Win_)
_endthread();
#endif
}
void usage(void) {
printf("useage: MD2SKINI <flag(s)>\n\n");
printf(" With no arguments, MD2SKINI converts MIDI input to SKINI\n");
printf(" format and sends the output directly to stdout.\n");
printf(" With flag = -s <hostname>, the output is sent over a socket\n");
printf(" connection to the optional hostname (default = localhost).\n");
printf(" With flag = -f <filename>, the output stream is simultaneously\n");
printf(" written to the file specified by the optional <filename>\n");
printf(" (default = test.ski).\n\n");
exit(0);
}
int main(int argc,char *argv[])
{
long j, i = 1;
MY_FLOAT byte2, byte3;
int channel;
int firstMessage = 1;
int writeFileOut = 0;
FILE *fileOut = NULL;
MIDIIO *controller;
char hostName[256];
char fileName[256];
int useSocket = 0;
int theSocket = 0;
struct sockaddr_in saServer;
static struct timeval timeout = {0, 10000}; // ten millisecond
if (argc>5) {
usage();
}
// Parse the command-line arguments.
while (i < argc) {
if (argv[i][0] == '-') {
switch(argv[i][1]) {
case 's':
if ((i+1 < argc) && argv[i+1][0] != '-') {
i++;
strcpy(hostName,argv[i]);
}
else strcpy(hostName,"localhost");
useSocket = 1;
break;
case 'f':
if ((i+1 < argc) && argv[i+1][0] != '-') {
i++;
strcpy(fileName,argv[i]);
if (strstr(fileName,".ski") == NULL) strcat(fileName,".ski");
}
else strcpy(fileName,"test.ski");
fileOut = fopen(fileName,"wb");
writeFileOut = 1;
break;
default:
usage();
break;
}
}
else usage();
i++;
}
MY_FLOAT dt=0.0;
controller = new MIDIIO();
// If using sockets, setup the client socket
if (useSocket) {
#if defined(__OS_Win_) // Stupid Windoze only stuff
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD(1,1);
WSAStartup(wVersionRequested, &wsaData);
if (wsaData.wVersion != wVersionRequested) {
fprintf(stderr,"\n Wrong Windoze socket library version!\n");
exit(0);
}
#endif
// Create the client-side socket
theSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (theSocket < 0) {
fprintf(stderr,"Couldn't create socket ... aborting!\n");
exit(0);
}
struct hostent *hostp;
if ((hostp = gethostbyname(hostName)) == 0) {
fprintf(stderr,"%s: unknown host ... aborting!\n", hostName);
exit(0);
}
// Fill in the address structure
saServer.sin_family = AF_INET;
memcpy((void *)&saServer.sin_addr, hostp->h_addr, hostp->h_length);
saServer.sin_port = htons(2001); // Port number
// Connect to the server
if(connect(theSocket, (struct sockaddr *)&saServer, sizeof(saServer)) < 0) {
fprintf(stderr,"Socket connect failed ... aborting!\n");
#if defined(__OS_Win_)
closesocket(theSocket);
WSACleanup();
#else
close(theSocket);
#endif
exit(0);
}
}
// Setup the exit thread.
#if (defined(__OS_IRIX_) || defined(__OS_Linux_))
if (pthread_create(&exit_thread, NULL, monitorStdin, NULL)) {
fprintf(stderr, "Unable to create exit thread ... aborting.\n");
exit(0);
}
#elif defined(__OS_Win_)
exit_thread = _beginthread(monitorStdin, 0, NULL);
if (exit_thread == -1) {
fprintf(stderr, "Unable to create exit thread ... aborting.\n");
exit(0);
}
#endif
/* Write SKINI messages to buffer 's'. This is the easiest way
to allow this single executable to work for both socketing
and printf's to stdout.
*/
char s[128];
while (!outAHere) {
if (controller->nextMessage() > 0) {
byte3 = controller->getByteThree();
byte2 = controller->getByteTwo();
channel = controller->getChannel();
if (writeFileOut) dt = controller->getDeltaTime();
if (firstMessage) { /* first MIDI message time stamp is meaningless */
dt = 0.0;
firstMessage = 0;
}
switch(controller->getType()) {
case __SK_NoteOn_:
if (byte3 < 1.0) {
sprintf(s,"NoteOff\t\t%.3f %d %.1f %.1f\n",0.0,channel,byte2,64.0);
if (writeFileOut) {
fprintf(fileOut,"NoteOff\t\t%.3f %d %.1f %.1f\n",dt,channel,byte2,64.0);
}
} else {
sprintf(s,"NoteOn\t\t%.3f %d %.1f %.1f\n",0.0,channel,byte2,byte3);
if (writeFileOut) {
fprintf(fileOut,"NoteOn\t\t%.3f %d %.1f %.1f\n",dt,channel,byte2,byte3);
}
}
break;
case __SK_NoteOff_:
if (byte3 < 2.0) byte3 = 64.0;
sprintf(s,"NoteOff\t\t%.3f %d %.1f %.1f\n",0.0,channel,byte2,byte3);
if (writeFileOut) {
fprintf(fileOut,"NoteOff\t\t%.3f %d %.1f %.1f\n",dt,channel,byte2,byte3);
}
break;
case __SK_PolyPressure_:
sprintf(s,"PolyPressure\t%.3f %d %.1f %.1f\n",0.0,channel,byte2,byte3);
if (writeFileOut) {
fprintf(fileOut,"PolyPressure\t%.3f %d %.1f %.1f\n",dt,channel,byte2,byte3);
}
break;
case __SK_ControlChange_:
j = (int) byte2;
switch(j) {
case __SK_Volume_:
sprintf(s,"Volume\t%.3f %d %.1f\n",0.0,channel,byte3);
if (writeFileOut) {
fprintf(fileOut,"Volume\t%.3f %d %.1f\n",dt,channel,byte3);
}
break;
case __SK_ModWheel_:
sprintf(s,"ModWheel\t%.3f %d %.1f\n",0.0,channel,byte3);
if (writeFileOut) {
fprintf(fileOut,"ModWheel\t%.3f %d %.1f\n",dt,channel,byte3);
}
break;
case __SK_Breath_:
sprintf(s,"Breath\t\t%.3f %d %.1f\n",0.0,channel,byte3);
if (writeFileOut) {
fprintf(fileOut,"Breath\t\t%.3f %d %.1f\n",dt,channel,byte3);
}
break;
case __SK_FootControl_:
sprintf(s,"FootControl\t%.3f %d %.1f\n",0.0,channel,byte3);
if (writeFileOut) {
fprintf(fileOut,"FootControl\t%.3f %d %.1f\n",dt,channel,byte3);
}
break;
case __SK_Portamento_:
sprintf(s,"Portamento\t%.3f %d %.1f\n",0.0,channel,byte3);
if (writeFileOut) {
fprintf(fileOut,"Portamento\t%.3f %d %.1f\n",dt,channel,byte3);
}
break;
case __SK_Balance_:
sprintf(s,"Balance\t%.3f %d %.1f\n",0.0,channel,byte3);
if (writeFileOut) {
fprintf(fileOut,"Balance\t%.3f %d %.1f\n",dt,channel,byte3);
}
break;
case __SK_Pan_:
sprintf(s,"Pan\t\t%.3f %d %.1f\n",0.0,channel,byte3);
if (writeFileOut) {
fprintf(fileOut,"Pan\t\t%.3f %d %.1f\n",dt,channel,byte3);
}
break;
case __SK_Sustain_:
sprintf(s,"Sustain\t%.3f %d %.1f\n",0.0,channel,byte3);
if (writeFileOut) {
fprintf(fileOut,"Sustain\t%.3f %d %.1f\n",dt,channel,byte3);
}
break;
case __SK_Expression_:
sprintf(s,"Expression\t%.3f %d %.1f\n",0.0,channel,byte3);
if (writeFileOut) {
fprintf(fileOut,"Expression\t%.3f %d %.1f\n",dt,channel,byte3);
}
break;
default:
sprintf(s,"ControlChange\t%.3f %d %ld %.1f\n",0.0,channel,j,byte3);
if (writeFileOut) {
fprintf(fileOut,"ControlChange\t%.3f %d %ld %.1f\n",dt,channel,j,byte3);
}
break;
}
break;
case __SK_ProgramChange_:
j = (int) byte2;
sprintf(s,"ProgramChange\t%.3f %d %ld\n",0.0,channel,j);
if (writeFileOut) {
fprintf(fileOut,"ProgramChange\t%.3f %d %ld\n",dt,channel,j);
}
break;
case __SK_ChannelPressure_:
sprintf(s,"ChannelPressure\t%.3f %d %.1f\n",0.0,channel,byte2);
if (writeFileOut) {
fprintf(fileOut,"ChannelPressure\t%.3f %d %.1f\n",dt,channel,byte2);
}
break;
case __SK_PitchBend_:
sprintf(s,"PitchBend\t%.3f %d %f\n",0.0,channel,byte2);
if (writeFileOut) {
fprintf(fileOut,"PitchBend\t%.3f %d %f\n",dt,channel,byte2);
}
break;
default:
sprintf(s,"// Unknown\t%.3f %d %f %f\n",0.0,channel,byte2,byte3);
if (writeFileOut) {
fprintf(fileOut,"// Unknown\t\t%.3f %d %f %f\n",dt,channel,byte2,byte3);
}
break;
}
if (useSocket) {
if (send(theSocket, s, strlen(s), 0) < 0) {
fprintf(stderr,"Socket connection failed ... aborting.\n");
#if defined(__OS_Win_)
closesocket(theSocket);
WSACleanup();
#else
close(theSocket);
#endif
outAHere = 1;
exit(0);
}
}
else {
printf("%s", s);
fflush(stdout);
}
memset(s, 0, sizeof(s));
} else {
// With Irix 5.3, you can no longer use the usleep()
// function. And in Windoze, you can't use the select()
// function to do timings. I love supporting multiple
// platforms!
#if defined(__OS_Win_)
Sleep ( (DWORD) 5);
#else
timeout.tv_sec = 0;
timeout.tv_usec = 10000; // 0.01 seconds
select(0, NULL, NULL, NULL, &timeout);
#endif
}
}
sprintf(s,"Exiting MD2SKINI process ... bye!\n");
if (useSocket) {
send(theSocket, s, strlen(s), 0);
#if defined(__OS_Win_)
closesocket(theSocket);
WSACleanup();
#else
close(theSocket);
#endif
}
else {
printf("%s", s);
fflush(stdout);
}
if (writeFileOut) {
printf("Wrote SKINI output to file %s.\n", fileName);
fclose(fileOut);
}
delete controller;
return 0;
}
#endif

View File

@@ -1,582 +0,0 @@
/******************************************/
/* MIDIIO.cpp */
/* Realtime MIDI I/O Object for STK, */
/* by Gary P. Scavone, 1998. */
/* Based in part on code by Perry */
/* Cook (SGI), Paul Leonard (Linux), */
/* the RoseGarden team (Linux), and */
/* Bill Putnam (Win95/NT). */
/* */
/* At the moment, this object only */
/* handles MIDI Input, though MIDI */
/* Output code can go here when someone */
/* decides they need it (and writes it). */
/* */
/* This object opens a MIDI Input device */
/* and parses MIDI messages into a MIDI */
/* buffer. Time stamp info is converted */
/* to deltaTime. MIDI data is stored as */
/* MY_FLOAT to conform with SKINI. */
/******************************************/
#include "MIDIIO.h"
#if defined(__STK_REALTIME_)
#define MIDI_BUFFER_SIZE 1024
int writeOffset;
int readOffset;
#if defined(__OS_IRIX_)
/*************************************/
/* SGI MIDI INPUT */
/*************************************/
#include <pthread.h>
#include <dmedia/midi.h>
#include <sys/types.h>
#include <signal.h>
MDport inport;
MDevent *midiBuffer;
pthread_t midi_input_thread;
void *midiInputThread(void *)
{
MDevent newMessage;
int status;
while (1) {
mdReceive(inport, &newMessage, 1);
status = (newMessage.msg[0] & MD_STATUSMASK);
// Ignore all system messages
//if (!((status & 0xff) == 0xfe || (status & 0xff) == 0xf8)) {
if (status != 0xf0) {
midiBuffer[writeOffset] = newMessage;
writeOffset++;
if( writeOffset >= MIDI_BUFFER_SIZE )
writeOffset = 0;
}
}
}
MIDIIO :: MIDIIO()
{
int nports;
nports = mdInit();
printf("%d MIDI devices available\n", nports);
inport = mdOpenInPort(NULL);
if (inport == NULL) {
fprintf(stderr,"Cannot open MIDI device.\n");
printf("Exiting MIDIIO Process.\n");
exit(0);
}
mdSetStampMode(inport, MD_NOSTAMP);
// Set up the circular buffer for the Midi Input Messages
midiBuffer = new MDevent[MIDI_BUFFER_SIZE];
readOffset = 0;
writeOffset = 0;
if (pthread_create(&midi_input_thread, NULL, midiInputThread, NULL)) {
fprintf(stderr, "unable to create MIDI input thread ... aborting.\n");
exit(0);
}
}
MIDIIO :: ~MIDIIO()
{
pthread_cancel(midi_input_thread);
mdClosePort(inport);
delete [] midiBuffer;
}
int MIDIIO :: nextMessage()
{
int status;
int byte1;
int byte2;
MDevent lastEvent;
static unsigned long long lastTimeStamp = 0;
if ( readOffset == writeOffset ) return 0;
lastEvent = midiBuffer[readOffset];
readOffset++;
if ( readOffset >= MIDI_BUFFER_SIZE ) readOffset = 0;
status = (lastEvent.msg[0] & MD_STATUSMASK);
byte1 = lastEvent.msg[1];
byte2 = lastEvent.msg[2];
channel = (lastEvent.msg[0] & MD_CHANNELMASK);
if ((status == MD_PROGRAMCHANGE) ||
(status == MD_CHANNELPRESSURE))
{
messageType = status;
byteTwo = (float) byte1;
deltaTime = (MY_FLOAT) ((lastEvent.stamp - lastTimeStamp) * 0.000000001);
lastTimeStamp = lastEvent.stamp;
}
else if ((status == MD_NOTEON) || (status == MD_NOTEOFF) ||
(status == MD_CONTROLCHANGE) || (status == MD_POLYKEYPRESSURE))
{
messageType = status;
byteTwo = (float) byte1;
byteThree = (float) byte2;
deltaTime = (MY_FLOAT) ((lastEvent.stamp - lastTimeStamp) * 0.000000001);
lastTimeStamp = lastEvent.stamp;
}
else if (status == MD_PITCHBENDCHANGE)
{
messageType = status;
byteTwo = (float) byte1 * NORM_7;
byteTwo += (float) byte2;
deltaTime = (MY_FLOAT) ((lastEvent.stamp - lastTimeStamp) * 0.000000001);
lastTimeStamp = lastEvent.stamp;
}
else
{
messageType = -1;
}
return messageType;
}
#elif defined(__OSS_API_)
/*************************************/
/* OSS MIDI INPUT */
/*************************************/
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/soundcard.h>
#include <pthread.h>
//#include <pthread/mit/pthread.h>
int _seqfd;
typedef unsigned char byte;
typedef struct {
byte data[4];
unsigned long time;
} MIDIMESSAGE;
MIDIMESSAGE *midiBuffer;
/* System Messages */
#define MIDI_SYSTEM_MSG ((byte)0xF0)
#define MessageType(MSG) (byte)((MSG) & ((byte)0xF0))
#define SEQUENCER_PATH "/dev/sequencer"
/* MIDI time code at 100 ticks per second. */
#define OSS_MIDI_CLOCK_RATE 100
pthread_t midi_input_thread;
void *midiInputThread(void *)
{
byte NumArgs = 0;
byte ArgsLeft = 0;
unsigned long lastTime = 0;
unsigned long newTime = 0;
byte InBytes[4];
static MIDIMESSAGE newMessage;
int n;
while (1) {
if ((n = read(_seqfd, &InBytes, sizeof(InBytes))) == -1) {
fprintf(stderr,"Error reading " SEQUENCER_PATH "\n");
exit(0);
}
if (n == 4) { /* ignore reads returning less than 4 bytes */
switch ( InBytes[0] )
{
case SEQ_WAIT:
/* MIDI clock ticks ... the first MIDI message deltaTime is calculated
* with respect to the start of the MIDI clock.
*/
newTime = ((InBytes[3]<<16)|(InBytes[2]<<8)| InBytes[1]);
break;
case SEQ_ECHO:
/* no echo events yet defined */
#ifdef DEBUG
fprintf(stderr,"ECHO EVENT\n");
#endif
break;
case SEQ_MIDIPUTC:
/* Determination of a full MIDI message from the input MIDI stream is based
here on the observation that MIDI status bytes and subsequent data bytes
are NOT returned in the same read() call. Rather, they are spread out
over multiple read() returns, with only a single value per return. So,
if we find a status byte, we then determine the number of expected
operands and process that number of subsequent read()s to determine the
complete MIDI message.
*/
if (InBytes[1] & 0x80) { /* Status Byte */
if (MessageType(InBytes[1]) == MIDI_SYSTEM_MSG)
{
NumArgs = 0; /* no timing info */
#ifdef DEBUG
fprintf(stderr, "SYSTEM MESSAGE\n");
#endif
}
else if (MessageType(InBytes[1]) == MIDI_PGM_CHANGE ||
MessageType(InBytes[1]) == MIDI_CHN_PRESSURE)
{
NumArgs = 1;
}
else
{
NumArgs = 2;
}
newMessage.data[0] = InBytes[1];
ArgsLeft = NumArgs;
newMessage.data[1] = 0;
newMessage.data[2] = 0;
}
if (ArgsLeft && !(InBytes[1] & 0x80)) { /* not a status byte */
if (ArgsLeft == NumArgs)
newMessage.data[1] = InBytes[1];
else
{
newMessage.data[2] = InBytes[1];
}
--ArgsLeft;
/* If MIDI message complete, then setup for running status mode
(another event of the same type without status byte).
*/
if ( !ArgsLeft ) {
if (MessageType(newMessage.data[0]) == (int) MIDI_PGM_CHANGE ||
MessageType(newMessage.data[0]) == (int) MIDI_CHN_PRESSURE)
{
ArgsLeft = 1;
}
else
{
ArgsLeft = 2;
}
newMessage.time = newTime - lastTime;
lastTime = newTime;
// Put newMessage in the circular buffer
midiBuffer[writeOffset] = newMessage;
writeOffset++;
if( writeOffset >= MIDI_BUFFER_SIZE )
writeOffset = 0;
break;
}
}
default:
break;
}
}
}
}
MIDIIO :: MIDIIO()
{
int err = 0;
_seqfd = 0;
#ifdef NONBLOCKING_MIDI
if((_seqfd = open(SEQUENCER_PATH, O_RDONLY+O_NONBLOCK, 0)) == -1) {
#else
if((_seqfd = open(SEQUENCER_PATH, O_RDONLY, 0)) == -1) {
#endif
fprintf(stderr,"Cannot open " SEQUENCER_PATH ". \n");
printf("Exiting MIDIIO Process.\n");
exit(0);
}
// Set up the circular buffer for the Midi Input Messages
midiBuffer = new MIDIMESSAGE[MIDI_BUFFER_SIZE];
readOffset = 0;
writeOffset = 0;
err = pthread_create(&midi_input_thread, NULL, midiInputThread, NULL);
if (err)
{
fprintf(stderr, "Unable to create MIDI input thread.\n");
printf("Exiting MIDIIO Process.\n");
exit(0);
}
}
MIDIIO :: ~MIDIIO()
{
pthread_cancel(midi_input_thread);
if (_seqfd != 0) close(_seqfd);
delete [] midiBuffer;
}
int MIDIIO::nextMessage()
{
MIDIMESSAGE lastEvent;
if ( readOffset == writeOffset ) return 0;
lastEvent = midiBuffer[readOffset];
readOffset++;
if ( readOffset >= MIDI_BUFFER_SIZE ) readOffset = 0;
messageType = (int) (lastEvent.data[0] & 0xf0);
channel = (int) (lastEvent.data[0] & 0x0f);
byteTwo = (float) lastEvent.data[1];
if (messageType == (int) MIDI_PITCH_BEND)
byteTwo = (float) lastEvent.data[2] + (byteTwo * NORM_7);
else
byteThree = (float) lastEvent.data[2];
deltaTime = (float) lastEvent.time / OSS_MIDI_CLOCK_RATE;
return messageType;
}
#elif defined(__OS_Win_)
/*************************************/
/* Windoze MIDI INPUT */
/*************************************/
#include <stdio.h>
#include "MIDIIO.h"
#define MIDI_NOTEON 0x90
#define MIDI_NOTEOFF 0x80
#define MIDI_POLYKEYPRESSURE 0xA0
#define MIDI_CHANNELPRESSURE 0xD0
#define MIDI_PROGRAMCHANGE 0xC0
#define MIDI_CONTROLCHANGE 0xB0
#define MIDI_PITCHBEND 0xE0
typedef struct {
DWORD data;
DWORD time;
} MIDIMESSAGE;
MIDIMESSAGE *midiBuffer;
static void CALLBACK midiInputCallback( HMIDIOUT hmin, UINT inputStatus,
DWORD instancePtr, DWORD midiMessage, DWORD timestamp)
{
MIDIMESSAGE newMessage;
switch (inputStatus) {
case MIM_OPEN:
#ifdef TESTING_MIDI_IN
printf("MIM_OPEN\n");
#endif
break;
case MIM_CLOSE:
#ifdef TESTING_MIDI_IN
printf("MIM_CLOSE\n");
#endif
break;
case MIM_DATA:
#ifdef TESTING_MIDI_IN
printf("MIM_DATA\n");
#endif
// Ignore Active Sensing messages
if ((midiMessage & 0xff) == 0xfe || (midiMessage & 0xff) == 0xf8) {
break;
}
newMessage.data = midiMessage;
newMessage.time = timestamp;
// Put newMessage in the circular buffer
midiBuffer[writeOffset] = newMessage;
writeOffset++;
if( writeOffset >= MIDI_BUFFER_SIZE )
writeOffset = 0;
break;
case MIM_ERROR:
fprintf(stderr,"Invalid MIDI message received!\n");
#ifdef TESTING_MIDI_IN
printf("MIM_ERROR\n");
#endif
break;
case MIM_LONGDATA:
/* System exclusive buffer is returned */
break;
case MIM_LONGERROR:
#ifdef TESTING_MIDI_IN
printf("MIM_LONGERROR\n");
#endif
break;
default:
break;
}
}
HMIDIIN hMidiIn ; // Handle to Midi Output Device
MIDIIO :: MIDIIO()
{
MMRESULT result;
UINT uDeviceID;
MIDIINCAPS deviceCaps;
UINT i;
char inputString[128];
uDeviceID = midiInGetNumDevs();
printf("%i MIDI Input Devices Available.\n",uDeviceID);
if (uDeviceID == 0) {
printf("Exiting MIDIIO Process.\n");
exit(0);
}
for (i=0; i<uDeviceID; i++) {
result = midiInGetDevCaps(i, &deviceCaps, sizeof(MIDIINCAPS));
printf("MIDI Device %d is %s.\n", i, deviceCaps.szPname);
}
if (uDeviceID > 1) {
printf("\nType the MIDI Device to open: ");
fgets(inputString, 128, stdin);
uDeviceID = (UINT) atoi(inputString);
}
else uDeviceID -= 1;
// Open the port and return any errors
result = midiInOpen(&hMidiIn, uDeviceID, (DWORD)&midiInputCallback, (DWORD)NULL, CALLBACK_FUNCTION);
if (result != MMSYSERR_NOERROR) {
fprintf(stderr,"Cannot open MIDI Input Device %d!\n", uDeviceID);
printf("Exiting MIDIIO Process.\n");
exit(0);
}
// Set up the circular buffer for the Midi Input Messages
midiBuffer = new MIDIMESSAGE[MIDI_BUFFER_SIZE];
readOffset = 0;
writeOffset = 0;
midiInStart( hMidiIn );
}
MIDIIO :: ~MIDIIO()
{
midiInReset( hMidiIn );
midiInStop( hMidiIn );
midiInClose( hMidiIn );
delete [] midiBuffer;
}
int MIDIIO :: nextMessage()
{
int status;
int byte1;
int byte2;
MIDIMESSAGE lastEvent;
static DWORD lastTime = 0;
static DWORD newTime = 0;
if ( readOffset == writeOffset ) return 0;
lastEvent = midiBuffer[readOffset];
readOffset++;
if ( readOffset >= MIDI_BUFFER_SIZE ) readOffset = 0;
status = (int) (lastEvent.data & 0xff);
byte1 = (int) (lastEvent.data & 0xff00) >> 8;
byte2 = (int) (lastEvent.data & 0xff0000) >> 16;
channel = (int) (status & 0x0f);
status &= 0xf0; // Clear lower byte of status
newTime = lastEvent.time;
deltaTime = (float) (newTime - lastTime) * 0.001;
lastTime = newTime;
if ((status == MIDI_PROGRAMCHANGE) ||
(status == MIDI_CHANNELPRESSURE))
{
messageType = status;
byteTwo = (float) byte1;
}
else if ((status == MIDI_NOTEON) || (status == MIDI_NOTEOFF) ||
(status == MIDI_CONTROLCHANGE) || (status == MIDI_POLYKEYPRESSURE))
{
messageType = status;
byteTwo = (float) byte1;
byteThree = (float) byte2;
}
else if (status == MIDI_PITCHBEND)
{
messageType = status;
byteTwo = (float) (byte1 * NORM_7);
byteTwo += (float) byte2;
}
else
{
messageType = -1;
}
return messageType;
}
#endif
void MIDIIO :: printMessage()
{
printf("type = %d, channel = %d, byte2 = %f, byte3 = %f\n",
this->getType(), this->getChannel(), this->getByteTwo(),
this->getByteThree());
}
int MIDIIO :: getType()
{
return messageType;
}
int MIDIIO :: getChannel()
{
return channel;
}
MY_FLOAT MIDIIO :: getByteTwo()
{
return byteTwo;
}
MY_FLOAT MIDIIO :: getByteThree()
{
return byteThree;
}
MY_FLOAT MIDIIO :: getDeltaTime()
{
return deltaTime;
}
#endif

View File

@@ -1,56 +0,0 @@
/******************************************/
/* MIDIIO.h */
/* Realtime MIDI I/O Object for STK, */
/* by Gary P. Scavone, 1998. */
/* Based in part on code by Perry */
/* Cook (SGI), Paul Leonard (Linux), */
/* the RoseGarden team (Linux), and */
/* Bill Putnam (Win95/NT). */
/* */
/* At the moment, this object only */
/* handles MIDI Input, though MIDI */
/* Output code can go here when someone */
/* decides they need it (and writes it). */
/* */
/* This object opens a MIDI Input device */
/* and parses MIDI data. Time stamp */
/* info is converted to deltaTime. */
/* MIDI data is stored as MY_FLOAT to */
/* conform with SKINI. */
/******************************************/
#if !defined(__MIDIIO_h)
#define __MIDIIO_h
#include "Object.h"
class MIDIIO : public Object
{
protected:
int messageType;
int channel;
float byteTwo;
float byteThree;
MY_FLOAT deltaTime;
public:
MIDIIO();
~MIDIIO();
void printMessage();
int nextMessage();
int getType();
int getChannel();
MY_FLOAT getByteTwo();
MY_FLOAT getByteThree();
MY_FLOAT getDeltaTime();
};
#if defined(__OS_Win_)
#include <windows.h>
#include <mmsystem.h>
static void CALLBACK midiInputCallback( HMIDIOUT hmin, UINT inputStatus,
DWORD instancePtr, DWORD midiMessage, DWORD timestamp);
#endif
#endif

View File

@@ -1,152 +0,0 @@
/********************************************/
/* Commuted Mandolin Subclass of enhanced */
/* dual plucked-string model */
/* by Perry Cook, 1995-96 */
/* */
/* Controls: CONTROL1 = bodySize */
/* CONTROL2 = pluckPosition */
/* CONTROL3 = loopGain */
/* MOD_WHEEL= deTuning */
/* */
/* Note: Commuted Synthesis, as with many */
/* other WaveGuide techniques, is covered */
/* by patents, granted, pending, and/or */
/* applied-for. Many are assigned to the */
/* Board of Trustees, Stanford University. */
/* For information, contact the Office of */
/* Technology Licensing, Stanford U. */
/********************************************/
#include "Mandolin.h"
#include "SKINI11.msg"
Mandolin :: Mandolin(MY_FLOAT lowestFreq) : Plucked2(lowestFreq)
{
// Concatenate the STK RAWWAVE_PATH to the rawwave file
char temp[128];
strcpy(temp, RAWWAVE_PATH);
soundfile[0] = new RawWvIn(strcat(temp,"rawwaves/mand1.raw"),"oneshot");
strcpy(temp, RAWWAVE_PATH);
soundfile[1] = new RawWvIn(strcat(temp,"rawwaves/mand2.raw"),"oneshot");
strcpy(temp, RAWWAVE_PATH);
soundfile[2] = new RawWvIn(strcat(temp,"rawwaves/mand3.raw"),"oneshot");
strcpy(temp, RAWWAVE_PATH);
soundfile[3] = new RawWvIn(strcat(temp,"rawwaves/mand4.raw"),"oneshot");
strcpy(temp, RAWWAVE_PATH);
soundfile[4] = new RawWvIn(strcat(temp,"rawwaves/mand5.raw"),"oneshot");
strcpy(temp, RAWWAVE_PATH);
soundfile[5] = new RawWvIn(strcat(temp,"rawwaves/mand6.raw"),"oneshot");
strcpy(temp, RAWWAVE_PATH);
soundfile[6] = new RawWvIn(strcat(temp,"rawwaves/mand7.raw"),"oneshot");
strcpy(temp, RAWWAVE_PATH);
soundfile[7] = new RawWvIn(strcat(temp,"rawwaves/mand8.raw"),"oneshot");
strcpy(temp, RAWWAVE_PATH);
soundfile[8] = new RawWvIn(strcat(temp,"rawwaves/mand9.raw"),"oneshot");
strcpy(temp, RAWWAVE_PATH);
soundfile[9] = new RawWvIn(strcat(temp,"rawwaves/mand10.raw"),"oneshot");
strcpy(temp, RAWWAVE_PATH);
soundfile[10] = new RawWvIn(strcat(temp,"rawwaves/mand11.raw"),"oneshot");
strcpy(temp, RAWWAVE_PATH);
soundfile[11] = new RawWvIn(strcat(temp,"rawwaves/mand12.raw"),"oneshot");
directBody = 1.0;
mic = 0;
dampTime = 0;
waveDone = 1;
}
Mandolin :: ~Mandolin()
{
}
void Mandolin :: pluck(MY_FLOAT amplitude)
{ /* this function gets interesting here, */
/* because pluck may be longer than */
/* string length, so we just reset the */
/* soundfile and add in the pluck in */
/* the tick method. */
soundfile[mic]->reset();
pluckAmp = amplitude;
/* Set Pick Position which puts zeroes at pos*length */
combDelay->setDelay((MY_FLOAT) 0.5 * pluckPos * lastLength);
dampTime = (long) lastLength; /* See tick method below */
waveDone = 0;
}
void Mandolin :: pluck(MY_FLOAT amplitude, MY_FLOAT position)
{
pluckPos = position; /* pluck position is zeroes at pos*length */
this->pluck(amplitude);
}
void Mandolin :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
{
this->setFreq(freq);
this->pluck(amp);
#if defined(_debug_)
printf("Mandolin : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
#endif
}
void Mandolin :: setBodySize(MY_FLOAT size)
{
int i;
for (i=0;i<12;i++) {
soundfile[i]->setRate(size);
}
}
MY_FLOAT Mandolin :: tick()
{
MY_FLOAT temp = (MY_FLOAT) 0;
if (!waveDone) {
waveDone = soundfile[mic]->informTick(); /* as long as it goes . . . */
temp = soundfile[mic]->lastOut() * pluckAmp; /* scaled pluck excitation */
temp = temp - combDelay->tick(temp); /* with comb filtering */
}
if (dampTime>=0) { /* Damping hack to help avoid */
dampTime -= 1; /* overflow on replucking */
lastOutput = delayLine->tick( /* Calculate 1st delay */
filter->tick( /* filterered reflection */
temp + /* plus pluck excitation */
(delayLine->lastOut() * (MY_FLOAT) 0.7)));
lastOutput += delayLine2->tick( /* and 2nd delay */
filter2->tick( /* just like the 1st */
temp +
(delayLine2->lastOut() * (MY_FLOAT) 0.7)));
}
else { /* No damping hack after 1 period */
lastOutput = delayLine->tick( /* Calculate 1st delay */
filter->tick( /* filtered reflection */
temp + /* plus pluck excitation */
(delayLine->lastOut() * loopGain)));
lastOutput += delayLine2->tick( /* and 2nd delay */
filter2->tick( /* just like the 1st */
temp +
(delayLine2->lastOut() * loopGain)));
}
lastOutput *= (MY_FLOAT) 0.3 / 32768.0;
return lastOutput;
}
void Mandolin :: controlChange(int number, MY_FLOAT value)
{
#if defined(_debug_)
printf("Mandolin : ControlChange: Number=%i Value=%f\n",number,value);
#endif
if (number == __SK_BodySize_)
this->setBodySize(value * (MY_FLOAT) NORM_7 * (MY_FLOAT) 2.0);
else if (number == __SK_PickPosition_)
this->setPluckPos(value * (MY_FLOAT) NORM_7);
else if (number == __SK_StringDamping_)
this->setBaseLoopGain((MY_FLOAT) 0.97 + (value * (MY_FLOAT) NORM_7 * (MY_FLOAT) 0.03));
else if (number == __SK_StringDetune_)
this->setDetune((MY_FLOAT) 1.0 - (value * (MY_FLOAT) NORM_7 * (MY_FLOAT) 0.1));
else if (number == __SK_AfterTouch_)
this->pluck(value * (MY_FLOAT) NORM_7);
else if (number == 411) {
mic = (int) value % 12;
}
else {
printf("Mandolin : Undefined Control Number!! %i\n",number);
}
}

View File

@@ -1,44 +0,0 @@
/********************************************/
/* Commuted Mandolin Subclass of enhanced */
/* dual plucked-string model */
/* by Perry Cook, 1995-96 */
/* Controls: CONTROL1 = bodySize */
/* CONTROL2 = pluckPosition */
/* CONTROL3 = loopGain */
/* MOD_WHEEL= deTuning */
/* */
/* Note: Commuted Synthesis, as with many */
/* other WaveGuide techniques, is covered */
/* by patents, granted, pending, and/or */
/* applied-for. All are assigned to the */
/* Board of Trustees, Stanford University. */
/* For information, contact the Office of */
/* Technology Licensing, Stanford U. */
/********************************************/
#if !defined(__Mandolin_h)
#define __Mandolin_h
#include "Plucked2.h"
#include "RawWvIn.h"
class Mandolin : public Plucked2
{
protected:
RawWvIn *soundfile[12];
MY_FLOAT directBody;
int mic;
long dampTime;
int waveDone;
public:
Mandolin(MY_FLOAT lowestFreq);
virtual ~Mandolin();
void pluck(MY_FLOAT amplitude);
void pluck(MY_FLOAT amplitude,MY_FLOAT position);
virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp);
void setBodySize(MY_FLOAT size);
virtual void controlChange(int number, MY_FLOAT value);
virtual MY_FLOAT tick();
};
#endif

View File

@@ -1,116 +0,0 @@
/*******************************************/
/* Marimba SubClass of Modal4 Instrument, */
/* by Perry R. Cook, 1995-96 */
/* */
/* Controls: CONTROL1 = stickHardness */
/* CONTROL2 = strikePosition*/
/* CONTROL3 = vibFreq */
/* MOD_WHEEL= vibAmt */
/*******************************************/
#include "Marimba.h"
#include "SKINI11.msg"
Marimba :: Marimba() : Modal4()
{
// Concatenate the STK RAWWAVE_PATH to the rawwave file
char file[128];
strcpy(file, RAWWAVE_PATH);
wave = new RawWvIn(strcat(file,"rawwaves/marmstk1.raw"),"oneshot");
wave->normalize();
wave->setRate((MY_FLOAT) 0.5); /* normal stick */
this->setRatioAndReson(0, (MY_FLOAT) 1.00,(MY_FLOAT) 0.9996); /* Set all 132.0 */
this->setRatioAndReson(1, (MY_FLOAT) 3.99,(MY_FLOAT) 0.9994); /* of our 523.0 */
this->setRatioAndReson(2,(MY_FLOAT) 10.65,(MY_FLOAT) 0.9994); /* default 1405.0 */
this->setRatioAndReson(3,-(MY_FLOAT) 2443.0,(MY_FLOAT) 0.999); /* resonances 2443.0 */
this->setFiltGain(0,(MY_FLOAT) 0.04); /* and */
this->setFiltGain(1,(MY_FLOAT) 0.01); /* gains */
this->setFiltGain(2,(MY_FLOAT) 0.01); /* for each */
this->setFiltGain(3,(MY_FLOAT) 0.008); /* resonance */
directGain = (MY_FLOAT) 0.1;
multiStrike = 0;
}
Marimba :: ~Marimba()
{
delete wave;
}
void Marimba :: setStickHardness(MY_FLOAT hardness)
{
stickHardness = hardness;
wave->setRate((MY_FLOAT) (0.25 * (MY_FLOAT) pow(4.0,stickHardness)));
masterGain = (MY_FLOAT) 0.1 + ((MY_FLOAT) 1.8 * stickHardness);
}
void Marimba :: setStrikePosition(MY_FLOAT position)
{
MY_FLOAT temp,temp2;
temp2 = position * PI;
strikePosition = position; /* Hack only first three modes */
temp = (MY_FLOAT) sin(temp2);
this->setFiltGain(0,(MY_FLOAT) 0.12 * temp); /* 1st mode function of pos. */
temp = (MY_FLOAT) sin(0.05 + (3.9 * temp2));
this->setFiltGain(1,(MY_FLOAT) -0.03 * temp); /* 2nd mode function of pos. */
temp = (MY_FLOAT) sin(-0.05 + (11 * temp2));
this->setFiltGain(2,(MY_FLOAT) 0.11 * temp); /* 3rd mode function of pos. */
}
void Marimba :: setModulationSpeed(MY_FLOAT mSpeed)
{
/* don't bother here, marimba decay so fast, mod doesn't make sense */
}
void Marimba :: setModulationDepth(MY_FLOAT mDepth)
{
}
void Marimba :: strike(MY_FLOAT amplitude)
{
int temp;
temp = rand() >> 10;
if (temp < 2) {
multiStrike = 1;
#if defined(_debug_)
printf("striking twice here!!\n");
#endif
}
else if (temp < 1) {
multiStrike = 2;
#if defined(_debug_)
printf("striking three times here!!!\n");
#endif
}
else multiStrike = 0;
Modal4::strike(amplitude);
}
void Marimba :: controlChange(int number, MY_FLOAT value)
{
#if defined(_debug_)
printf("Marimba : ControlChange: Number=%i Value=%f\n",number,value);
#endif
if (number == __SK_StickHardness_)
this->setStickHardness(value * NORM_7);
else if (number == __SK_StrikePosition_)
this->setStrikePosition(value * NORM_7);
else if (number == __SK_ModFrequency_)
vibr->setFreq((value * NORM_7 * (MY_FLOAT) 12.0));
else if (number == __SK_ModWheel_)
vibrGain = (value * NORM_7);
else if (number == __SK_AfterTouch_Cont_)
this->strike(value * NORM_7);
else {
printf("Marimba : Undefined Control Number!!\n");
}
}
MY_FLOAT Marimba :: tick()
{
if (multiStrike>0)
if (wave->isFinished()) {
wave->reset();
multiStrike -= 1;
}
return Modal4::tick();
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,44 +0,0 @@
/*******************************************/
/* Matlab MAT-file Output Class, */
/* by Gary P. Scavone, 1999. */
/* This object creates a Matlab MAT-file */
/* structure with a numeric array */
/* subelement and fills it with buffers */
/* of samples (doubles). */
/* */
/* When originally created, the Matlab */
/* MAT-file format was not public and I */
/* had to reverse-engineer the format. */
/* Matlab finally released the format in */
/* the Spring of 1999, and this class was */
/* updated to more closely adhere to */
/* specifications. */
/*******************************************/
#include "Object.h"
#include "WvOut.h"
#if !defined(__MatWvOut_h)
#define __MatWvOut_h
#define MAT_BUFFER_SIZE 1024
class MatWvOut : public WvOut
{
protected:
FILE *fd;
double data[MAT_BUFFER_SIZE]; /* not MY_FLOAT because MAT-file uses doubles */
INT32 counter;
INT32 totalCount;
int channels;
public:
MatWvOut(char *infileName);
MatWvOut(int chans, char *infileName);
~MatWvOut();
INT32 getCounter();
MY_FLOAT getTime();
void tick(MY_FLOAT sample);
void mtick(MY_MULTI samples);
};
#endif // defined(__MatWvOut_h)

View File

@@ -1,189 +0,0 @@
/*******************************************/
/* 4 Resonance Modal Synthesis Instrument */
/* by Perry R. Cook, 1995-96 */
/* This instrument contains an excitation */
/* wavetable, an envelope, and four reso- */
/* nances (Non-Sweeping BiQuad Filters). */
/*******************************************/
#include "Modal4.h"
Modal4 :: Modal4()
{
envelope = new Envelope;
// We don't make the excitation wave here yet,
// because we don't know what it's going to be.
filters[0] = new BiQuad;
filters[1] = new BiQuad;
filters[2] = new BiQuad;
filters[3] = new BiQuad;
onepole = new OnePole;
// Concatenate the STK RAWWAVE_PATH to the rawwave file
char file[128];
strcpy(file, RAWWAVE_PATH);
vibr = new RawWvIn(strcat(file,"rawwaves/sinewave.raw"),"looping");
vibr->normalize();
vibr->setFreq((MY_FLOAT) 6.0);
vibrGain = (MY_FLOAT) 0.05;
directGain = (MY_FLOAT) 0.0;
masterGain = (MY_FLOAT) 1.0;
baseFreq = (MY_FLOAT) 440.0;
this->setRatioAndReson(0,(MY_FLOAT) 1.00,(MY_FLOAT) 0.9997); /* Set some */
this->setRatioAndReson(1,(MY_FLOAT) 1.30,(MY_FLOAT) 0.9997); /* silly */
this->setRatioAndReson(2,(MY_FLOAT) 1.77,(MY_FLOAT) 0.9997); /* default */
this->setRatioAndReson(3,(MY_FLOAT) 2.37,(MY_FLOAT) 0.9997); /* values here */
this->setFiltGain(0,(MY_FLOAT) 0.01);
this->setFiltGain(1,(MY_FLOAT) 0.01);
this->setFiltGain(2,(MY_FLOAT) 0.01);
this->setFiltGain(3,(MY_FLOAT) 0.01);
this->clear();
filters[0]->setEqualGainZeroes();
filters[1]->setEqualGainZeroes();
filters[2]->setEqualGainZeroes();
filters[3]->setEqualGainZeroes();
stickHardness = (MY_FLOAT) 0.5;
strikePosition = (MY_FLOAT) 0.561;
}
Modal4 :: ~Modal4()
{
delete envelope;
delete filters[0];
delete filters[1];
delete filters[2];
delete filters[3];
delete onepole;
delete vibr;
}
void Modal4 :: clear()
{
onepole->clear();
filters[0]->clear();
filters[1]->clear();
filters[2]->clear();
filters[3]->clear();
}
void Modal4 :: setFreq(MY_FLOAT frequency)
{
baseFreq = frequency;
this->setRatioAndReson(0,ratios[0],resons[0]);
this->setRatioAndReson(1,ratios[1],resons[1]);
this->setRatioAndReson(2,ratios[2],resons[2]);
this->setRatioAndReson(3,ratios[3],resons[3]);
}
#include <stdio.h>
void Modal4 :: setRatioAndReson(int whichOne, MY_FLOAT ratio,MY_FLOAT reson)
{
MY_FLOAT temp;
if (ratio*baseFreq < SRATE_OVER_TWO) {
ratios[whichOne] = ratio;
}
else {
temp = ratio;
while (temp*baseFreq > SRATE_OVER_TWO) temp *= (MY_FLOAT) 0.5;
ratios[whichOne] = temp;
#if defined(_debug_)
printf("Modal4 : Aliasing would occur here, correcting.\n");
#endif
}
resons[whichOne] = reson;
if (ratio<0)
temp = -ratio;
else
temp = ratio*baseFreq;
filters[whichOne]->setFreqAndReson(temp,reson);
}
void Modal4 :: setMasterGain(MY_FLOAT aGain)
{
masterGain = aGain;
}
void Modal4 :: setDirectGain(MY_FLOAT aGain)
{
directGain = aGain;
}
void Modal4 :: setFiltGain(int whichOne, MY_FLOAT gain)
{
filters[whichOne]->setGain(gain);
}
void Modal4 :: strike(MY_FLOAT amplitude)
{
int i;
MY_FLOAT temp;
envelope->setRate((MY_FLOAT) 1.0);
envelope->setTarget(amplitude);
onepole->setPole((MY_FLOAT) 1.0 - amplitude);
envelope->tick();
wave->reset();
for (i=0;i<4;i++) {
if (ratios[i] < 0)
temp = -ratios[i];
else
temp = ratios[i] * baseFreq;
filters[i]->setFreqAndReson(temp,resons[i]);
}
}
void Modal4 :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
{
this->strike(amp);
this->setFreq(freq);
#if defined(_debug_)
printf("Modal4 : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
#endif
}
void Modal4 :: noteOff(MY_FLOAT amp) /* This calls damp, but inverts the */
{ /* meaning of amplitude. */
this->damp((MY_FLOAT) 1.0 - (amp * (MY_FLOAT) 0.03)); /* (high amplitude means fast damping) */
#if defined(_debug_)
printf("Modal4 : NoteOff: Amp=%lf\n",amp);
#endif
}
void Modal4 :: damp(MY_FLOAT amplitude)
{
int i;
MY_FLOAT temp;
for (i=0;i<4;i++) {
if (ratios[i] < 0)
temp = -ratios[i];
else
temp = ratios[i] * baseFreq;
filters[i]->setFreqAndReson(temp,resons[i]*amplitude);
}
}
void Modal4 :: controlChange(int number, MY_FLOAT value)
{
}
MY_FLOAT Modal4 :: tick()
{
MY_FLOAT temp,temp2;
temp = masterGain * onepole->tick(wave->tick() * envelope->tick());
temp2 = filters[0]->tick(temp);
temp2 += filters[1]->tick(temp);
temp2 += filters[2]->tick(temp);
temp2 += filters[3]->tick(temp);
temp2 = temp2 - (temp2 * directGain);
temp2 += directGain * temp;
if (vibrGain != 0.0) {
temp = (MY_FLOAT) 1.0 + (vibr->tick() * vibrGain); /* Calculate AM */
temp2 = temp * temp2; /* and apply to master out */
}
lastOutput = temp2 * (MY_FLOAT) 2.0;
return lastOutput;
}

View File

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

View File

@@ -1,86 +0,0 @@
/*******************************************/
/* Modulator Class, Perry R. Cook, 1995-96*/
/* This Object combines random and */
/* periodic modulations to give a nice */
/* natural human modulation function. */
/*******************************************/
#define POLE_POS (MY_FLOAT) 0.999
#define RND_SCALE (MY_FLOAT) 10.0
#include "Modulatr.h"
Modulatr :: Modulatr()
{
// Concatenate the STK RAWWAVE_PATH to the rawwave file
char file[128];
strcpy(file, RAWWAVE_PATH);
vibwave = new RawWvIn(strcat(file,"rawwaves/sinewave.raw"),"looping");
vibwave->normalize();
vibwave->setFreq((MY_FLOAT) 6.0);
vibAmt = (MY_FLOAT) 0.04;
noise = new SubNoise(330);
rndAmt = (MY_FLOAT) 0.005;
onepole = new OnePole;
onepole->setPole(POLE_POS);
onepole->setGain(rndAmt * RND_SCALE);
}
Modulatr :: ~Modulatr()
{
delete vibwave;
delete noise;
delete onepole;
}
void Modulatr :: reset()
{
lastOutput = (MY_FLOAT) 0.0;
}
void Modulatr :: setVibFreq(MY_FLOAT vibFreq)
{
vibwave->setFreq(vibFreq);
}
void Modulatr :: setVibAmt(MY_FLOAT vibAmount)
{
vibAmt = vibAmount;
}
void Modulatr :: setRndAmt(MY_FLOAT rndAmount)
{
rndAmt = rndAmount;
onepole->setGain(RND_SCALE * rndAmt);
}
MY_FLOAT Modulatr :: tick()
{
lastOutput = vibAmt * vibwave->tick(); /* Compute periodic and */
lastOutput += onepole->tick(noise->tick()); /* random modulations */
return lastOutput;
}
MY_FLOAT Modulatr :: lastOut()
{
return lastOutput;
}
/************ Test Main Program *****************/
/*
void main()
{
Modulatr testMod;
FILE *fd;
short data;
long i;
fd = fopen("test.raw","wb");
for (i=0;i<20000;i++) {
data = testMod.tick() * 32000.0;
fwrite(&data,2,1,fd);
}
fclose(fd);
}
*/

View File

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

View File

@@ -1,114 +0,0 @@
/******************************************/
/* Test Sampler Subclass of */
/* Sampling Synthesizer Class */
/* by Perry R. Cook, 1995-96 */
/* */
/* Controls: CONTROL1 = filterQ */
/* CONTROL2 = filterRate */
/* CONTROL3 = vibFreq */
/* MOD_WHEEL= vibAmt */
/******************************************/
#include "Moog1.h"
#include "SKINI11.msg"
Moog1 :: Moog1() : SamplFlt()
{
// Concatenate the STK RAWWAVE_PATH to the rawwave file
char temp[128];
char file[128];
strcpy(temp, RAWWAVE_PATH);
strcpy(file,temp);
attacks[0] = new RawWvIn(strcat(file,"rawwaves/mandpluk.raw"),"oneshot");
strcpy(file,temp);
loops[0] = new RawWvIn(strcat(file,"rawwaves/impuls20.raw"),"looping");
strcpy(file,temp);
loops[1] = new RawWvIn(strcat(file,"rawwaves/sinewave.raw"),"looping"); /* Steal one for vibrato */
attacks[0]->normalize();
loops[0]->normalize();
loops[1]->normalize();
loops[1]->setFreq((MY_FLOAT) 6.122);
adsr->setAllTimes((MY_FLOAT) 0.001,(MY_FLOAT) 1.5,(MY_FLOAT) 0.6,(MY_FLOAT) 0.250);
filterQ = (MY_FLOAT) 0.85;
filterRate = (MY_FLOAT) 0.0001;
modDepth = (MY_FLOAT) 0.0;
}
Moog1 :: ~Moog1()
{
delete attacks[0];
delete loops[0];
delete loops[1];
}
void Moog1 :: setFreq(MY_FLOAT frequency)
{
baseFreq = frequency;
attacks[0]->setFreq(baseFreq * (MY_FLOAT) 0.01);
loops[0]->setFreq(baseFreq);
}
void Moog1 :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
{
MY_FLOAT temp;
this->setFreq(freq);
this->keyOn();
attackGain = amp * (MY_FLOAT) 0.5;
loopGain = amp;
temp = filterQ + (MY_FLOAT) 0.05;
filters[0]->setStates((MY_FLOAT) 2000.0,temp,(MY_FLOAT) 2.0 * ((MY_FLOAT) 1.0 - temp));
filters[1]->setStates((MY_FLOAT) 2000.0,temp,(MY_FLOAT) 2.0 * ((MY_FLOAT) 1.0 - temp));
temp = filterQ + (MY_FLOAT) 0.099;
filters[0]->setTargets((MY_FLOAT) freq,temp,(MY_FLOAT) 2.0 * ((MY_FLOAT) 1.0 - temp));
filters[1]->setTargets((MY_FLOAT) freq,temp,(MY_FLOAT) 2.0 * ((MY_FLOAT) 1.0 - temp));
filters[0]->setSweepRate(filterRate * (MY_FLOAT) 22050.0 / SRATE);
filters[1]->setSweepRate(filterRate * (MY_FLOAT) 22050.0 / SRATE);
#if defined(_debug_)
printf("Moog1 : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
#endif
}
void Moog1 :: setModulationSpeed(MY_FLOAT mSpeed)
{
loops[1]->setFreq(mSpeed);
}
void Moog1 :: setModulationDepth(MY_FLOAT mDepth)
{
modDepth = mDepth * (MY_FLOAT) 0.5;
}
void Moog1 :: controlChange(int number, MY_FLOAT value)
{
#if defined(_debug_)
printf("Moog1 : ControlChange: Number=%i Value=%f\n",number,value);
#endif
if (number == __SK_FilterQ_)
filterQ = (MY_FLOAT) 0.80 + ((MY_FLOAT) 0.1 * value * NORM_7);
else if (number == __SK_FilterSweepRate_)
filterRate = (value * NORM_7 * (MY_FLOAT) 0.0002);
else if (number == __SK_ModFrequency_)
this->setModulationSpeed(value * NORM_7 * (MY_FLOAT) 12.0);
else if (number == __SK_ModWheel_)
this->setModulationDepth(value * NORM_7);
else if (number == __SK_AfterTouch_Cont_)
adsr->setTarget(value * NORM_7);
else {
printf("Moog1 : Undefined Control Number!!\n");
}
}
MY_FLOAT Moog1 :: tick()
{
MY_FLOAT temp;
if (modDepth!=0.0) {
temp = loops[1]->tick() * modDepth;
loops[0]->setFreq(baseFreq * ((MY_FLOAT) 1.0 + temp));
}
lastOutput = SamplFlt :: tick();
return lastOutput;
}

View File

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

View File

@@ -1,140 +0,0 @@
/******************************************/
/* NRev Reverb Subclass */
/* by Tim Stilson, 1998 */
/* based on CLM NRev */
/* Integrated into STK by Gary Scavone */
/* */
/* This is based on some of the famous */
/* Stanford CCRMA reverbs (NRev, KipRev) */
/* all based on the the Chowning/Moorer/ */
/* Schroeder reverberators, which use */
/* networks of simple allpass and comb */
/* delay filters. This particular */
/* arrangement consists of 6 comb */
/* filters in parallel, followed by 3 */
/* allpass filters, a lowpass filter, */
/* and another allpass in series, */
/* followed by two allpass filters in */
/* parallel with corresponding right and */
/* left outputs. */
/******************************************/
#include "NRev.h"
NRev :: NRev(MY_FLOAT T60)
{
int lens[15]={1433,1601,1867,2053,2251,2399,347,113,37,59,53,43,37,29,19};
double srscale= SRATE / 25641.0;
int val;
int i;
for (i=0; i<15; i++)
{
val = (int)floor(srscale*lens[i]);
if ((val & 1) == 0) val++;
while (!this->isprime(val)) val+=2;
lens[i]=val;
}
for (i=0; i<6; i++)
{
CdelayLine[i] = new DLineN((long) (lens[i]) + 2);
CdelayLine[i]->setDelay((long) (lens[i]));
combCoef[i] = pow(10,(-3 * lens[i] / (T60 * SRATE)));
}
for (i=0; i<8; i++)
{
APdelayLine[i] = new DLineN((long) (lens[i+6]) + 2);
APdelayLine[i]->setDelay((long) (lens[i+6]));
}
allPassCoeff = 0.7;
effectMix = 0.3;
this->clear();
}
NRev :: ~NRev()
{
int i;
for (i=0; i<6; i++) delete CdelayLine[i];
for (i=0; i<8; i++) delete APdelayLine[i];
}
void NRev :: clear()
{
int i;
for (i=0; i<6; i++) CdelayLine[i]->clear();
for (i=0; i<8; i++) APdelayLine[i]->clear();
lastOutL = 0.0;
lastOutR = 0.0;
lpLastout = 0.0;
}
void NRev :: setEffectMix(MY_FLOAT mix)
{
effectMix = mix;
}
MY_FLOAT NRev :: lastOutput()
{
return (lastOutL + lastOutR) * 0.5;
}
MY_FLOAT NRev :: lastOutputL()
{
return lastOutL;
}
MY_FLOAT NRev :: lastOutputR()
{
return lastOutR;
}
MY_FLOAT NRev :: tick(MY_FLOAT input)
{
// FPU underflow checks seem to make things much
// worse here, so I won't do them.
MY_FLOAT temp,temp0,temp1,temp2,temp3;
int i;
temp0 = 0.0;
for (i=0; i<6; i++)
{
temp = input + (combCoef[i] * CdelayLine[i]->lastOut());
temp0 += CdelayLine[i]->tick(temp);
}
for (i=0; i<3; i++)
{
temp = APdelayLine[i]->lastOut();
temp1 = allPassCoeff * temp;
temp1 += temp0;
APdelayLine[i]->tick(temp1);
temp0 = -(allPassCoeff * temp1) + temp;
}
lpLastout = 0.7*lpLastout + 0.3*temp0; // onepole LP filter
temp = APdelayLine[3]->lastOut();
temp1 = allPassCoeff * temp;
temp1 += lpLastout;
APdelayLine[3]->tick(temp1);
temp1 = -(allPassCoeff * temp1) + temp;
temp = APdelayLine[4]->lastOut();
temp2 = allPassCoeff * temp;
temp2 += temp1;
APdelayLine[4]->tick(temp2);
lastOutL = effectMix*(-(allPassCoeff * temp2) + temp);
temp = APdelayLine[5]->lastOut();
temp3 = allPassCoeff * temp;
temp3 += temp1;
APdelayLine[5]->tick(temp3);
lastOutR = effectMix*(-(allPassCoeff * temp3) + temp);
temp = (1.0 - effectMix) * input;
lastOutL += temp;
lastOutR += temp;
return (lastOutL + lastOutR) * 0.5;
}

View File

@@ -1,52 +0,0 @@
/******************************************/
/* NRev Reverb Subclass */
/* by Tim Stilson, 1998 */
/* based on CLM NRev */
/* Integrated into STK by Gary Scavone */
/* */
/* This is based on some of the famous */
/* Stanford CCRMA reverbs (NRev, KipRev) */
/* all based on the the Chowning/Moorer/ */
/* Schroeder reverberators, which use */
/* networks of simple allpass and comb */
/* delay filters. This particular */
/* arrangement consists of 6 comb */
/* filters in parallel, followed by 3 */
/* allpass filters, a lowpass filter, */
/* and another allpass in series, */
/* followed by two allpass filters in */
/* parallel with corresponding right and */
/* left outputs. */
/******************************************/
#if !defined(__NRev_h)
#define __NRev_h
#include "Object.h"
#include "Reverb.h"
#include "DLineN.h"
class NRev : public Reverb
{
protected:
DLineN *APdelayLine[8];
DLineN *CdelayLine[6];
MY_FLOAT allPassCoeff;
MY_FLOAT combCoef[6];
MY_FLOAT lpLastout;
MY_FLOAT lastOutL;
MY_FLOAT lastOutR;
MY_FLOAT effectMix;
public:
NRev(MY_FLOAT T60);
~NRev();
void clear();
void setEffectMix(MY_FLOAT mix);
MY_FLOAT lastOutput();
MY_FLOAT lastOutputL();
MY_FLOAT lastOutputR();
MY_FLOAT tick(MY_FLOAT input);
};
#endif

View File

@@ -1,37 +0,0 @@
/*******************************************/
/* Noise Generator Class, */
/* by Perry R. Cook, 1995-96 */
/* White noise as often as you like. */
/*******************************************/
#include "Noise.h"
#ifdef __OS_NeXT_
#include <libc.h>
#endif
Noise :: Noise() : Object()
{
lastOutput = (MY_FLOAT) 0.0;
}
Noise :: ~Noise()
{
}
MY_FLOAT Noise :: tick()
{
#if defined(__OS_Win_) /* For Windoze */
lastOutput = (MY_FLOAT) (rand() - (int)RANDLIMIT_OVER_TWO);
#else /* This is for Linux, NeXT and SGI */
lastOutput = (MY_FLOAT) (random() - (int)RANDLIMIT_OVER_TWO);
#endif
lastOutput *= (MY_FLOAT) ONE_OVER_RANDLIMIT;
return lastOutput;
}
MY_FLOAT Noise :: lastOut()
{
return lastOutput;
}

View File

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

View File

@@ -1,23 +0,0 @@
/*******************************************/
/* Object Class, by Perry R. Cook, 1995-96*/
/* This is mostly here for compatibility */
/* with Objective C. We'll also stick */
/* global defines here, so everyone will */
/* see them. */
/*******************************************/
#include "Object.h"
// #include "byteswap.c"
/* This is just here for compatibility and convenience,
so there's no need to do any real calculations.
I do set up some redefinable variables here. */
Object :: Object()
{
}
Object :: ~Object()
{
}

View File

@@ -1,155 +0,0 @@
/*********************************************/
/* Object Class, by Perry R. Cook, 1995-99 */
/* */
/* This is mostly here for compatibility */
/* with Objective C. We'll also stick */
/* global defines here, so everyone will */
/* see them. */
/*********************************************/
#if !defined(__Object_h)
#define __Object_h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
class Object
{
public:
protected:
Object();
virtual ~Object();
};
/* The OS type definitions are made in the Makefile */
#if defined(__OS_NeXT_) /* For NeXTStep - Black or White Hardware */
#define RANDLIMIT 2147483647
#elif defined(__OS_IRIX_) /* For SGI */
#define __STK_REALTIME_
#define RANDLIMIT 2147483647
#elif defined(__OS_Linux_) /* For Linux */
#define __STK_REALTIME_
#define __OSS_API_ /* Use OSS API */
#define __LITTLE_ENDIAN__
#define RANDLIMIT 2147483647
#elif defined(__OS_Win_) /* For WindowsXX or NT */
#define __STK_REALTIME_
#define __WINDS_API_ /* For DirectSound API */
// #define __WINMM_API_ /* For Win MM API */
#define __LITTLE_ENDIAN__
#define RANDLIMIT 32767
#endif
/* Real-time audio input and output buffer size. The value of
* this buffer should be an integer multiple of the number of
* channels your application plans to support, in order that
* multi-channel data is not split across multiple buffers. If
* clicks are occuring in the input or output sound stream, a
* larger buffer size may help. Larger buffer sizes, however,
* produce more latency between input and output.
*
* NOTE FOR WINDOZE USERS: Given inherent delays in the audio
* input and output mechanism under Windoze, there is a trade-off
* between smoothness of fast SKINI parameter updates and input/output
* latency as discussed above. You can use buffer sizes as low
* as 100 (maybe lower) for delay critical applications, but in
* this case SKINI parameter updates will be clumped together
* and sound unnatural. If you want smoother parameter updates
* and you can live with more delay, try using buffer sizes
* closer to 1000. If you need smooth parameter updates AND
* low delay, don't use Windoze!
*/
#define RT_BUFFER_SIZE 256
/* This sets the maximum number of simultaneous
* (within a buffer) MIDI messages that can be
* serviced before messages begin to be lost or
* overwritten. It should be a function of
* RT_BUFFER_SIZE
*/
#define MAX_IN_STRINGS 25
/* The following definition is concatenated to the
* beginning of all references to rawwave files in
* the various STK core classes (ex. Clarinet.cpp).
* If you wish to move the rawwaves directory to a
* different location in your file system, you will
* need to set this path definition appropriately.
* The current definition is a relative reference
* that will work "out of the box" for the STK
* distribution.
*/
#define RAWWAVE_PATH "../"
/* Sampling Rate */
#define SRATE (MY_FLOAT) 22050.0
/* Other SRATE derived defines */
#define SRATE_OVER_TWO (MY_FLOAT) (SRATE / 2)
#define ONE_OVER_SRATE (MY_FLOAT) (1 / SRATE)
#define TWO_PI_OVER_SRATE (MY_FLOAT) (2 * PI / SRATE)
/* Yer Basic Trigonometric constants */
#if !defined(PI)
#define PI (MY_FLOAT) 3.14159265359
#endif
#define TWO_PI (MY_FLOAT) 6.28318530718
#define ONE_OVER_TWO_PI (MY_FLOAT) 0.15915494309
#define SQRT_TWO 1.414213562
/* Useful random number generator values */
#define ONE_OVER_RANDLIMIT (1.0/RANDLIMIT)
#define RANDLIMIT_OVER_TWO (int)(RANDLIMIT/2)
/* FPU Underflow Limit
* The IEEE specification doesn't call for automatic
* zeroing of floating-point values when they reach
* their numerical limits. Instead, most processors
* switch to a much more computation-intensive mode
* when a FPU underflow occurs. We set a lower limit
* here for our own (not so efficient) checks. Here's
* a useful macro for limiting MY_FLOATs. At this time,
* no FPU underflow checks are being performed.
*/
#define FPU_UFLOW_LIMIT 0.0000000001
#define LIMIT_MY_FLOAT(j) ((((j)<(MY_FLOAT)FPU_UFLOW_LIMIT)&&((j)>(MY_FLOAT)-FPU_UFLOW_LIMIT))?(MY_FLOAT)0.0:(j))
/* States for Envelopes, etc. */
#define ATTACK 0
#define DECAY 1
#define SUSTAIN 2
#define RELEASE 3
/* Machine dependent stuff, possibly useful for optimization.
* For example, changing double to float here increases
* performance (speed) by a whopping 4-6% on 486-flavor machines.
* BUT!! a change from float to double here increases speed by
* 30% or so on SGI machines.
*/
#define MY_FLOAT double
//#define MY_FLOAT float
/* MY_MULTI is just a pointer to MY_FLOAT. This type is used
* to pass multichannel data back and forth within STK.
*/
typedef MY_FLOAT *MY_MULTI;
/* INT16 is just that ... a 16-bit signed integer. */
typedef signed short INT16;
/* INT32 is just that ... a 32-bit signed integer. */
typedef signed long INT32;
/* Debugging define, causes massive printf's to come out.
* Also enables timing calculations in WaveOut class, other stuff.
* Uncomment to enable.
*/
//#define _debug_ 1
/* MIDI definitions */
#define NORM_7 (MY_FLOAT) 0.0078125 /* this is 1/128 */
#endif

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,113 +0,0 @@
/*******************************************/
/* PRCRev, a simple reverb unit */
/* by Perry Cook, 1996. */
/* Incorporated into the Reverb superclass */
/* by Gary Scavone, 1998. */
/* */
/* This is based on some of the famous */
/* Stanford CCRMA reverbs (NRev, KipRev) */
/* all based on the the Chowning/Moorer/ */
/* Schroeder reverberators, which use */
/* networks of simple allpass and comb */
/* delay filters. This particular */
/* structure consists of 2 allpass units */
/* in series followed by 2 comb filters in */
/* parallel. */
/*******************************************/
#include "PRCRev.h"
PRCRev :: PRCRev(MY_FLOAT T60)
{
int lens[4]={353,1097,1777,2137};
double srscale = SRATE / 44100.0;
int val, i;
if (SRATE < 44100.0) {
for (i=0; i<4; i++) {
val = (int) floor(srscale * lens[i]);
if ((val & 1) == 0) val++;
while (!this->isprime(val)) val += 2;
lens[i] = val;
}
}
for (i=0; i<2; i++)
{
APdelayLine[i] = new DLineN(lens[i] + 2);
APdelayLine[i]->setDelay(lens[i]);
CdelayLine[i] = new DLineN(lens[i+2] + 2);
CdelayLine[i]->setDelay(lens[i+2]);
combCoeff[i] = pow(10,(-3 * lens[i+2] / (T60 * SRATE)));
}
allPassCoeff = (MY_FLOAT) 0.7;
effectMix = (MY_FLOAT) 0.5;
this->clear();
}
PRCRev :: ~PRCRev()
{
delete APdelayLine[0];
delete APdelayLine[1];
delete CdelayLine[0];
delete CdelayLine[1];
}
void PRCRev :: clear()
{
APdelayLine[0]->clear();
APdelayLine[1]->clear();
CdelayLine[0]->clear();
CdelayLine[1]->clear();
lastOutL = (MY_FLOAT) 0.0;
lastOutR = (MY_FLOAT) 0.0;
}
void PRCRev :: setEffectMix(MY_FLOAT mix)
{
effectMix = mix;
}
MY_FLOAT PRCRev :: lastOutput()
{
return (lastOutL + lastOutR) * (MY_FLOAT) 0.5;
}
MY_FLOAT PRCRev :: lastOutputL()
{
return lastOutL;
}
MY_FLOAT PRCRev :: lastOutputR()
{
return lastOutR;
}
MY_FLOAT PRCRev :: tick(MY_FLOAT input)
{
MY_FLOAT temp,temp0,temp1,temp2,temp3;
temp = APdelayLine[0]->lastOut();
temp0 = allPassCoeff * temp;
temp0 += input;
APdelayLine[0]->tick(temp0);
temp0 = -(allPassCoeff * temp0) + temp;
temp = APdelayLine[1]->lastOut();
temp1 = allPassCoeff * temp;
temp1 += temp0;
APdelayLine[1]->tick(temp1);
temp1 = -(allPassCoeff * temp1) + temp;
temp2 = temp1 + (combCoeff[0] * CdelayLine[0]->lastOut());
temp3 = temp1 + (combCoeff[1] * CdelayLine[1]->lastOut());
lastOutL = effectMix * (CdelayLine[0]->tick(temp2));
lastOutR = effectMix * (CdelayLine[1]->tick(temp3));
temp = (MY_FLOAT) (1.0 - effectMix) * input;
lastOutL += temp;
lastOutR += temp;
return (lastOutL + lastOutR) * (MY_FLOAT) 0.5;
}

View File

@@ -1,43 +0,0 @@
/*******************************************/
/* PRCRev, a simple reverb unit */
/* by Perry Cook, 1996. */
/* Incorporated into the Reverb superclass */
/* by Gary Scavone, 1998. */
/* */
/* This is based on some of the famous */
/* Stanford CCRMA reverbs (NRev, KipRev) */
/* all based on the the Chowning/Moorer/ */
/* Schroeder reverberators, which use */
/* networks of simple allpass and comb */
/* delay filters. */
/*******************************************/
#if !defined(__PRCRev_h)
#define __PRCRev_h
#include "Reverb.h"
#include "DLineN.h"
class PRCRev : public Reverb
{
protected:
DLineN *APdelayLine[2];
DLineN *CdelayLine[2];
MY_FLOAT allPassCoeff;
MY_FLOAT combCoeff[2];
MY_FLOAT lastOutL;
MY_FLOAT lastOutR;
MY_FLOAT effectMix;
public:
PRCRev(MY_FLOAT T60);
~PRCRev();
void clear();
void setEffectMix(MY_FLOAT mix);
MY_FLOAT lastOutput();
MY_FLOAT lastOutputL();
MY_FLOAT lastOutputR();
MY_FLOAT tick(MY_FLOAT input);
};
#endif

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