119 Commits
4.1.3 ... 4.5.0

Author SHA1 Message Date
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
420 changed files with 67597 additions and 29332 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/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

41
INSTALL
View File

@@ -1,41 +0,0 @@
The Synthesis ToolKit in C++ (STK)
By Perry R. Cook and Gary P. Scavone, 1995-2004.
The Synthesis ToolKit in C++ can be used in a variety of ways, depending on your particular needs. Some people just choose the classes they need for a particular project and copy those to their project directory. Others like to compile and link to a library of object files. STK was not designed with one particular style of use in mind.
To configure and compile (on Unix systems):
1. Unpack the STK distribution (tar -xzf stk-4.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 (linux only)
--with-jack = choose native JACK server API support (linux only)
--enable-midiator = enable native MS-124W MIDI support (linux only)
At the moment, it is not possible to specify more than one Linux audio API, though this will change in the next release. Typing "./configure --help" will display all the available options. In addition, it is possible to specify the RAWWAVES and INCLUDE paths to configure as (ex. to set to /home/gary/rawwaves and /home/gary/include):
./configure RAWWAVE_PATH="/home/gary/rawwaves/"
./configure INCLUDE_PATH="/home/gary/include/"
The ending "/" is required for the RAWWAVES path. The default behavior will set a relative path that works for the project files included with the distribution (assuming they are not moved). You can also change the RAWWAVE_PATH dynamically via the static Stk::setRawwavePath() function.
If you wish to use a different compiler than that selected by configure, specify that compiler in the command line (ex. to use CC):
./configure CXX=CC
In addition, a linux RPM is available from the STK WWW site (http://www-ccrma.stanford.edu/software/stk/).
For Windows Users:
An STK distribution is available which contains precompiled executables. In addition, Visual C++ project files are included for each of the example STK projects.

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

27
LICENSE Normal file
View File

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

117
README
View File

@@ -1,117 +0,0 @@
The Synthesis ToolKit in C++ (STK)
By Perry R. Cook and Gary P. Scavone, 1995-2004.
This distribution of the Synthesis ToolKit in C++ (STK) contains the following:
include: STK class header files
src: STK class source files
rawwaves: STK audio files (1-channel, 16-bit, big-endian)
doc: STK documentation
projects: example STK programs
Please read the Legal and Ethical notes near the bottom of this document.
For compiling and installing STK, see the INSTALL file in this directory.
OVERVIEW:
The Synthesis ToolKit in C++ (STK) is a set of open source audio signal processing and algorithmic synthesis classes written in C++. STK was designed to facilitate rapid development of music synthesis and audio processing software, with an emphasis on cross-platform functionality, realtime control, ease of use, and educational example code. The Synthesis ToolKit is extremely portable (it's mostly platform-independent C and C++ code), and it's completely user-extensible (all source included, no unusual libraries, and no hidden drivers). We like to think that this increases the chances that our programs will still work in another 5-10 years. In fact, the ToolKit has been working continuously for nearly 8 years now. STK currently runs with "realtime" support (audio and MIDI) on SGI (Irix), Linux, Macintosh OS X, and Windows computer platforms. Generic, non-realtime support has been tested under NeXTStep, Sun, and other platforms and should work with any standard C++ compiler.
The Synthesis ToolKit is free for non-commercial use. The only parts of the Synthesis ToolKit that are platform-dependent concern real-time audio and MIDI input and output, and that is taken care of with a few special classes. The interface for MIDI input and the simple Tcl/Tk graphical user interfaces (GUIs) provided is the same, so it's easy to experiment in real time using either the GUIs or MIDI. The Synthesis ToolKit can generate simultaneous SND (AU), WAV, AIFF, and MAT-file output soundfile formats (as well as realtime sound output), so you can view your results using one of a large variety of sound/signal analysis tools already available (e.g. Snd, Cool Edit, Matlab).
The Synthesis Toolkit is not one particular program. Rather, it is a set of C++ classes that you can use to create your own programs. A few example applications are provided to demonstrate some of the ways to use the classes. If you have specific needs, you will probably have to either modify the example programs or write a new program altogether. Further, the example programs don't have a fancy GUI wrapper. If you feel the need to have a "drag and drop" graphical patching GUI, you probably don't want to use the ToolKit. Spending hundreds of hours making platform-dependent graphics code would go against one of the fundamental design goals of the ToolKit - platform independence.
For those instances where a simple GUI with sliders and buttons is helpful, we use Tcl/Tk (http://dev.scriptics.com) which is freely distributed for all the supported ToolKit platforms. A number of Tcl/Tk GUI scripts are distributed with the ToolKit release. For control, the Synthesis Toolkit uses raw MIDI (on supported platforms), and SKINI (Synthesis ToolKit Instrument Network Interface, a MIDI-like text message synthesis control format).
SYSTEM REQUIREMENTS:
See the individual README's (eg. README-linux) in the /doc directory for platform specific information and system requirements. In general, you will use the configure script to create Makefiles on unix platforms 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:
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 Release Notes to see what has changed since the last release.
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 Irix, audio input and output are possible with very low latency. Using the Windoze DirectSound API, minimum dependable output sound latency seems to be around 20 milliseconds or so, while input sound latency is on the order of a hundred milliseconds or more!
As mentioned above, it is possible to record the audio ouput of an STK program to .snd, .wav, .raw, .aif, and .mat (Matlab MAT-file) output file types. Though somewhat obsolete, the program Md2Skini can be used to write SKINI scorefiles from realtime MIDI input. Finally, STK should compile with non-realtime functionality on any platform with a generic C++ compiler.
For those who wish to make a library from the core STK classes, the configure script generates a Makefile in the src directory that will accomplish that (Linux, SGI, and Macintosh OS X only).
DISCLAIMER:
You probably already guessed this, but just to be sure, we don't guarantee anything works. :-) It's free ... what do you expect? If you find a bug, please let us know and we'll try to correct it. You can also make suggestions, but again, no guarantees. Send email to 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 complete documentation on this ToolKit, the classes, etc., see the doc directory of the distribution or surf to http://www-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 (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 . . .

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--2014.
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

@@ -3,7 +3,7 @@
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
# Free Software Foundation, Inc.
timestamp='2001-04-20'
timestamp='2004-02-26'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
# Free Software Foundation, Inc.
timestamp='2001-04-20'
timestamp='2004-02-26'
# This file is (in principle) common to ALL GNU software.
# The presence of a machine in this file suggests that SOME GNU software

View File

@@ -1,12 +1,19 @@
# Process this file with autoconf to produce a configure script.
AC_INIT(STK, 4.1.2, gary@ccrma.stanford.edu, stk)
AC_INIT(STK, 4.5.0, gary@music.mcgill.ca, stk)
AC_CONFIG_AUX_DIR(config)
AC_CONFIG_SRCDIR(src/Stk.cpp)
AC_CONFIG_FILES(src/Makefile projects/demo/Makefile projects/effects/Makefile projects/ragamatic/Makefile projects/examples/Makefile)
AC_CONFIG_FILES(Makefile src/Makefile projects/demo/Makefile projects/effects/Makefile projects/ragamatic/Makefile projects/examples/Makefile projects/examples/libMakefile projects/eguitar/Makefile)
# Fill GXX with something before test.
AC_SUBST( GXX, ["no"] )
# Checks for programs.
AC_PROG_CC
AC_PROG_CXX(g++ CC c++ cxx)
AC_PROG_CXX
AC_PROG_RANLIB
AC_PATH_PROG(AR, ar, no)
if [[ $AR = "no" ]] ; then
AC_MSG_ERROR("Could not find ar - needed to create a library");
fi
# Checks for header files.
AC_HEADER_STDC
@@ -33,85 +40,173 @@ AC_MSG_RESULT($INCLUDE_PATH)
# Check for realtime support disable
AC_MSG_CHECKING(whether to compile realtime support)
AC_ARG_ENABLE(realtime, [ --disable-realtime = only compile generic non-realtime classes], [AC_SUBST( realtime, [no] ) AC_SUBST( sound_api, [] )], [AC_SUBST( realtime, [yes] ) ] )
AC_ARG_ENABLE(realtime,
[ --disable-realtime = only compile generic non-realtime classes],
realtime=$enableval)
if test "$realtime" = "no"; then
AC_SUBST( sound_api, [] )
else
AC_SUBST( realtime, [yes] )
fi
AC_MSG_RESULT($realtime)
AC_MSG_CHECKING(whether to build the static library)
AC_ARG_ENABLE(static,
[ --disable-static = do not compile static library ],
build_static=$enableval,
build_static=yes)
AC_SUBST(build_static)
AC_MSG_RESULT($build_static)
AC_MSG_CHECKING(whether to build the shared library)
AC_ARG_ENABLE(shared,
[ --enable-shared = compile the shared library ],
build_shared=$enableval,
build_shared=no)
AC_SUBST(build_shared)
AC_MSG_RESULT($build_shared)
if test x$build_static = xno -a x$build_shared = xno ; then
AC_MSG_ERROR([ both static and shared libraries are disabled], 1)
fi
# Check for math library
AC_CHECK_LIB(m, cos, , AC_MSG_ERROR(math library is needed!))
if test $realtime = yes; then
AC_CHECK_LIB(pthread, pthread_create, , AC_MSG_ERROR(realtime support requires the pthread library!))
AC_CHECK_FUNCS(gettimeofday select socket)
fi
# Check for debug
AC_MSG_CHECKING(whether to compile debug version)
AC_ARG_ENABLE(debug,
[ --enable-debug = enable various debug output],
[AC_SUBST( debug, [-D_STK_DEBUG_] ) AC_SUBST( cflags, [-g] ) AC_SUBST( object_path, [Debug] ) AC_MSG_RESULT(yes)],
[AC_SUBST( debug, [] ) AC_SUBST( cflags, [-O2] ) AC_SUBST( object_path, [Release] ) AC_MSG_RESULT(no)])
[ --enable-debug = enable various debug output],
debug=$enableval)
if test "$debug" = "yes"; then
AC_SUBST( cppflag, ["-D_STK_DEBUG_ -D__RTAUDIO_DEBUG__ -D__RTMIDI_DEBUG__"] )
AC_SUBST( cxxflag, ["-g"] )
AC_SUBST( object_path, [Debug] )
else
AC_SUBST( debug, [no] )
AC_SUBST( cppflag, [] )
AC_SUBST( cxxflag, [-O3] )
AC_SUBST( object_path, [Release] )
fi
AC_MSG_RESULT($debug)
# Checks for functions
if test $realtime = yes; then
AC_CHECK_FUNCS(select socket)
AC_CHECK_FUNC(gettimeofday, [cppflag="$cppflag -DHAVE_GETTIMEOFDAY"], )
fi
# For -I and -D flags
CPPFLAGS="$CPPFLAGS $cppflag"
# For debugging and optimization ... overwrite default because it has both -g and -O2
CXXFLAGS="$cxxflag"
# Check compiler and use -Wall if gnu.
if test $GXX = "yes" ; then
AC_SUBST( warn, ["-Wall -g"] )
if [test $GXX = "yes" ;] then
AC_SUBST( cxxflag, [-Wall] )
fi
CXXFLAGS="$CXXFLAGS $cxxflag"
AC_CANONICAL_HOST
AC_SUBST( sharedlib, ["libstk.so"] )
AC_SUBST( sharedname, ["libstk.so.\$(RELEASE)"] )
AC_SUBST( libflags, ["-shared -Wl,-soname,\$(SHAREDLIB).\$(MAJOR) -o \$(SHAREDLIB).\$(RELEASE)"] )
case $host in
*-apple*)
AC_SUBST( sharedlib, ["libstk.dylib"] )
AC_SUBST( sharedname, ["libstk.\$(RELEASE).dylib"] )
AC_SUBST( libflags, ["-dynamiclib -o libstk.\$(RELEASE).dylib"] )
esac
if test $realtime = yes; then
# Checks for package options and external software
AC_CANONICAL_HOST
AC_MSG_CHECKING(for audio API)
case $host in
*-*-linux*)
AC_SUBST( sound_api, [_NO_API_] )
AC_ARG_WITH(jack, [ --with-jack = choose JACK server support (mac and linux only)], [
api="$api -D__UNIX_JACK__"
AC_MSG_RESULT(using JACK)
AC_CHECK_LIB(jack, jack_client_open, , AC_MSG_ERROR(JACK support requires the jack library!))
AC_CHECK_LIB(asound, snd_pcm_open, , AC_MSG_ERROR(Jack support also requires the asound library!))], )
# Look for Jack flag
AC_ARG_WITH(jack, [ --with-jack = choose JACK server support (linux only)], [AC_SUBST( sound_api, [-D__LINUX_JACK__] ) AC_MSG_RESULT(using JACK)] , )
if [test $sound_api = -D__LINUX_JACK__;] then
TEMP_LIBS=$LIBS
AC_CHECK_LIB(jack, jack_client_new, , AC_MSG_ERROR(JACK support requires the jack library!))
AC_CHECK_LIB(asound, snd_pcm_open, , AC_MSG_ERROR(ALSA support requires the asound library!))
LIBS="`pkg-config --cflags --libs jack` $TEMP_LIBS -lasound"
audio_apis="-D__LINUX_JACK__"
fi
# Look for Alsa flag
AC_ARG_WITH(alsa, [ --with-alsa = choose native ALSA API support (linux only)], [AC_SUBST( sound_api, [-D__LINUX_ALSA__] ) AC_MSG_RESULT(using ALSA)], )
if test $sound_api = -D__LINUX_ALSA__; then
AC_CHECK_LIB(asound, snd_pcm_open, , AC_MSG_ERROR(ALSA support requires the asound library!))
audio_apis="-D__LINUX_ALSA__ $audio_apis"
fi
# Look for ALSA flag
AC_ARG_WITH(alsa, [ --with-alsa = choose native ALSA API support (linux only)], [
api="$api -D__LINUX_ALSA__"
AC_MSG_RESULT(using ALSA)
AC_CHECK_LIB(asound, snd_pcm_open, , AC_MSG_ERROR(ALSA support requires the asound library!))], )
# Look for OSS flag
AC_ARG_WITH(oss, [ --with-oss = choose OSS API support (linux only)], [AC_SUBST( sound_api, [-D__LINUX_OSS__] ) AC_MSG_RESULT(using OSS)], )
if test $sound_api = -D__LINUX_OSS__; then
audio_apis="-D__LINUX_OSS__ $audio_apis"
AC_ARG_WITH(oss, [ --with-oss = choose OSS API support (linux only)], [
api="$api -D__LINUX_OSS__ -D__LINUX_ALSA__"
AC_MSG_RESULT(using OSS)
AC_CHECK_LIB(asound, snd_pcm_open, , AC_MSG_ERROR(OSS support requires ALSA for RtMidi!))], )
# If no audio api flags specified, use ALSA
if [test "$api" == "";] then
AC_MSG_RESULT(using ALSA)
AC_SUBST( api, [-D__LINUX_ALSA__] )
AC_CHECK_LIB(asound, snd_pcm_open, , AC_MSG_ERROR(ALSA support requires the asound library!))
fi
# If no audio api flags specified, use OSS
if [test $sound_api = _NO_API_;] then
AC_SUBST( sound_api, [-D__LINUX_OSS__] )
AC_MSG_RESULT(using OSS)
AC_SUBST( audio_apis, [-D__LINUX_OSS__] )
fi
AC_ARG_ENABLE(midiator, [ --enable-midiator = enable native MS-124W MIDI support (linux only)], [AC_SUBST( midiator, [-D__MIDIATOR__] )], [AC_SUBST( midiator, [] )])
;;
*-sgi*)
AC_SUBST( audio_apis, ["-D__IRIX_AL__ -LANG:std -w"] )
AC_MSG_RESULT(using IRIX AL)
AC_CHECK_LIB(audio, alOpenPort, , AC_MSG_ERROR(IRIX audio support requires the audio library!) )
AC_CHECK_LIB(md, mdOpenInPort, , AC_MSG_ERROR(IRIX MIDI support requires the md library!) )
AC_CHECK_LIB(pthread, pthread_create, , AC_MSG_ERROR(RtAudio requires the pthread library!))
;;
*-apple*)
# Check for CoreAudio and CoreMIDI framework
AC_CHECK_HEADERS(CoreAudio/CoreAudio.h CoreMIDI/CoreMIDI.h CoreServices/CoreServices.h,
[AC_SUBST( audio_apis, [-D__MACOSX_CORE__] )],
[AC_MSG_ERROR(CoreAudio and/or CoreMIDI header files not found!)] )
AC_SUBST( frameworks, ["-framework CoreAudio -framework CoreMIDI -framework CoreFoundation"] )
# Explicitly link with c++ library.
AC_CHECK_LIB(stdc++, printf, , AC_MSG_ERROR(Stk requires the C++ library!) )
AC_ARG_WITH(jack, [ --with-jack = choose JACK server support (unix only)], [
api="$api -D__UNIX_JACK__"
AC_MSG_RESULT(using JACK)
AC_CHECK_LIB(jack, jack_client_new, , AC_MSG_ERROR(JACK support requires the jack library!))], )
# Look for Core flag
AC_ARG_WITH(core, [ --with-core = choose CoreAudio API support (mac only)], [
api="$api -D__MACOSX_CORE__"
AC_MSG_RESULT(using CoreAudio)
AC_CHECK_HEADER(CoreAudio/CoreAudio.h, [], [AC_MSG_ERROR(CoreAudio header files not found!)] )
LIBS="$LIBS -framework CoreAudio -framework CoreFoundation -framework CoreMidi" ], )
# If no audio api flags specified, use CoreAudio
if [test "$api" == ""; ] then
AC_SUBST( api, [-D__MACOSX_CORE__] )
AC_MSG_RESULT(using CoreAudio)
AC_CHECK_HEADER(CoreAudio/CoreAudio.h,
[],
[AC_MSG_ERROR(CoreAudio header files not found!)] )
AC_SUBST( LIBS, ["-framework CoreAudio -framework CoreFoundation -framework CoreMidi"] )
fi
AC_CHECK_LIB(pthread, pthread_create, , AC_MSG_ERROR(RtAudio requires the pthread library!))
;;
*-mingw32*)
AC_ARG_WITH(asio, [ --with-asio = choose ASIO API support (windoze only)], [
api="$api -D__WINDOWS_ASIO__"
AC_MSG_RESULT(using ASIO)
AC_SUBST( objects, ["asio.o asiodrivers.o asiolist.o iasiothiscallresolver.o"] ) ], )
# Look for DirectSound flag
AC_ARG_WITH(ds, [ --with-ds = choose DirectSound API support (windoze only)], [
api="$api -D__WINDOWS_DS__"
AC_MSG_RESULT(using DirectSound)
LIBS="-ldsound $LIBS" ], )
# Look for WASAPI flag
AC_ARG_WITH(wasapi, [ --with-wasapi = choose Windows Audio Session API support (windoze only)], [
api="$api -D__WINDOWS_WASAPI__"
AC_MSG_RESULT(using WASAPI)
LIBS="-luuid -lksuser $LIBS" ], )
# If no audio api flags specified, use DirectSound
if [test "$api" == "";] then
AC_SUBST( api, [-D__WINDOWS_DS__] )
AC_MSG_RESULT(using DirectSound)
LIBS="-ldsound -lwinmm $LIBS"
fi
api="$api -D__WINDOWS_MM__"
LIBS="-lole32 -lwinmm -lwsock32 $LIBS"
;;
*)
@@ -119,10 +214,8 @@ if test $realtime = yes; then
AC_MSG_ERROR(Unknown system type for realtime support ... try --disable-realtime argument!)
;;
esac
CPPFLAGS="$CPPFLAGS $api"
fi
# Checks for library functions.
AC_PROG_GCC_TRADITIONAL
AC_CHECK_FUNCS(strstr)
AC_OUTPUT

View File

@@ -1,167 +0,0 @@
STK: A ToolKit of Audio Synthesis Classes and Instruments in C++
By Perry R. Cook and Gary P. Scavone, 1995-2004.
STK Classes - See the HTML documentation in the html directory for complete information.
.- Envelope - ADSR
|
|- Noise - SubNoise
|
|- Table
|
|- WvIn - (WaveLoop, RtWvIn, TcpWvIn)
|
|- WvOut - (RtWvOut, TcpWvOut)
|
|- Filter - (OnePole, OneZero, Delay, TwoPole, TwoZero, PoleZero, Biquad)
| | |
| DelayL FormSwep
| DelayA
|
|- Echo, Chorus, PitShift
|
|- RtAudio, RtMidi, Socket, Thread
Stk -|
|- Reverb - (PRCRev, JCRev, NRev)
|
|- Modulate
|
|- SingWave
|
|- Voicer
|
|- Messager
|
|- SKINI
|
|- ReedTabl, JetTabl, BowTabl
|
| .- FM - (HevyMetl, PercFlut, Rhodey, Wurley, TubeBell, BeeThree, FMVoices)
| |
| |- Modal - ModalBar
| |
| |- VoicForm
| |
| |- Sampler - Moog
| |
| |- Resonate
| |
| |- PluckedTwo - Mandolin
.- Instrmnt -|
|- Drummer
|
|- Clarinet, BlowHole, Saxofony, Flute, Brass, BlowBotl, Bowed, Plucked, StifKarp, Sitar
|
|- Shakers
|
|- BandedWG
|
|- Mesh2D
|
.- Whistle
*********** UNIT GENERATORS **************
Master Class: Stk.cpp Sample rate, byte-swapping, error handling functionality
Sources: Envelope.cpp Linearly Goes to Target by Rate
ADSR.cpp ADSR Flavor of Envelope
Noise.cpp Random Number Generator
SubNoise.cpp Random Numbers each N samples
Table.cpp Lookup Table (assumes given data in big-endian format)
WvIn.cpp Data Input Class (interpolating) for RAW, WAV, SND (AU), AIFF, MAT-file files
WaveLoop.cpp Wavetable looping (subclass of WvIn)
RtWvIn.cpp Realtime Audio Input Class (subclass of WvIn)
TcpWvIn.cpp Audio Streaming (socket server) Input Class (subclass of WvIn)
Sinks: WvOut.cpp Output Master Class for RAW, WAV, SND (AU), AIFF, MAT-file files
RtWvOut.cpp Realtime Audio Output Class (subclass of WvOut)
TcpWvOut.cpp Audio Streaming (socket client) Output Class (subclass of WvOut)
Duplex: RtDuplex.cpp Synchronous Realtime Audio Input/Output Class
Filters: Filter.cpp Filter Master Class
OneZero.cpp One Zero Filter
OnePole.cpp One Pole Filter
PoleZero.cpp One Pole/One Zero Filter
TwoZero.cpp Two Zero Filter
TwoPole.cpp Two Pole Filter
BiQuad.cpp Two Pole/Two Zero Filter
FormSwep.cpp Sweepable BiQuad Filter (goes to target by rate)
Delay.cpp Non-Interpolating Delay Line Class
DelayL.cpp Linearly Interpolating Delay Line (subclass of Delay)
DelayA.cpp Allpass Interpolating Delay Line (subclass of Delay)
Non-Linear: JetTabl.cpp Cubic Jet Non-Linearity
BowTabl.cpp x^(-3) Bow Non-Linearity
ReedTabl.cpp One Breakpoint Saturating Reed Non-Linearity
Derived: Modulate.cpp Periodic and Random Vibrato: WvIn, SubNoise, OnePole
SingWave.cpp Looping wave table with randomness: Modulate, WaveLoop, Envelope
********** INSTRUMENTS AND ALGORITHMS **************
Each class is listed either with some of the unit generators it uses,
or in terms of the algorithm it implements. All inherit from Instrmnt,
which inherits from Stk.
Simple.cpp Simple Instrument Pulse oscillator + resonant filtered noise
Plucked.cpp Basic Plucked String DelayA, OneZero, OnePole, Noise
StifKarp.cpp Plucked String with Stiffness DelayA, DelayL, OneZero, BiQuad, Noise
PluckTwo.cpp Not So Basic Pluck DelayL, DlineA, OneZero
Mandolin.cpp Commuted Mandolin <<flavor of PluckTwo>>
Bowed.cpp So So Bowed String DelayL, BowTabl, OnePole, BiQuad, WaveLoop, ADSR
Brass.cpp Not So Bad Brass Instrument DelayA, BiQuad, PoleZero, ADSR, WaveLoop
Clarinet.cpp Pretty Good Clarinet DelayL, ReedTabl, OneZero, Envelope, Noise, WaveLoop
BlowHole.cpp Clarinet w/ Tone & Vent Holes DelayL, ReedTabl, OneZero, Envelope, Noise, WaveLoop, PoleZero
Saxofony.cpp A Faux Saxophone DelayL, ReedTabl, OneZero, Envelope, Noise, WaveLoop
Flute.cpp Pretty Good Flute JetTabl, DelayL, OnePole, PoleZero, Noise, ADSR, WaveLoop
BlowBotl.cpp Blown Bottle JetTabl, BiQuad, PoleZero, Noise, ADSR, WaveLoop
BandedWG.cpp Banded Waveguide Meta-Object Delay, BowTabl, ADSR, BiQuad
Modal.cpp N Resonances Envelope, WaveLoop, BiQuad, OnePole
ModalBar.cpp Various presets 4 Resonance Models
FM.cpp N Operator FM Master ADSR, WaveLoop, TwoZero
HevyMetl.cpp Distorted FM Synthesizer 3 Cascade with FB Modulator
PercFlut.cpp Percussive Flute 3 Cascade Operators
Rhodey.cpp Rhodes-Like Electric Piano 2 Parallel Simple FMs
Wurley.cpp Wurlitzer Electric Piano 2 Parallel Simple FMs
TubeBell.cpp Classic FM Bell 2 Parallel Simple FMs
FMVoices.cpp 3 Formant FM Voice 3 Carriers Share 1 Modulator
VoicForm.cpp 4 Formant Voice Synthesis FormSwep, SingWave, OnePole, OneZero, Envelope, Noise
BeeThree.cpp Cheezy Additive Organ 4 Oscillators Additive
Sampler.cpp Sampling Synthesizer 5 each ADSR, WvIn, WaveLoop, OnePole
Moog.cpp Swept Filter Sampler with Swept Filter
Resonate.cpp Filtered Noise ADSR, BiQuad, Noise
Drummer.cpp Drum Synthesizer Bunch of WvIns, and OnePole
Shakers.cpp PhISM statistical model for shakers and real-world sound effects
Mesh2D.cpp Two-dimensional, rectilinear digital waveguide mesh.
Whistle.cpp Hybrid physical/spectral model of a police whistle.
Reverb.cpp Reverberator Effects Processor Master Class for reverberators
JCRev.cpp Chowning Reverberator 3 series allpass units, 4 parallel combs, 2 stereo delays
NRev.cpp Another famous CCRMA Reverb 8 allpass, 6 parallel comb filters
PRCRev.cpp Dirt Cheap Reverb by Cook 2 allpass, 2 comb filters
Flanger.cpp Flanger Effects Processor DelayL, WaveLoop
Chorus.cpp Chorus Effects Processor DelayL, WaveLoop
PitShift.cpp Cheap Pitch Shifter DelayL
*********** OTHER SUPPORT CLASSES AND FILES **************
RtAudio.cpp Multi-OS/API audio I/O routines
RtMidi.cpp Multi-OS/API MIDI I/O routines
Messager.cpp Pipe, socket, and MIDI control message handling
Voicer.cpp Multi-instrument voice manager
demo.cpp Demonstration program for most synthesis algorithms
effects.cpp Effects demonstration program
ragamatic.cpp Nirvana just waiting to happen
SKINI.cpp SKINI file/message parser object
SKINI.msg #defines for often used and universal MIDI/SKINI symbols
SKINI.tbl Table of SKINI messages

View File

@@ -1,26 +1,13 @@
The Synthesis ToolKit in C++ (STK)
By Perry R. Cook and Gary P. Scavone, 1995-2004.
By Perry R. Cook and Gary P. Scavone, 1995--2014.
Please read the file README and INSTALL for more general STK information.
Realtime support for Linux is currently using either the Open Sound System (OSS) or the Advanced Linux Sound Architecture (ALSA) sound and MIDI APIs. The free version of OSS works as well (and in some cases better than the commercial OSS version ... such as with my Maestro 2e chipset). In general, the ALSA drivers also seem to perform well. You can read more about ALSA at http://www.alsa-project.org/. ALSA is open source and holds great promise for audio under Linux. The API is selected during compilation using either the __LINUX_ALSA__ or __LINUX_OSS__ definitions. The configure script uses the OSS API by default. The ALSA API can be selected by passing the "--with-alsa" option to configure.
Realtime audio support for Linux currently includes the Advanced Linux Sound Architecture (ALSA), the JACK low-latency audio server, and/or Open Sound System (OSS version 4.0 and higher only) APIs. That said, the OSS API support has not been tested in several years and is not considered a high priority. One or more APIs are selected during compilation using the __LINUX_ALSA__, __UNIX_JACK__, and/or __LINUX_OSS__ definitions. Because the ALSA library is now integrated into the standard Linux kernel, it is the default audio/MIDI API with STK versions 4.2 and higher.
STK should compile without much trouble under Linux ... afterall, it is primarily developed on Linux platforms. 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.
Realtime MIDI support Linux currently includes the Jack and ALSA sequencer support. Native OSS MIDI support no longer exists in RtMidi. If the __LINUX_OSS__ preprocessor definition is specified, only OSS audio support will be compiled and RtMidi will still be compiled using the ALSA API. For this reason, STK now requires the asound library for realtime support (unless only using the Jack API). Realtime programs must also link with the pthread library.
MIDIATOR SERIAL PORT MIDI SUPPORT:
STK now has special support for the MIDIator serial port MIDI interface. This is of primary interest to us laptop users, whose computers usually don't have a gameport. If you want to buy one of these devices, make sure you get the MS-124w model (www.midiator.com). For it to work in STK, you must provide the __MIDIATOR__ definition during compilation (in addition to either __LINUX_ALSA__ or __LINUX_OSS__) or pass the "--enable-midiator" option to configure.
There are a few things that need to be done on your system to get the MIDIator working. Assuming you wish to attach the MIDIator to serial port 0, add the following lines to your bootup sequence in /etc/rc.d/rc.local:
setserial /dev/ttyS0 baud_base 57600
setserial /dev/ttyS0 divisor 1
You may need to specify the full path to the setserial function, depending on how your PATH variable is set up. Also, you may need to modify the permissions of /dev/ttyS0 (chmod a+rwx). And finally, the MIDIator should be set for "single addresssed" mode (the S/A switch on S and the A/B switch on A), which puts identical output on all 4 MIDI output ports. It is possible to use the MIDIator in a "multi-port" mode, though I'm not currently supporting that in STK.
NOTE REGARDING PTHREADS:
There haven't been any problems with threads since the old days of RedHat Linux 5.0. STK uses the MIT pthreads API.
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 Makefiles. Typing "make" in a project directory will initiate the compilation process (after initially running the configure script in the top-level directory).

View File

@@ -1,22 +1,16 @@
The Synthesis ToolKit in C++ (STK)
By Perry R. Cook and Gary P. Scavone, 1995-2004.
By Perry R. Cook and Gary P. Scavone, 1995--2014.
Please read the file README and INSTALL for more general STK information.
Realtime support for Macintosh OS X uses the CoreAudio HAL API and is specified during compilation using the __MACOSX_CORE__ preprocessor definition.
It is necessary to download the OS X developer kit in order to compile STK. STK was successfully tested on OS X version 10.2.
The internal Macintosh audio hardware typically supports a sample rate of 44100 Hz only. Therefore, it is necessary to either specify this rate as a command-line option to the STK example programs or to change the default sample rate inside the Stk.h file before compilation. In addition, the RT_BUFFER_SIZE, specified in Stk.h, could be increased (to a higher power of two) for more robust performance.
There is a potential conflict between the STK Delay class and a Delay() function declared in OSUtils.h (which is included via <CoreServices/CoreServices.h>). In general, this conflict can be avoided via the use of a namespace (an explicit Delay::Delay declaration), though this made the Windows Visual C++ compiler barf. If you use STK classes within a project that includes the OSUtils.h file, you will likely need to make changes in STK classes that use the Delay class.
The default realtime support for Macintosh OS X uses the CoreAudio HAL API and is specified during compilation using the __MACOSX_CORE__ preprocessor definition. There is also support for the JACK audio server using the __UNIX_JACK__ preprocessor definition.
It is necessary to install the OS X developer kit (or the command line tools) in order to compile STK. STK was successfully tested on the latest version of OS X.
Tcl/Tk on OS X:
The tcl/tk interpreter does not ship by default with OS X, but must be downloaded from the internet. The latest Tcl/Tk Aqua distribution (http://www.apple.com/downloads/macosx/unix_open_source/tcltk.html) has been successfully tested on a 10.2 system. The default installation will place a link to the wish interpretor at /usr/bin/wish.
I think that tcl/tk interpreter is now included in the XCode package, since I haven't had to download it for several years now.
Initial tests have shown somewhat poor response between changes made in the tcl/tk script and the resulting audio updates.
It appears that socket support in Tcl/Tk on OS X uses the Nagle algorithm, which produces poor response between changes made in the tcl/tk script and the resulting audio updates. Note that this is only a problem when using a socket connection from a Tcl/Tk script.
It is possible to connect a tcl/tk interface to an STK program via a socket connection. However, the tcl/tk interpreter does not appear to properly close the socket connection during disconnection. It is therefore necessary to type "Exit" in the STK program terminal window to properly exit the STK program.

View File

@@ -1,7 +0,0 @@
The Synthesis ToolKit in C++ (STK)
By Perry R. Cook and Gary P. Scavone, 1995-2004.
Please read the file README and INSTALL for more general STK information.
STK has always worked under NeXTStep without realtime audio or MIDI support. In general, STK should compile in this way using any generic C++ compiler. C++ exception handling was added to STK with release 3.2. We managed to get a version of gcc compiled for NeXTStep that can deal with C++ exceptions.

View File

@@ -1,13 +1,7 @@
The Synthesis ToolKit in C++ (STK)
By Perry R. Cook and Gary P. Scavone, 1995-2004.
By Perry R. Cook and Gary P. Scavone, 1995--2014.
Please read the file README and INSTALL for more general STK information.
The project Makefiles are created by configure. If you have trouble running "make", try invoking "gmake" (for GNU make). If that doesn't work, try to download the GNU Makefile utilities from the Internet.
Another issue that has crept up with this release is proper compiler support for C++ error handling. If you experience problems, you probably don't have a recent version of the C++ compiler. Otherwise, STK should compile and run on SGI platforms without any problems. Release 4.0 of STK is confirmed to compile (with various warnings) using CC version 7.30.
NOTE REGARDING PTHREADS:
Since release 3.1, STK has used 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!
Since STK version 4.3, realtime support for IRIX has been discontinued due to an inability to test it. If you need realtime support on an SGI, go back to version 4.2.1. Release 4.0 of STK is confirmed to compile (with various warnings) using CC version 7.30.

View File

@@ -1,23 +1,22 @@
The Synthesis ToolKit in C++ (STK)
By Perry R. Cook and Gary P. Scavone, 1995-2004.
By Perry R. Cook and Gary P. Scavone, 1995--2014.
Please read the file README for more general STK information.
DirectX and WindowsNT Issues:
-----------------------------
The configure script supports MinGW. As well, STK is distributed with Visual C++ .NET project and workspace files (though these may no longer work with current versions of Visual Studio). It no longer compiles with Visual C++ 6.0.
STK is currently distributed with Visual C++ 6.0 project and workspace files. It has been tested using both Visual C++ 6.0 and Visual C++ .NET.
With Windows XP/7, piping works as under unix. Simply fire up the script files (ex. StkDemo.bat) by either double-clicking on them or from within a shell.
IMPORTANT VC++ NOTE: When compiling "release" versions of STK programs, link to the release multithreaded library. When compiling "debug" versions, link to the debug multithreaded library. Compiler errors will result otherwise. Also, the Microsoft folk are up to their old habits of trying to change standards. The .NET compiler will complain about cerr for some reason.
IMPORTANT VC++ NOTE: When compiling "release" versions of STK programs, link to the release multithreaded library. When compiling "debug" versions, link to the debug multithreaded library. Compiler errors will result otherwise.
Both the DirectSound and Steinberg ASIO audio APIs are supported for realtime audio input/output. The Visual C++ project files included with this distribution are configured to use the DirectSound API. In order to use the ASIO API, it is necessary to change the preprocessor definition from __WINDOWS_DS__ to __WINDOWS_ASIO__, as well as include all the files in the /src/asio/ directory (i.e. asio.h, asio.cpp, ...). If you have a good quality soundcard and a native ASIO driver (not emulated), you are likely to get much better input/output response using that.
The DirectSound, WASAPI and Steinberg ASIO audio APIs are supported for realtime audio input/output. The Visual C++ project files included with this distribution are configured to use all supported APIs. In order to use the ASIO API, it is necessary to use the preprocessor definition __WINDOWS_ASIO__, as well as include most of the files in the /src/include/ directory (i.e. asio.h, asio.cpp, ...). If you have a good quality soundcard and a native ASIO driver (not emulated), you are likely to get much better input/output response using that.
When using the DirectSound API for audio input, latency is typically pretty horrendous (should we be surprised?). Also, there is a slight chance you don't have DirectSoundCapture support on your computer. If not, 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. The last time I checked, there was no DirectSoundCapture support for WindowsNT ... you'll have to switch to Windows 2000 or XP or use an ASIO driver. I stopped supporting the WinMM audio output code with release 3.2.
When using the DirectSound API for audio input, latency can be high. If you experience realtime audio "stuttering", you should experiment with different "buffer size" and "number of buffers" values.
Realtime MIDI input is supported using the winmm.lib API.
Realtime MIDI input/output is supported by RtMidi using the winmm.lib API and requires the __WINDOWS_MM__ preprocessor definition.
Visual C++ 6.0 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 for a project, 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":
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 for a project, 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" (this was for VC 6.0 ... things have changed with the newer versions of the VC compiler):
1. Under General: Set "Output files:" to <blank> (this will put the executable in the main project directory.
@@ -27,48 +26,10 @@ Visual C++ 6.0 workspaces have been created for the various STK projects. Every
4. Under C/C++ > Preprocessor: Add "../../include" directory to the "extra include" field.
5. Under C/C++ > Preprocessor: Add "__WINDOWS_DS__" to the definitions field.
5. Under C/C++ > Preprocessor: Add "__WINDOWS_DS__", "__WINDOWS_MM__", and "__LITTLE_ENDIAN__ to the definitions field.
6. Add all the necessary files to the project.
Remember that items 1-5 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 -
WINDOWS XP/2000:
There is a big advantage in using Windows XP/2000 over 95/98 with STK in that piping works, just as under unix. Also, the scheduler in 2000/XP seems to be much better, so socketed messages don't get clumped together like they do in Windows 95/98. Simply fire up a script file (ex. StkDemo.bat) by either double-clicking on it or typing it within a shell.
WINDOWS 95/98:
PLAY SKINI SCOREFILES IN REALTIME:
demo Clarinet -or < scores/streetsf.ski
USE TCL/TK GUIs FOR REALTIME CONTROL:
1. Open a DOS console window and start syntmono (eg. demo Clarinet -or -is).
2. Double click on a Tcl/Tk file in the tcl/ subdirectory of the demo directory (eg. Demo.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 with MIDI input (eg. demo Clarinet -or -im).
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. Note, however, that the DirectSoundCapture API does not exist for WindowsNT, so it is necessary to use an ASIO audio driver and the STK ASIO support.
To use the Tcl/Tk GUIs, you will have to install Tcl/Tk.

View File

@@ -1,6 +1,138 @@
The Synthesis ToolKit in C++ (STK)
By Perry R. Cook and Gary P. Scavone, 1995-2004.
By Perry R. Cook and Gary P. Scavone, 1995--2014.
v4.5.0: (26 April 2014)
- updated versions of RtAudio and RtMidi, with associated renaming of RtError class to either RtAudioError or RtMidiError and addition of WASAPI support in Windows
- added support in FileRead for little-endian AIFC file format
- new iOS project files (thanks to Ariel Elkin)
- bug fix in FreeVerb that could cause crackling for stereo input
- various bug fixes and updates to minimize compiler warnings
- ADSR fix for decay/release time calculations
- various updates to build system
v4.4.4: (24 August 2012)
- new FreeVerb class (thanks to Greg Burlet)
- new Guitar class
- new electric guitar project
- cleaned / revised Shakers class
- updated versions of RtAudio and RtMidi
- bug fix in LentPitShift
- bug fix in Echo constructor
- bug fix in FileWvIn (file size when chunking)
- bug fix in StkFrames copy constructor
v4.4.3: (30 August 2011)
- changed SINT24 to be lower 3 bytes of 32-bit word
- bug fixes to vectorized tick functions in Effects classes
- updated versions of RtAudio and RtMidi
- fix to ADSR bugs
- updates to the internal argument checking and reporting scheme
- updates to Bowed class (thanks to Esteban Maestre!)
- fixes for 24-bit support in FileRead and FileWrite
- added WAVE_FORMAT_EXTENSIBLE support in FileWrite
- added sample rate variable reading and writing for MAT-files in FileRead and FileWrite
v4.4.2: (4 February 2011)
- added various header file includes for newer compilers
- new LentPitShift class (thanks to Francois Germain)
- added "addTo" function to Delay class
- updates to RtAudio and RtMidi
- bug fixes in Voicer class (thanks Richard Dobson!)
- bug fixes in Granulate class
- added Makefile.in to compile library and all projects, as well as clean and distclean all
v4.4.1: (3 June 2010)
- added multi-channel/frame tick() virtual function to WvIn and WvOut abstract base classes (required update to RtWvOut class)
- updated configure script to select g++ compiler by default
- in demo.cpp: removed voicer grouping for messages, fixing polyphony when messages are on the same MIDI/SKINI channel
- updates to RtAudio and RtMidi
v4.4: (30 April 2010)
- all classes embedded in the "stk" namespace (except RtAudio, RtMidi, and RtError)
- class WaveLoop renamed FileLoop
- significant efficiency improvements via code restructuring and inlining
- some class source (.cpp) files deleted as part of inlining (Generator, Filter, Function, WvIn, WvOut, Effect, Instrmnt, BowTable, ReedTable, JetTable, Vector3D)
- updates to RtAudio and RtMidi
- previous "tickFrame()" functions renamed "tick" for more consistent API
- more consistent and scalable approach to multichannel data and computations
- multichannel support added to Granulate class
- Filter class made abstract. New Iir and Fir classes made for non-order-specific filtering.
- new TapDelay class
- SubNoise class deleted (same as sub-sampled "ticking" of Noise class)
v4.3.1: (7 December 2007)
- further headerless file support in FileRead
- bug fix in RtWvOut.cpp
- added configure support for MinGW
- updates to RtAudio and RtMidi for MinGW
- changes to channel assignment in demo.cpp
v4.3.0: (13 August 2007)
- an official MIT-like license
- new functionality to automatically update class data when the STK sample rate changes (partly implemented)
- updates for new RtAudio version 4.0
- removed RtDuplex class, users should use RtAudio directly with a callback function
- bug fix in interpolate() function in Stk.h for non-interleaved data
- fixes / improvements to the Granulate class
- fix in Whistle when doing animation
- fixes in BlitSquare for frequency, harmonics, and dc offset
- updates to Makefiles for non-realtime compile
- fix in demo.cpp for voice channel assignment
- updated versions of RtMidi and RtAudio
- updated ASIO files for MinGW compiler
- new FAQ in documentation
- MAT-file bug fix in FileRead class
v4.2.1: (14 October 2005)
- greatly expanded StkFrames functionality (including interpolation and indexing by channel/frame)
- new Granulate granular synthesis class
- new Blit, BlitSaw, and BlitSquare bandlimited waveform classes (thanks to Robin Davies!)
- removed Table class ... all functionality (including interpolation) now in StkFrames and FileRead classes
- revised Socket class (now abstract) and added TcpServer, TcpClient, and UdpSocket subclasses
- added Stk::showWarnings() and Stk::printErrors() functions to dis/enable warning and error printouts
- extracted file I/O functionality to new FileRead and FileWrite classes
- revised WvIn / WvOut class structure (WvIn / WvOut now abstract and file I/O functionality in new FileWvIn / FileWvOut subclasses)
- new SineWave class which calculates its own static table of variable length (no rawwave dependency)
- new sinewave.raw file of length 1024 samples (used to be 256)
- TcpWvIn and TcpWvOut renamed InetWvIn and InetWvOut, with added support for UDP sockets
- fixed bug in WvOut tickFrame( const StkFrames &frames ) function
- fixed bug in demo.cpp when writing output soundfiles without realtime output
- added "binary" open flag to MidiFileIn class for Windows
- fixed oversized MAT-file header in WvOut.cpp
- fixed case statement bug in MidiFileIn.cpp for sysex
- added missing getDelay() function to DelayA.cpp
- fixed modDepth omission in Chorus.cpp
- fixed DC blocker initialization bug in Flute.cpp
- changed Filter class behavior so no default clearing of state when changing coefficients
- bug fixes to RtAudio, especially for Windows DirectSound and ASIO (thanks to Robin Davies)
- bug fixes to RtMidi, especially for Linux (thanks to Pedro Pedro Lopez-Cabanillas)
v4.2.0: (4 October 2004)
- simultaneous multiple audio APIs supported at compile time
- fixed hidden overloaded virtual functions
- new Asymp exponential envelope class
- various changes to better conform to standard C++ programming practices
- MY_FLOAT type converted to StkFloat and changed throughout (use treesed utility to search/replace in old files)
- most example programs rewritten to use an audio callback paradigm (which works better in OS-X)
- new StkFrames class for vectorized multichannel data and associated new tick() functions making use of StkFrames
- new RtMidi class with MIDI output capabilities (API changes)
- new MidiFileIn class for reading MIDI files
- revised Filter classes to use std::vectors for coefficients (API changes)
- revised Messager class (now queues messages for retrieval) (API changes)
- new abstract parent Effect class for various effects
- added setT60 function to all reverbs
- new abstract parent Generator class for various signal sources
- new abstract parent Function class for tables and various non-linear functions
- Skini class completely rewritten (simplified) using the C++ STL (API changes)
- WvOut classes now clip to -1.0 to +1.0 and report out of range
- new Mutex class
- turned Nagle algorithm off by default in Socket class
- error reporting standardized in all classes
v4.1.3: (22 March 2004)
- bug fix in RtAudio for Windows DirectSound output only support
@@ -108,7 +240,7 @@ v3.0: (10 October 1999)
- 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()
- multi-channel data support in WvIn and WvOut classes using MY_MULTI data type (pointer to StkFloat) 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)

View File

@@ -10,7 +10,7 @@ for the Synthesis Toolkit in C++ by Perry R. Cook.
* A SKINI Haiku. *
*********************************
Profound thanks to Dan Trueman, Brad Garton, and
Profound thanks to Dan trueman, Brad Garton, and
Gary Scavone for input on this revision. Thanks
also to MIDI, the NeXT MusicKit, ZIPI and all
the creators and modifiers of these for good bases
@@ -120,7 +120,7 @@ upon/from which to build and depart.
4) C Files Used To Implement SKINI
SKINI.cpp is an object which can either open a SKINI file, and
Skini.cpp is an object which can either open a SKINI file, and
successively read and parse lines of text as SKINI strings, or
accept strings from another object and parse them. The latter
functionality would be used by a socket, pipe, or other connection
@@ -128,11 +128,11 @@ upon/from which to build and depart.
but not restricted to real time.
SKINI.msg should be included by anything wanting to use the
SKINI.cpp object. This is not mandatory, but use of the __SK_blah_
Skini.cpp object. This is not mandatory, but use of the __SK_blah_
symbols which are defined in the .msg file will help to ensure
clarity and consistency when messages are added and changed.
SKINI.tbl is used only by the SKINI parser object (SKINI.cpp).
SKINI.tbl is used only by the SKINI parser object (Skini.cpp).
In the file SKINI.tbl, an array of structures is declared and
assigned values which instruct the parser as to what the message
types are, and what the fields mean for those message types.
@@ -240,7 +240,7 @@ upon/from which to build and depart.
7) The SKINI.tbl File, How Messages are Parsed:
The SKINI.tbl file contains an array of structures which
are accessed by the parser object SKINI.cpp. The struct is:
are accessed by the parser object Skini.cpp. The struct is:
struct SKINISpec { char messageString[32];
long type;
@@ -322,70 +322,67 @@ upon/from which to build and depart.
8) Objects using SKINI
Here's a simple example of code which uses the SKINI object
Here's a simple example of code which uses the Skini object
to read a SKINI file and control a single instrument.
Skini score;
Skini::Message message;
instrument = new Mandolin(50.0);
score = new SKINI(argv[1]);
while(score->getType() > 0) {
tempDouble = score->getDelta();
if (tempDouble < 0) {
tempDouble = - tempDouble;
tempDouble = tempDouble - output.getTime();
if (tempDouble < 0) {
printf("Bad News Here!!! Backward Absolute Time Required.\n");
tempDouble = 0.0;
}
score.setFile( argv[1] );
while ( score.nextMessage( message ) != 0 ) {
tempDouble = message.time;
if (tempDouble < 0) {
tempDouble = - tempDouble;
tempDouble = tempDouble - output.getTime();
if (tempDouble < 0) {
printf("Bad News Here!!! Backward Absolute Time Required.\n");
tempDouble = 0.0;
}
tempLong = (long) (tempDouble * Stk::sampleRate());
for (i=0;i<tempLong;i++) {
output.tick(instrument->tick());
}
tempLong = (long) ( tempDouble * Stk::sampleRate() );
for ( i=0; i<tempLong; i++ ) {
output.tick( instrument->tick() );
}
tempDouble3 = message.floatValues[1] * NORM_MIDI;
if ( message.type == __SK_NoteOn_ ) {
if ( tempDouble3 == 0.0 ) {
tempDouble3 = 0.5;
instrument->noteOff( tempDouble3 );
}
tempDouble3 = score->getByteThree();
if (score->getType()== __SK_NoteOn_ ) {
tempDouble3 *= NORM_MIDI;
if (score->getByteThree() == 0) {
tempDouble3 = 0.5;
instrument->noteOff(tempDouble3);
}
else {
tempLong = (int) score->getByteTwo();
tempDouble2 = Midi2Pitch[tempLong];
instrument->noteOn(tempDouble2,tempDouble3);
}
else {
tempLong = message.intValues[0];
tempDouble2 = Midi2Pitch[tempLong];
instrument->noteOn( tempDouble2, tempDouble3 );
}
else if (score->getType() == __SK_NoteOff_) {
tempDouble3 *= NORM_MIDI;
instrument->noteOff(tempDouble3);
}
else if (score->getType() == __SK_ControlChange_) {
tempLong = score->getByteTwoInt();
instrument->controlChange(tempLong,temp3.0);
}
score->nextMessage();
}
else if ( message.type == __SK_NoteOff_ ) {
instrument->noteOff( tempDouble3 );
}
else if ( message.type == __SK_ControlChange_ ) {
tempLong = message.intValues[0];
instrument->controlChange( tempLong, tempDouble3 );
}
}
When the score (SKINI object) object is created from the
filename in argv[1], the first valid command line is read
from the file and parsed.
When a SKINI score is passed to a Skini object using the
Skini::setFile() function, valid messages are read from
the file and returned using the Skini::nextMessage() function.
The score->getType() retrieves the messageType. If this is
-1, there are no more valid messages in the file and the
synthesis loop terminates. Otherwise, the message type is
returned.
A Skini::Message structure contains all the information parsed
from a single SKINI message. A returned message type of zero
indicates either an invalid message or the end of a scorefile.
getDelta() retrieves the deltaTime until the current message
should occur. If this is greater than 0, synthesis occurs
until the deltaTime has elapsed. If deltaTime is less than
zero, the time is interpreted as absolute time and the output
device is queried as to what time it is now. That is used to
form a deltaTime, and if it's positive we synthesize. If
it's negative, we print an error and pretend this never
happened and we hang around hoping to eventually catch up.
The "time" member of a Skini::Message is the deltaTime until the
current message should occur. If this is greater than 0,
synthesis occurs until the deltaTime has elapsed. If deltaTime is
less than zero, the time is interpreted as absolute time and the
output device is queried as to what time it is now. That is used
to form a deltaTime, and if it's positive we synthesize. If it's
negative, we print an error, pretend this never happened and we
hang around hoping to eventually catch up.
The rest of the code sorts out message types NoteOn, NoteOff
(including NoteOn with velocity 0), and ControlChange. The
code implicitly takes into account the integer type of the
control number, but all other data is treated as double float.
The last line reads and parses the next message in the file.

File diff suppressed because it is too large Load Diff

View File

@@ -1,13 +1,25 @@
/*! \page compile Compiling
The Synthesis ToolKit can be used in a variety of ways, depending on your particular needs. Some people choose the classes they need for a particular project and copy those to their working directory. Others create <TT>Makefiles</TT> which compile project-specific class objects from common <TT>src</TT> and <TT>include</TT> directories. And still others like to compile and link to a common library of object files. STK was not designed with one particular style of use in mind.
The Synthesis ToolKit can be used in a variety of ways, depending on your particular needs. Some people choose the classes they need for a particular project and copy those to their working directory. Others create <TT>Makefiles</TT> that compile project-specific class objects from common <TT>src</TT> and <TT>include</TT> directories. And still others like to compile and link to a common library of object files. STK was not designed with one particular style of use in mind.
\section rtvsnonrt "Realtime" vs. "Non-Realtime"
Most of the Synthesis ToolKit classes are platform independent. That means that they should compile on any reasonably current C++ compiler. The functionality needed for realtime audio and MIDI input/output, as well as realtime control message acquistion, is inherently platform and operating-system (OS) <I>dependent</I>. STK classes which require specific platform/OS support include RtAudio, RtWvOut, RtWvIn, RtDuplex, RtMidi, TcpWvIn, TcpWvOut, Socket, and Thread. These classes currently can only be compiled on Linux, Irix, Macintosh OS X, and Windows systems using the <TT>__LINUX_OSS__</TT>, <TT>__LINUX_ALSA__</TT>, <TT>__IRIX_AL__</TT>, <TT>__MACOSX_CORE__</TT>, <TT>__WINDOWS_DS__</TT>, or <TT>__WINDOWS_ASIO__</TT> preprocessor definitions.
Most of the Synthesis ToolKit classes are platform independent. That
means that they should compile on any reasonably current C++ compiler.
The functionality needed for realtime audio and MIDI input/output, as
well as realtime control message acquistion, is inherently platform
and operating-system (OS) <I>dependent</I>. STK classes that require
specific platform/OS support include RtAudio, RtWvOut, RtWvIn,
RtDuplex, RtMidi, InetWvIn, InetWvOut, Socket, UdpSocket, TcpServer,
TcpClient, Thread, and Mutex. These classes currently can only be
compiled on Linux, Macintosh OS X, and Windows systems.
Without the "realtime" classes, it is still possible to read SKINI scorefiles for control input and to read and write to/from a variety of audio file formats (WAV, SND, AIFF, MAT-file, and RAW). If compiling for a "little-endian" host processor, the <TT>__LITTLE_ENDIAN__</TT> preprocessor definition should be provided.
Without the "realtime" classes, it is still possible to read SKINI
scorefiles for control input and to read and write to/from a variety
of audio file formats (WAV, SND, AIFF, MAT-file, and RAW). If
compiling for a "little-endian" host processor, the
<TT>__LITTLE_ENDIAN__</TT> preprocessor definition should be provided.
\section unix Unix Systems:
@@ -30,42 +42,49 @@ STK compiles with realtime support on the following flavors of the Unix operatin
</TR>
<TR>
<TD>Linux</TD>
<TD>OSS</TD>
<TD>__LINUX_OSS__, __LITTLE_ENDIAN__</TD>
<TD><TT>pthread</TT></TD>
<TD>OSS (version 4.0 only, use ALSA for MIDI support)</TD>
<TD>__LINUX_OSS__, __LINUX_ALSA__, __LITTLE_ENDIAN__</TD>
<TD><TT>asound, pthread</TT></TD>
</TR>
<TR>
<TD>Linux and Macintosh OS-X</TD>
<TD>Jack</TD>
<TD>__UNIX_JACK__, __LITTLE_ENDIAN__</TD>
<TD><TT>asound, pthread, jack</TT></TD>
</TR>
<TR>
<TD>Macintosh OS X</TD>
<TD>CoreAudio</TD>
<TD>__MACOSX_CORE__</TD>
<TD><TT>pthread, stdc++, CoreAudio, CoreMIDI, CoreFoundation</TT></TD>
</TR>
<TR>
<TD>Irix</TD>
<TD>AL</TD>
<TD>__IRIX_AL__</TD>
<TD><TT>audio, pthread</TT></TD>
<TD><TT>pthread, CoreAudio, CoreMidi, CoreFoundation</TT></TD>
</TR>
</TABLE>
</CENTER>
The available C++ compilers on any of these systems can vary.
One approach in using STK is to simply copy the class files needed for a particular program into a project directory. Taking the <TT>sineosc.cpp</TT> example from the previous tutorial chapter, it would be necessary to set up a directory that includes the files <TT>sineosc.cpp</TT>, the rawwave file <TT>sinewave.raw</TT> in a subdirectory called <TT>rawwaves</TT>, and the header and source files for the classes Stk, WvIn, WaveLoop, and WvOut. The program could then be compiled on a Linux system using the GNU g++ compiler as follows:
\code
g++ -Wall -D__LITTLE_ENDIAN__ -o sineosc Stk.cpp WvIn.cpp WaveLoop.cpp WvOut.cpp sineosc.cpp
\endcode
One approach in using STK is to simply copy the class files needed for
a particular program into a project directory. Taking the
<TT>sineosc.cpp</TT> example from the previous tutorial chapter, it
would be necessary to set up a directory that includes the files
<TT>sineosc.cpp</TT>, the rawwave file <TT>sinewave.raw</TT> in a
subdirectory called <TT>rawwaves</TT>, and the header and source files
for the classes Stk, FileRead, FileWrite, FileWvIn, FileLoop, and
FileWvOut. The program could then be compiled on a little-endian
system, such as a PC running Linux, using the GNU g++ compiler as
follows:
\code g++ -Wall -D__LITTLE_ENDIAN__ -o sineosc Stk.cpp FileRead.cpp FileWrite.cpp FileWvIn.cpp FileLoop.cpp FileWvOut.cpp sineosc.cpp \endcode
Note that the <TT>sineosc.cpp</TT> example does not make use of realtime audio or MIDI input/output classes. For programs using any of the STK realtime classes mentioned above, it is necessary to specify an audio/MIDI API preprocessor definition and link with the appropriate libraries or frameworks.
When working with a number of different projects that make use of ToolKit classes, the above approach can become cumbersome (especially when trying to synchronize with new STK releases). Most of the STK projects (e.g., demo, effects, ...) contain <TT>Makefiles</TT> (built by the configure script) which compile project-specific class objects from the distribution <TT>src</TT> and <TT>include</TT> directories. This approach makes it relatively easy when upgrading to a new STK release (by making path substitutions in the <TT>Makefile</TT> or by moving the projects to a similar relative path within the new STK source tree). A <TT>Makefile</TT> is provided in the <TT>projects/examples</TT> directory for compiling all the tutorial programs, as well as other example programs. To compile the <TT>sineosc.cpp</TT> program, for example, one need only type <TT>make sineosc</TT> from within the <TT>projects/examples</TT> directory. Note that this particular <TT>Makefile</TT> depends on a static library, as described in the next section.
When working with a number of different projects that make use of ToolKit classes, the above approach can become cumbersome (especially when trying to synchronize with new STK releases). Most of the STK projects (e.g., demo, effects, ...) contain <TT>Makefiles</TT> (built by the configure script) that compile project-specific class objects from the distribution <TT>src</TT> and <TT>include</TT> directories. This approach makes it relatively easy when upgrading to a new STK release (by making path substitutions in the <TT>Makefile</TT> or by moving the projects to a similar relative path within the new STK source tree). A <TT>Makefile</TT> is provided in the <TT>projects/examples</TT> directory for compiling all the tutorial programs, as well as other example programs. To compile the <TT>sineosc.cpp</TT> program, for example, one need only type <TT>make sineosc</TT> from within the <TT>projects/examples</TT> directory.
\subsection library Library Use:
The STK distribution provides a <TT>Makefile</TT> that can be used on Unix systems to build a static library. After unpacking the distribution (<TT>tar -xzf stk-4.x.tar.gz</TT>), run the configure script by typing <TT>./configure</TT> from the top level distribution directory (see the INSTALL file in the same directory for more information). Then from within the <TT>src</TT> directory, type <TT>make</TT>. After a successful build, you may wish to move the library (<TT>libstk.a</TT>) and the contents of the <TT>include</TT> directory to standard library and include search paths on your system. For example, the linux RPM distribution of STK puts the library in <TT>/usr/lib/</TT> and the STK header files in <TT>/usr/include/stk/</TT>.
The STK distribution provides a <TT>Makefile</TT> that can be used on Unix systems to build a static library. After unpacking the distribution (<TT>tar -xzf stk-4.x.x.tar.gz</TT>), run the configure script by typing <TT>./configure</TT> from the top level distribution directory (see the INSTALL file in the same directory for more information). Then from within the <TT>src</TT> directory, type <TT>make</TT>. After a successful build, you may wish to move the library (<TT>libstk.a</TT>) and the contents of the <TT>include</TT> directory to standard library and include search paths on your system. For example, the linux RPM distribution of STK puts the library in <TT>/usr/lib/</TT> and the STK header files in <TT>/usr/include/stk/</TT>.
Assuming the library is located in a standard search path and the header files are located in <TT>/usr/include/stk/</TT>, the <TT>sineosc.cpp</TT> example from the previous tutorial chapter can be compiled on a Linux system using the GNU g++ compiler as follows:
Assuming the library is located in a standard search path and the header files are located in <TT>/usr/include/stk/</TT>, the <TT>sineosc.cpp</TT> example from the previous tutorial chapter can be compiled on a little-endian system using the GNU g++ compiler as follows:
\code
g++ -Wall -D__LITTLE_ENDIAN__ -I/usr/include/stk -o sineosc sineosc.cpp -lstk
@@ -74,8 +93,8 @@ g++ -Wall -D__LITTLE_ENDIAN__ -I/usr/include/stk -o sineosc sineosc.cpp -lstk
With the header files in a standard search path, it is possible to modify the <TT>\#include</TT> statements in the <TT>sineosc.cpp</TT> program as follows:
\code
#include "stk/WaveLoop.h"
#include "stk/WvOut.h"
#include "stk/FileLoop.h"
#include "stk/FileWvOut.h"
\endcode
and then compile without an explicit include path argument to the compiler:
@@ -87,13 +106,22 @@ g++ -Wall -D__LITTLE_ENDIAN__ -o sineosc sineosc.cpp -lstk
\section compileWin Windows:
STK has been tested on Windows platforms using the Visual C++ compiler only. It is assumed here that you're familiar with Visual C++ and its particular idiosyncrasies.
STK has been tested on Windows platforms using the Visual .NET compiler
only. It is assumed here that you're familiar with Visual C++ and its
particular idiosyncrasies. STK won't compile in Visual C++ 6.0 any more.
The approach when using Visual C++ is to build a project which includes the necessary ToolKit files from the distribution <TT>src</TT> and <TT>include</TT> directories. For the example program from the previous tutorial chapter, create a VC++ console application project, add the Stk, WvIn, WaveLoop, and WvOut class files, as well as <TT>sineosc.cpp</TT>, and make sure the <TT>sinewave.raw</TT> file is in the subdirectory <TT>rawwaves</TT>.
The approach when using Visual C++ is to build a project that
includes the necessary ToolKit files from the distribution
<TT>src</TT> and <TT>include</TT> directories. For the example
program from the previous tutorial chapter, create a VC++ console
application project, add the Stk, FileRead, FileWrite, WvIn, FileWvIn,
FileLoop, WvOut, and FileWvOut class files, as well as
<TT>sineosc.cpp</TT>, and make sure the <TT>sinewave.raw</TT> file is
in the subdirectory <TT>rawwaves</TT>.
For programs using any of the STK realtime classes mentioned above, it is necessary to link with the DirectSound (<TT>dsound.lib</TT>), <TT>winmm.lib</TT>, and <TT>Wsock32.lib</TT> libraries, select the multithreaded library, and provide the <TT>__LITTLE_ENDIAN__</TT> and <TT>__WINDOWS_DS__</TT> preprocessor definitions.
For programs using any of the STK realtime classes mentioned above, it is necessary to link with the DirectSound (<TT>dsound.lib</TT>), <TT>winmm.lib</TT>, and <TT>Wsock32.lib</TT> libraries, select the multithreaded library, and provide the <TT>__LITTLE_ENDIAN__</TT>, <TT>__WINDOWS_DS__</TT>, and <TT>__WINDOWS_MM__</TT> preprocessor definitions.
For Steinberg ASIO support, use the <TT>__WINDOWS_ASIO__</TT> preprocessor definition, include all the files in the <TT>src/asio/</TT> directory (i.e., <TT>asio.h,cpp</TT>, <TT>asiodrivers.h,cpp</TT>, ...), and link with the <TT>winmm.lib</TT>, and <TT>Wsock32.lib</TT> libraries.
For Steinberg ASIO support, use the <TT>__WINDOWS_ASIO__</TT> preprocessor definition (and the <TT>__WINDOWS_MM__</TT> definition for RtMidi support), include all the files in the <TT>src/asio/</TT> directory (i.e., <TT>asio.h,cpp</TT>, <TT>asiodrivers.h,cpp</TT>, ...), and link with the <TT>winmm.lib</TT>, and <TT>Wsock32.lib</TT> libraries.
[<A HREF="realtime.html">Next tutorial</A>] &nbsp; [<A HREF="tutorial.html">Main tutorial page</A>]
[<A HREF="tutorial.html">Main tutorial page</A>] &nbsp; [<A HREF="filtering.html">Next tutorial</A>]
*/

View File

@@ -17,114 +17,38 @@ StringDetune 0.100000 2 12.0
NoteOff 1.000000 2 69.0 64.0
\endcode
MIDI messages (with the exception of Sysex) are easily represented within the SKINI protocol.
MIDI messages are easily represented within the SKINI protocol.
The class Messager can be used to acquire and parse MIDI messages from a MIDI device and SKINI messages from STDIN and socket connections. Many of the example programs included with the ToolKit distribution use a Messager instance to accept control input from the accompanying tcl/tk graphical user interfaces, from external MIDI devices, or from SKINI scorefiles.
The class stk::Messager can be used to acquire and parse MIDI messages
from a MIDI device and SKINI messages from STDIN and socket
connections. Incoming messages are acquired asynchronously and saved
to an internal message queue of stk::Skini::Message types (MIDI
messages are converted to the stk::Skini:Message format). The user
then uses the stk::Messager:popMessage() function to retrieve incoming
control messages. This function does not block, instead returning a
message type of zero when no more messages are in the queue. Many of
the example programs included with the ToolKit distribution use a
stk::Messager instance to accept control input from the accompanying tcl/tk
graphical user interfaces, from external MIDI devices, or from SKINI
scorefiles.
In the following example, we'll modify the <TT>bethree.cpp</TT> program from the previous tutorial chapter and incorporate a Messager class to allow control via a SKINI scorefile.
In the following example, we'll modify the <TT>bethree.cpp</TT> program from the previous tutorial chapter and incorporate a stk::Messager class to allow control via SKINI messages read from a SKINI file.
\include controlbee.cpp
A realtime control message will usually have a delta time of zero, in which case it is processed as soon as possible. Non-realtime messages, normally from a scorefile, will usually have non-zero delta times. The scheme used in this example is designed to work for both scorefile and realtime input types. When no message is available from the queue, the instrument is "ticked" for DELTA_CONTROL_TICKS and then the queue is checked again. The value of DELTA_CONTROL_TICKS roughly defines the program "control rate" in a realtime context, though multiple available messages in the queue are processed in immediate succession when their delta time values are zero.
The \c processMessage() function centralizes the handling of control messages. Other control update schemes can be implemented, perhaps using a separate thread or in the \c main() function, and this function should work in any context.
Assuming the program is compiled as <TT>controlbee</TT> and the SKINI scorefile <A HREF="tutorial/bookert.ski"><TT>bookert.ski</TT></A> is in the <TT>scores</TT> directory, the program can be run as:
\code
// controlbee.cpp
#include "BeeThree.h"
#include "RtWvOut.h"
#include "Messager.h"
#include "SKINI.msg"
#include <math.h>
int main()
{
// Set the global sample rate before creating class instances.
Stk::setSampleRate( 44100.0 );
Instrmnt *instrument = 0;
RtWvOut *output = 0;
Messager *messager = 0;
bool done = FALSE;
try {
// Define and load the BeeThree instrument
instrument = new BeeThree();
// Define and open the default realtime output device for one-channel playback
output = new RtWvOut(1);
}
catch (StkError &) {
goto cleanup;
}
try {
// Create a Messager instance to read from a redirected SKINI scorefile.
messager = new Messager();
}
catch (StkError &) {
goto cleanup;
}
// Play the instrument until the end of the scorefile.
int i, nTicks, type;
MY_FLOAT byte2, byte3, frequency;
while (!done) {
// Look for new messages and return a delta time (in samples).
type = messager->nextMessage();
if (type < 0)
done = TRUE;
nTicks = messager->getDelta();
try {
for ( i=0; i<nTicks; i++ )
output->tick( instrument->tick() );
}
catch (StkError &) {
goto cleanup;
}
if ( type > 0 ) {
// Process the new control message.
byte2 = messager->getByteTwo();
byte3 = messager->getByteThree();
switch(type) {
case __SK_NoteOn_:
frequency = (MY_FLOAT) 220.0 * pow( 2.0, (byte2 - 57.0) / 12.0 );
instrument->noteOn( frequency, byte3 * ONE_OVER_128 );
break;
case __SK_NoteOff_:
instrument->noteOff( byte3 * ONE_OVER_128 );
break;
case __SK_ControlChange_:
instrument->controlChange( (int) byte2, byte3 );
break;
case __SK_AfterTouch_:
instrument->controlChange( 128, byte2 );
break;
}
}
}
cleanup:
delete instrument;
delete output;
delete messager;
return 0;
}
\endcode
Assuming the program is compiled as <TT>controlbee</TT> and the SKINI scorefile <A HREF="tutorial/bookert.ski"><TT>bookert.ski</TT></A> is in the <TT>scores</TT> directory, the scorefile could be redirected to the program as:
\code
controlbee < scores/bookert.ski
controlbee scores/bookert.ski
\endcode
Only a few basic SKINI message type case statements are included in this example. It is easy to extend the program to support a much more elaborate set of instrument control parameters.
This example could also be easily extended to accept "realtime" control input messages via STDIN, socket, or MIDI connections. The Messager class constructor takes an optional argument consisting of a bitmask of the following options: <TT>STK_PIPE</TT>, <TT>STK_SOCKET</TT>, and/or <TT>STK_MIDI</TT>.
This example could also be easily extended to accept "realtime" control input messages via pipe, socket or MIDI connections. The stk::Messager class provides stk::Messager::startStdInput(), stk::Messager::startSocketInput(), and stk::Messager::startMidiInput() functions for this purpose.
[<A HREF="multichannel.html">Next tutorial</A>] &nbsp; [<A HREF="tutorial.html">Main tutorial page</A>]
[<A HREF="tutorial.html">Main tutorial page</A>] &nbsp; [<A HREF="multichannel.html">Next tutorial</A>]
*/

74
doc/doxygen/crealtime.txt Normal file
View File

@@ -0,0 +1,74 @@
/*! \page crealtime Realtime Audio (callback)
An alternative scheme for audio input/output is to define a specific
function in which audio computations are performed and to let the
audio system call this function when more input/output data can be
accepted by the hardware (referred to as a callback scheme). In this
section, we show how the previous <TT>rtsine.cpp</TT> program can be
modified to work in a callback scenario. There is no "single-sample"
interface for this functionality. The callback function will be
invoked automatically by the audio system controller (RtAudio) when
new data is needed and it is necessary to compute a full audio buffer
of samples at that time (see \ref callback for further information).
The previous section described the use of the stk::RtWvOut class for
realtime audio output. The stk::RtWvOut::tick() function writes data to a
large ring-buffer, from which data is periodically written to the
computer's audio hardware via an underlying callback routine.
\include crtsine.cpp
The sinusoidal oscillator is created as before. The instantiation of
RtAudio requires quite a few more parameters, including output/input
device and channel specifiers, the data format, and the desired buffer
length (in frames). In this example, we request a single output
channel using the default output device, zero channels of input, the
RtAudio data format which corresponds to an <tt>StkFloat</tt>, and the
RT_BUFFER_SIZE defined in Stk.h. The \c bufferFrames argument is an
API-dependent buffering parameter (see RtAudio for further
information).
We also provide the audio system controller with a pointer to our
callback function and an optional pointer to data that will be made
available in the callback. In this example, we need to pass only the
pointer to the oscillator. In more complex programs, it is typically
necessary to put all shared data in a <tt>struct</tt> (see the next
tutorial program for an example) or make use of global variables.
Our callback routine is the \c tick() function. Function arguments
include pointers to the audio input and output data buffers, the
buffer size (in frames), a stream time argument, a status argument to
test for over/underruns, and the data pointer passed in the
openStream() function (if it exists). It is necessary to cast these
pointers to their corresponding data types before use. Our tick()
routine simply "ticks" the oscillator for \c nBufferFrames counts and
writes the result into the audio data buffer before returning.
The \c main() function blocks at the std::cin.get() call until the
user hits the "enter" key, after which the audio controller is shut
down and program execution ends.
\section callback Blocking vs. Callbacks
Prior to version 4.2.0, all STK example projects and programs used
blocking audio input/output functionality (typically with the RtWvIn,
RtWvOut, or RtDuplex classes). In many instances, a blocking scheme
results in a clearer and more straight-forward program structure.
Within a graphical user interface (GUI) programming context, however,
callback routines are often more natural.
In order to allow all STK programs to function with equal proficiency
on all supported computer platforms, a decision was made to modify the
example projects to use audio callback routines. The result is a more
complicated code structure, which is unfortunate given that we
generally strive to make STK code as clear as possible for educational
purposes. This was especially an issue with the demo program because
it is designed to function in both realtime and non-realtime contexts.
The use of global variables has been avoided by defining data
structures to hold all variables that must be accessible to the
callback routine and other functions. Alternative schemes for making
control updates could be designed depending on particular program
needs and constraints.
[<A HREF="tutorial.html">Main tutorial page</A>] &nbsp; [<A HREF="instruments.html">Next tutorial</A>]
*/

View File

@@ -1,15 +1,167 @@
/*! \page download Download and Release Notes
/*! \page download Download, Release Notes, and Bug Fixes
\section down Download Version 4.5.0 (26 April 2014):
<B>Version 4.1.3, 22 March 2004</B><P>
<UL>
<LI><A HREF="http://www-ccrma.stanford.edu/software/stk/release/stk-4.1.3.tar.gz">Source distribution</A></LI>
<LI><A HREF="http://www-ccrma.stanford.edu/software/stk/release/stk-4.1.3.binaries.tar.gz">Source with precompiled Windows binaries</A></LI>
<LI><A HREF="http://www-ccrma.stanford.edu/planetccrma/software/">Linux RPMs from Planet CCRMA</A></LI>
<LI><A HREF="http://ccrma.stanford.edu/software/stk/release/stk-4.5.0.tar.gz">Source distribution</A></LI>
</UL>
\section notes Release Notes:
\subsection v4dot5dot0 Version 4.5.0
<ul>
<li>Updated versions of RtAudio and RtMidi, with associated renaming of RtError class to either RtAudioError or RtMidiError</li>
<li>New iOS project files (thanks to Ariel Elkin)</li>
<li>Bug fix in FreeVerb that could cause crackling for stereo input</li>
<li>Various bug fixes and updates to minimize compiler warnings</li>
<li>ADSR fix for decay/release time calculations</li>
<li>Various updates to build system</li>
</ul>
\subsection v4dot4dot4 Version 4.4.4
<ul>
<li>New FreeVerb class (thanks to Greg Burlet)</li>
<li>New Guitar class</li>
<li>New electric guitar project</li>
<li>Updated versions of RtAudio and RtMidi</li>
<li>Cleaned / revised Shakers class</li>
<li>Bug fix in LentPitShift</li>
<li>Bug fix in Echo constructor</li>
<li>Bug fix in FileWvIn (file size when chunking)</li>
<li>Bug fix in StkFrames copy constructor</li>
</ul>
\subsection v4dot4dot3 Version 4.4.3
<ul>
<li>Changed SINT24 to be lower 3 bytes of 32-bit word.</li>
<li>Bug fixes to vectorized tick functions in Effects classes.</li>
<li>Updated versions of RtAudio and RtMidi.</li>
<li>Bug fixes in ADSR and Envelope classes.</li>
<li>Updates to the internal argument checking and reporting scheme.</li>
<li>Updates to Bowed class (thanks to Esteban Maestre!).</li>
<li>Fixes for 24-bit support in FileRead and FileWrite.</li>
<li>Added WAVE_FORMAT_EXTENSIBLE support in FileWrite.</li>
<li>Added sample rate variable reading and writing for MAT-files in FileRead and FileWrite.</li>
</ul>
\subsection v4dot4dot2 Version 4.4.2
<ul>
<li>Added various header file includes for newer compilers.</li>
<li>Updates to RtAudio and RtMidi.</li>
<li>New LentPitShift class (thanks to Francois Germain).</li>
<li>Bug fixes in Voicer class (thanks Richard Dobson!).</li>
<li>Added Makefile.in to compile library and all projects, as well as clean and distclean.</li>
</ul>
\subsection v4dot4dot1 Version 4.4.1
<ul>
<li>Added multi-channel/frame tick() virtual function to WvIn and WvOut abstract base classes (required update to RtWvOut class).</li>
<li>Updated configure script to select g++ compiler by default.</li>
<li>In demo.cpp: removed voicer grouping for messages, fixing polyphony when messages are on the same MIDI/SKINI channel.</li>
<li>Updates to RtAudio and RtMidi.</li>
</ul>
\subsection v4dot4dot0 Version 4.4.0
<ul>
<li>All classes embedded in the "stk" namespace (except RtAudio, RtMidi, and RtError).</li>
<li>Class WaveLoop renamed FileLoop.</li>
<li>Significant efficiency improvements via code restructuring and inlining.</li>
<li>Some class source (.cpp) files deleted as part of inlining (Generator, Filter, Function, WvIn, WvOut, Effect, Instrmnt, BowTable, ReedTable, JetTable, Vector3D).</li>
<li>Updates to RtAudio and RtMidi.</li>
<li>Previous "tickFrame()" functions renamed "tick" for more consistent API.</li>
<li>More consistent and scalable approach to multichannel data and computations.</li>
<li>Multichannel support added to Granulate class.</li>
<li>Filter class made abstract. New Iir and Fir classes made for non-order-specific filtering.</li>
<li>New TapDelay class.</li>
<li>SubNoise class deleted (same as sub-sampled "ticking" of Noise class).</li>
</ul>
\subsection v4dot3dot1 Version 4.3.1
<ul>
<li>Further headerless file support in FileRead.</li>
<li>Bug fix in RtWvOut.cpp.</li>
<li>Added configure support for MinGW.</li>
<li>Updates to RtAudio and RtMidi for MinGW.</li>
<li>Changes to channel assignment in demo.cpp.</li>
</ul>
\subsection v4dot3dot0 Version 4.3.0
<ul>
<li>An official MIT-like license.</li>
<li>New functionality to automatically update class data when the STK sample rate changes (partly implemented).</li>
<li>Updates for new RtAudio version 4.0.</li>
<li>Removed RtDuplex class, users should use RtAudio directly with a callback function.</li>
<li>Bug fix in interpolate() function in Stk.h for non-interleaved data.</li>
<li>Fixes / improvements to the Granulate class.</li>
<li>Fix in Whistle when doing animation.</li>
<li>Fixes in BlitSquare for frequency, harmonics, and dc offset.</li>
<li>Updates to Makefiles for non-realtime compile.</li>
<li>Fix in demo.cpp for voice channel assignment.</li>
<li>Updated versions of RtMidi and RtAudio.</li>
<li>Updated ASIO files for MinGW compiler.</li>
<li>New FAQ in documentation.</li>
<li>MAT-file bug fix in FileRead class.</li>
</ul>
\subsection v4dot2dot1 Version 4.2.1
<ul>
<li>Greatly expanded StkFrames functionality (including interpolation and indexing by channel/frame).</li>
<li>New Blit, BlitSaw, and BlitSquare bandlimited waveform classes (thanks to Robin Davies!).</li>
<li>New Granulate granular synthesis class.</li>
<li>Removed Table class ... all functionality (including interpolation) now in StkFrames and FileRead classes.</li>
<li>Revised Socket class (now abstract) and added TcpServer, TcpClient, and UdpSocket subclasses.</li>
<li>Added Stk::showWarnings() and Stk::printErrors() functions to dis/enable warning and error printouts.</li>
<li>Extracted file I/O functionality to FileRead and FileWrite classes.</li>
<li>Revised WvIn / WvOut class structure (WvIn / WvOut now abstract and file I/O functionality in new FileWvIn / FileWvOut subclasses).</li>
<li>New SineWave class which calculates its own static table of variable length (no rawwave dependency).</li>
<li>New sinewave.raw file of length 1024 samples (used to be 256).</li>
<li>TcpWvIn and TcpWvOut renamed InetWvIn and InetWvOut, with added support for UDP sockets.</li>
<li>Fixed bug in WvOut tickFrame( const StkFrames &frames ) function.</li>
<li>Fixed bug in demo.cpp when writing output soundfiles without realtime output.</li>
<li>Added "binary" open flag to MidiFileIn class for Windows.</li>
<li>Fixed oversized MAT-file header in WvOut.cpp</li>
<li>Fixed case statement bug in MidiFileIn.cpp for sysex.</li>
<li>Added missing getDelay() function to DelayA.cpp.</li>
<li>Fixed modDepth omission in Chorus.cpp.</li>
<li>Fixed DC blocker initialization bug in Flute.cpp.</li>
<li>Changed Filter class behavior so no default clearing of state when changing coefficients.</li>
<li>Fixes to RtAudio, especially for Windows DirectSound and ASIO (thanks to Robin Davies).</li>
</ul>
\subsection v4dot2dot0 Version 4.2.0
<ul>
<li>Simultaneous multiple audio APIs supported at compile time.</li>
<li>Various changes to better conform to standard C++ programming practices.</li>
<li>Fixed hidden overloaded virtual functions.</li>
<li>New Asymp exponential envelope class.</li>
<li><tt>MY_FLOAT</tt> type converted to <tt>StkFloat</tt> and changed throughout (use \c treesed utility to search/replace in old files).</li>
<li>Most example programs rewritten to use an audio callback paradigm (which works better in OS-X).</li>
<li>New StkFrames class for vectorized multichannel data and associated new tick() functions making use of StkFrames.</li>
<li>New RtMidi class with MIDI output capabilities (API changes).</li>
<li>New MidiFileIn class for reading MIDI files.</li>
<li>Revised Filter classes to use std::vectors for coefficients (API changes).</li>
<li>Revised Messager class (API changes).</li>
<li>New abstract parent Effect class for various effects.</li>
<li>New abstract parent Generator class for various signal sources.</li>
<li>New abstract parent Function class for tables and various non-linear functions.</li>
<li>Skini class completely rewritten (simplified) using the C++ STL (API changes).</li>
<li>WvOut classes now clip to -1.0 to +1.0 and report out of range.</li>
<li>New Mutex class.</li>
<li>Turned Nagle algorithm off by default in Socket class.</li>
<li>Error reporting standardized in all classes.</li>
</ul>
\subsection v4dot1dot3 Version 4.1.3
<ul>
@@ -30,7 +182,7 @@
<li>Update to the contentsAt() method of Delay class.</li>
<li>WAV file fixes (8-bit) in WvIn and WvOut classes.</li>
<li>Configure script changes.</li>
<li>Updated <iostream> include statements and appended "std::" as necessary throughout for compatibility with gcc 3.</li>
<li>Updated \<iostream\> include statements and appended "std::" as necessary throughout for compatibility with gcc 3.</li>
</UL>
\subsection v4dot1dot1 Version 4.1.1
@@ -138,7 +290,7 @@
<LI>Added RawWvOut class.</LI>
<LI>New WvIn class with RawWvIn, SndWvIn, WavWvIn, MatWvIn, and RTWvIn subclasses.</LI>
<LI>Removed RawWave, RawShot, RawInterp, and RawLoop classes (supplanted by RawWvIn).</LI>
<LI>Multi-channel data support in WvIn and WvOut classes using MY_MULTI data type (pointer to MY_FLOAT) and the methods mtick() and mlastOutput().</LI>
<LI>Multi-channel data support in WvIn and WvOut classes using MY_MULTI data type (pointer to StkFloat) and the methods mtick() and mlastOutput().</LI>
<LI>Now writing to primary buffer under Windoze when allowed by hardware.</LI>
<LI>Cleaned up Object.h a bit.</LI>
<LI>Pulled various utility and thread functions out of syntmono.cpp (to aid readability of the code).</LI>
@@ -160,11 +312,11 @@
<UL>
<LI>Unification of the capabilities of STK across the various platforms. All of the previous SGI functionality has been ported to Linux and Windows, including realtime sound output and MIDI input.</LI>
<LI>MIDI input (with optional time-stamping) supported on SGI, Linux (OSS device drivers only), and Windows operating systems. Time stamping under IRIX and Windows is quantized to milliseconds and under Linux to hundredths of a second.</LI>
<LI>Various Sound Output Options - .wav, .snd, and .mat (Matlab MAT-file) soundfile outputs are supported on all operating systems. I hacked out the MAT-file structure, so you don't have to include any platform-specific libraries. Realtime sound output is provided as well, except under NeXTStep. </LI>
<LI>Various Sound Output Options - .wav, .snd, and .mat (Matlab MAT-file) soundfile outputs are supported on all operating systems. I hacked out the MAT-file structure, so you don't have to include any platform-specific libraries. Realtime sound output is provided as well, except under NeXTStep.</LI>
<LI>Multiple Reverberator Implementations - Reverb subclasses of JCRev and NRev (popular reverberator implementations from CCRMA) have been written. Perry's original reverb implementation still exists as PRCRev. All reverberators now take a T60 initializer argument.</LI>
<LI>MD2SKINI - A program which parses a MIDI input stream and spits out SKINI code. The output of MD2SKINI is typically piped into an STK instrument executable (eg. <FONT FACE="Geneva">MD2SKINI | syntmono Clarinet -r -i</FONT>). In addition, you can supply a filename argument to MD2SKINI and have it simultaneously record a SKINI score file for future reuse.
<LI>Modifications to <I>Object.h</I> for OS_TYPE compilation dependencies. <I>Makefile</I> automatically determines OS_TYPE when invoked (if you have the GNU makefile utilities installed on your system).
<LI>A single distribution for all platforms. The Unix and Windows versions have been merged into a single set of classes. Makefiles and Visual C++ workspace/project files are provided for compiling.
<LI>MD2SKINI - A program which parses a MIDI input stream and spits out SKINI code. The output of MD2SKINI is typically piped into an STK instrument executable (eg. <tt>MD2SKINI | syntmono Clarinet -r -i</tt>). In addition, you can supply a filename argument to MD2SKINI and have it simultaneously record a SKINI score file for future reuse.</LI>
<LI>Modifications to <I>Object.h</I> for OS_TYPE compilation dependencies. <I>Makefile</I> automatically determines OS_TYPE when invoked (if you have the GNU makefile utilities installed on your system).</LI>
<LI>A single distribution for all platforms. The Unix and Windows versions have been merged into a single set of classes. Makefiles and Visual C++ workspace/project files are provided for compiling.</LI>
</UL>
*/

80
doc/doxygen/faq.txt Normal file
View File

@@ -0,0 +1,80 @@
/*! \page faq Frequently Asked Questions
- \ref license
- \ref filerate
- \ref endianness
- \ref xwindows
\section license Does STK have a license?
Yes, we finally made something official for release 4.3.0. It is listed in the Stk class and a few other places in the distribution, but I'll repeat it here for clarity:
\verbatim
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. 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.
STK WWW site: http://ccrma.stanford.edu/software/stk/
The Synthesis ToolKit in C++ (STK)
Copyright (c) 1995--2014 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.
\endverbatim
\section filerate Why is my file sample rate wrong?
When the FileWvIn class loads a soundfile, it automatically sets its internal read increment based on the soundfile rate and the current STK sample rate. For example, if the current STK sample rate is 44100 Hz and the soundfile rate is 22050 Hz, the read increment, or rate, will be set to 0.5 and the file will be interpolated so that is sounds correct at 44100 Hz. For most cases, this works fine. However, consider the following example:
\code
FileWvIn input( "infile" ); // read an input soundfile
StkFloat sampleRate = input.getFileRate();
Stk::setSampleRate( sampleRate ); // set a new STK sample rate based on the file rate
\endcode
With version 4.3 and higher of STK, the FileWvIn class will be notified of a sample rate change and it will automatically adjust its read rate accordingly. Previous versions of STK did not perform this change and thus, the read rate could end up being incorrect. If you do not want FileWvIn to perform this automatic adjustment, you can call the \c ignoreSampleRateChange() function for a given class instance.
\section endianness Why does the sound I generated with STK sound like *&#@!?
If the resultant sound generated by an STK program sounds like noise (and you're not doing an MLS experiment), the problem is likely related to the byte "endianness" of your computer. By default, STK assumes "big endian" byte order. If you are working with STK classes on a PC (Windows or Linux), you \e must define the <TT>__LITTLE_ENDIAN__</TT> preprocessor definition \e before compiling. If after reading this you realize you need to make this change, do not forget to recompile all STK classes from scratch.
\section xwindows Why do I get a Tk display error message?
The following error may be printed to your terminal window (depending on the version of the tcl/tk interpreter you are running) if you attempt to start an STK tcl/tk interface without the X Server first running:
\code
Application initialization failed: this isn't a Tk applicationcouldn't connect to display ":0.0"
\endcode
Simply start your X server and then try the command again.
*/

91
doc/doxygen/filtering.txt Normal file
View File

@@ -0,0 +1,91 @@
/*! \page filtering Using Filters
In this section, we demonstrate the use of a few of the STK filter classes. The stk::Iir class provides functionality to implement a generalized infinite impulse response (IIR) digital filter, similar to the \c filter function in Matlab. In this example, we create an stk::Iir instance and initialize it with specific numerator and denominator coefficients. We then compute its impulse response for 20 samples.
\code
#include "Iir.h"
using namespace stk;
int main()
{
StkFrames output( 20, 1 ); // initialize StkFrames to 20 frames and 1 channel (default: interleaved)
output[0] = 1.0;
std::vector<StkFloat> numerator( 5, 0.1 ); // create and initialize numerator coefficients
std::vector<StkFloat> denominator; // create empty denominator coefficients
denominator.push_back( 1.0 ); // populate our denomintor values
denominator.push_back( 0.3 );
denominator.push_back( -0.5 );
Iir filter( numerator, denominator );
filter.tick( output );
for ( unsigned int i=0; i<output.size(); i++ ) {
std::cout << "i = " << i << " : output = " << output[i] << std::endl;
}
return 0;
}
\endcode
The stk::Iir class implements the standard difference equation
\code
a[0]*y[n] = b[0]*x[n] + ... + b[nb]*x[n-nb] - a[1]*y[n-1] - ... - a[na]*y[n-na],
\endcode
where "b" values are numerator coefficients and "a" values are denominator coefficients. Note that if the first denominator coefficient is not 1.0, the Iir class automatically normalizes all filter coefficients by that value. The coefficient values are passed to the Iir class via a C++ <a href="http://www.roguewave.com/support/docs/sourcepro/stdlibref/vector.html">vector</a>, a container object provided by the C++ Standard Library.
Most STK classes use more specific types of digital filters, such as the stk::OneZero, stk::OnePole, stk::TwoPole, or stk::BiQuad varieties. These classes inherit from the stk::Filter abstract base class and provide specific functionality particular to their use, as well as functions to independently control individual coefficient values.
\section reson Resonances:
The STK stk::BiQuad and stk::TwoPole classes provide functionality for creating resonance filters. The following example demonstrates how to create a resonance centered at 440 Hz that is used to filter the output of a stk::Noise generator.
\code
#include "BiQuad.h"
#include "Noise.h"
using namespace stk;
int main()
{
StkFrames output( 20, 1 ); // initialize StkFrames to 20 frames and 1 channel (default: interleaved)
Noise noise;
BiQuad biquad;
biquad.setResonance( 440.0, 0.98, true ); // automatically normalize for unity peak gain
for ( unsigned int i=0; i<output.size(); i++ ) {
output[i] = biquad.tick( noise.tick() ); // single-sample computations
std::cout << "i = " << i << " : output = " << output[i] << std::endl;
}
return 0;
}
\endcode
By passing a boolian value of \c true as the third argument to the stk::BiQuad::setResonance() function, the filter coefficients are automatically scaled to achieve unity gain at the resonance peak frequency. The previous code could be easily modified for "vector-based" calculations:
\code
#include "BiQuad.h"
#include "Noise.h"
using namespace stk;
int main()
{
StkFrames output( 20, 1 ); // initialize StkFrames to 20 frames and 1 channel (default: interleaved)
Noise noise;
BiQuad biquad;
biquad.setResonance( 440.0, 0.98, true ); // automatically normalize for unity peak gain
biquad.tick( noise.tick( output ) ); // vector-based computations
for ( unsigned int i=0; i<output.size(); i++ ) {
std::cout << "i = " << i << " : output = " << output[i] << std::endl;
}
return 0;
}
\endcode
[<A HREF="tutorial.html">Main tutorial page</A>] &nbsp; [<A HREF="realtime.html">Next tutorial</A>]
*/

View File

@@ -1,8 +1,8 @@
<HR>
<table>
<tr><td><A HREF="http://www-ccrma.stanford.edu/software/stk/"><I>The Synthesis ToolKit in C++ (STK)</I></A></td></tr>
<tr><td>&copy;1995-2004 Perry R. Cook and Gary P. Scavone. All Rights Reserved.</td></tr>
<tr><td><A HREF="http://ccrma.stanford.edu/software/stk/"><I>The Synthesis ToolKit in C++ (STK)</I></A></td></tr>
<tr><td>&copy;1995--2014 Perry R. Cook and Gary P. Scavone. All Rights Reserved.</td></tr>
</table>
</BODY>

View File

@@ -0,0 +1,65 @@
/*! \page fundamentals STK Fundamentals
The Synthesis ToolKit is implemented in the C++ programming language. STK does not attempt to provide a new programming environment or paradigm but rather provides a set of objects that can be used within a normal C++ programming framework. Therefore, it is expected that users of STK will have some familiarity with C/C++ programming concepts. That said, the STK classes do have some particular idiosyncrasies that we will mention here. Starting with STK version 4.4, all STK classes except RtAudio and RtMidi are defined within the stk namespace.
\section Signal Computations:
Audio and control signals throughout STK use a floating-point data type, <tt>StkFloat</tt>, the exact precision of which can be controlled via a typedef statement in Stk.h. By default, an StkFloat is a double-precision floating-point value. Thus, the ToolKit can use any normalization scheme desired. The base instruments and algorithms are implemented with a general audio sample dynamic maximum of +/-1.0.
In general, the computation and/or passing of values is performed on a "single-sample" basis. For example, the stk::Noise class outputs random floating-point numbers in the range +/-1.0. The computation of such values occurs in the stk::Noise::tick() function. The following program will generate 20 random floating-point (<tt>StkFloat</tt>) values in the range -1.0 to +1.0:
\code
#include "Noise.h"
using namespace stk;
int main()
{
StkFloat output;
Noise noise;
for ( unsigned int i=0; i<20; i++ ) {
output = noise.tick();
std::cout << "i = " << i << " : output = " << output << std::endl;
}
return 0;
}
\endcode
Nearly all STK classes implement <TT>tick()</TT> functions that take and/or return sample values. Within the <TT>tick()</TT> function, the fundamental sample calculations are performed for a given class. Most STK classes consume/generate a single sample per operation and their <TT>tick()</TT> method takes/returns each sample "by value". In addition, every class implementing a <TT>tick()</TT> function also provides one or more overloaded <TT>tick()</TT> functions that can be used for vectorized computations, as shown in the next example.
\code
#include "Noise.h"
using namespace stk;
int main()
{
StkFrames output(20, 1); // initialize StkFrames to 20 frames and 1 channel (default: interleaved)
Noise noise;
noise.tick( output );
for ( unsigned int i=0; i<output.size(); i++ ) {
std::cout << "i = " << i << " : output = " << output[i] << std::endl;
}
return 0;
}
\endcode
In this way, it might be possible to achieve improved processing efficiency using vectorized computations. The StkFrames class is a relatively new addition to the ToolKit to provide a general "mechanism" for handling and passing vectorized, multi-channel audio data. The StkFrames "type" provides functions to set and/or determine the number of audio channels and sample frames it holds. Further, the StkFrames class provides data interpolation and subscripting functionality by frame/channel values.
\section STK Inheritance:
Nearly all STK classes inherit from the Stk abstract base class, which provides common functionality related to error reporting, sample rate control, and byte swapping. Several other base classes exist that roughly group many of the classes according to function as follows:
- stk::Generator: source signal unit generator classes [stk::Envelope, stk::ADSR, stk::Asymp, stk::Noise, stk::SubNoise, stk::Modulate, stk::SingWave, stk::SineWave, stk::Blit, stk::BlitSaw, stk::BlitSquare, stk::Granulate]
- stk::Filter: digital filtering classes [stk::OneZero, stk::OnePole, stk::PoleZero, stk::TwoZero, stk::TwoPole, stk::BiQuad, stk::FormSwep, stk::Delay, stk::DelayL, stk::DelayA, stk::TapDelay]
- stk::Function: input to output function mappings [stk::BowTable, stk::JetTable, stk::ReedTable]
- stk::Instrmnt: sound synthesis algorithms, including physical, FM, modal, and particle models
- stk::Effect: sound processing effect classes [stk::Echo, stk::Chorus, stk::PitShift, stk::PRCRev, stk::JCRev, stk::NRev]
- stk::WvOut: audio data output classes [stk::FileWvOut, stk::RtWvOut, stk::InetWvOut]
- stk::WvIn: audio data input classes [stk::FileWvIn, stk::FileLoop, stk::RtWvIn, stk::InetWvIn]
[<A HREF="tutorial.html">Main tutorial page</A>] &nbsp; [<A HREF="hello.html">Next tutorial</A>]
*/

View File

@@ -6,5 +6,5 @@
<BODY BGCOLOR="#FFFFFF">
<CENTER>
<img src="princeton.gif"> &nbsp; <img src="ccrma.gif"> &nbsp; <img src="mcgill.gif"><P>
<a class="qindex" href="index.html">Home</a> &nbsp; <a class="qindex" href="information.html">Information</a> &nbsp; <a class="qindex" href="classes.html">Classes</a> &nbsp; <a class="qindex" href="download.html">Download</a> &nbsp; <a class="qindex" href="usage.html">Usage</a> &nbsp; <a class="qindex" href="maillist.html">Mail List</a> &nbsp; <a class="qindex" href="system.html">Requirements</a> &nbsp; <a class="qindex" href="links.html">Links</a> &nbsp; <a class="qindex" href="tutorial.html">Tutorial</a></CENTER>
<a class="qindex" href="index.html">Home</a> &nbsp; <a class="qindex" href="information.html">Information</a> &nbsp; <a class="qindex" href="classes.html">Classes</a> &nbsp; <a class="qindex" href="download.html">Download</a> &nbsp; <a class="qindex" href="usage.html">Usage</a> &nbsp; <a class="qindex" href="maillist.html">Mail List</a> &nbsp; <a class="qindex" href="system.html">Requirements</a> &nbsp; <a class="qindex" href="links.html">Links</a> &nbsp; <a class="qindex" href="faq.html">FAQ</a> &nbsp; <a class="qindex" href="tutorial.html">Tutorial</a></CENTER>
<HR>

View File

@@ -19,13 +19,13 @@
\vspace*{1cm}
{\large by Perry R. Cook and Gary P. Scavone}\\
\vspace*{0.5cm}
{\small \copyright 1995--2002}\\
{\small \copyright 1995--2007}\\
\end{center}
\end{titlepage}
\clearemptydoublepage
\pagenumbering{roman}
\rfoot[\fancyplain{}{\bfseries\scriptsize The Synthesis ToolKit in C++ by Perry R. Cook and Gary P. Scavone, \copyright~1995--2002}]{}
\lfoot[]{\fancyplain{}{\bfseries\scriptsize The Synthesis ToolKit in C++ by Perry R. Cook and Gary P. Scavone, \copyright~1995--2002}}
\rfoot[\fancyplain{}{\bfseries\scriptsize The Synthesis ToolKit in C++ by Perry R. Cook and Gary P. Scavone, \copyright~1995--2007}]{}
\lfoot[]{\fancyplain{}{\bfseries\scriptsize The Synthesis ToolKit in C++ by Perry R. Cook and Gary P. Scavone, \copyright~1995--2007}}
\tableofcontents
\clearemptydoublepage
\pagenumbering{arabic}

View File

@@ -1,104 +1,94 @@
/*! \page hello Hello Sine!
We'll begin our introduction to the Synthesis ToolKit with a simple sine-wave oscillator program. STK does not provide a specific oscillator for sine waves. Instead, it provides a generic waveform oscillator class, WaveLoop, which can load a variety of common file types. In this example, we load a sine "table" from an STK RAW file (defined as monophonic, 16-bit, big-endian data). We use the class WvOut to write the result to a 16-bit, WAV formatted audio file.
We'll continue our introduction to the Synthesis ToolKit with a simple
sine-wave oscillator program. STK provides two different classes for
sine-wave generation. We will first look at a generic waveform
oscillator class, stk::FileLoop, that can load a variety of common file
types. In this example, we load a sine "table" from an STK RAW file
(defined as monophonic, 16-bit, big-endian data). We use the class
stk::FileWvOut to write the result to a 16-bit, WAV formatted audio file.
\code
// sineosc.cpp
#include "WaveLoop.h"
#include "WvOut.h"
#include "FileLoop.h"
#include "FileWvOut.h"
using namespace stk;
int main()
{
// Set the global sample rate before creating class instances.
Stk::setSampleRate( 44100.0 );
// Define and load the sine wave file
WaveLoop *input = new WaveLoop( "rawwaves/sinewave.raw", TRUE );
input->setFrequency( 440.0 );
FileLoop input;
FileWvOut output;
// Define and open a 16-bit, one-channel WAV formatted output file
output = new WvOut( "hellosine.wav", 1, WvOut::WVOUT_WAV, Stk::STK_SINT16 );
// Load the sine wave file.
input.openFile( "rawwaves/sinewave.raw", true );
// Open a 16-bit, one-channel WAV formatted output file
output.openFile( "hellosine.wav", 1, FileWrite::FILE_WAV, Stk::STK_SINT16 );
input.setFrequency( 440.0 );
// Run the oscillator for 40000 samples, writing to the output file
int i;
for ( i=0; i<40000; i++ ) {
output->tick( input->tick() );
}
// Clean up
delete input;
delete output;
for ( int i=0; i<40000; i++ )
output.tick( input.tick() );
return 0;
}
\endcode
WaveLoop is a subclass of WvIn, which supports WAV, SND (AU), AIFF, MAT-file (Matlab), and RAW file formats with 8-, 16-, and 32-bit integer and 32- and 64-bit floating-point data types. WvIn provides interpolating, read once ("oneshot") functionality, as well as methods for setting the read rate and read position.
stk::FileLoop is a subclass of stk::FileWvIn, which supports WAV, SND
(AU), AIFF, MAT-file (Matlab), and RAW file formats with 8-, 16-, and
32-bit integer and 32- and 64-bit floating-point data types.
stk::FileWvIn provides interpolating, read-once ("oneshot")
functionality, as well as methods for setting the read rate and read
position.
The WvIn and WvOut classes are complementary, both supporting WAV, SND (AU), AIFF, MAT-file (Matlab), and RAW file formats with 8-, 16-, and 32-bit integer and 32- and 64-bit floating-point data types. However, WvOut does not perform data interpolation.
stk::FileWvIn provides a "tick level" and interpolating interface to
the stk::FileRead class. Likewise, stk::FileWvOut provides a "tick
level" interface to the stk::FileWrite class. stk::FileRead and
FileWrite both support WAV, SND(AU), AIFF, MAT-file (Matlab), and RAW
file formats with 8-, 16-, and 32-bit integer and 32- and 64-bit
floating-point data types. stk::FileWvOut does not currently offer
data interpolation functionality.
Nearly all STK classes implement <TT>tick()</TT> functions which take and/or return sample values. Within the <TT>tick()</TT> function, the fundamental sample calculations are performed for a given class. Most STK classes consume/generate a single sample per operation and their <TT>tick()</TT> method takes/returns each sample "by value". In addition, every class implementing a <TT>tick()</TT> function also provides an overloaded <TT>tick()</TT> function taking pointer and size arguments which can be used for vectorized computations.
A number of STK parent classes, including stk::WvIn, stk::WvOut,
stk::Instrmnt, stk::Generator, and stk::Effect, (and some or all of
their subclasses) support multi-channel sample frames. If a
single-sample version of the <TT>tick()</TT> function is called for
these classes, a full sample frame is computed but only a single value
is either input and/or output. For example, if the single-sample
<TT>tick()</TT> function is called for subclasses of stk::WvOut, the
sample argument is written to all channels in the one computed frame.
For classes returning values, an optional \c channel argument
specifies which channel value is returned from the computed frame (the
default is always channel 0). To input and/or output multichannel data
to these classes, the overloaded <TT>tick()</TT> functions taking
StkFrames reference arguments should be used.
The WvIn and WvOut classes support multi-channel sample frames. To distinguish single-sample frame operations from multi-channel frame operations, these classes also implement <TT>tickFrame()</TT> functions. When a <TT>tick()</TT> method is called for multi-channel data, frame averages are returned or the input sample is distributed across all channels of a sample frame.
Nearly all STK classes inherit from the Stk base class. Stk provides a static sample rate which is queried by subclasses as needed. Because many classes use the current sample rate value during instantiation, it is important that the desired value be set at the beginning of a program. The default STK sample rate is 22050 Hz.
Another primary concept that is somewhat obscurred in this example concerns the data format in which sample values are passed and received. Audio and control signals throughout STK use a floating-point data type, the exact precision of which can be controlled via the <TT>MY_FLOAT</TT> \#define statement in Stk.h. Thus, the ToolKit can use any normalization scheme desired. The base instruments and algorithms are implemented with a general audio sample dynamic maximum of +/-1.0, and the WvIn and WvOut classes and subclasses scale appropriately for DAC or soundfile input and output.
Nearly all STK classes inherit from the stk::Stk base class. Stk
provides a static sample rate that is queried by subclasses as needed.
Because many classes use the current sample rate value during
instantiation, it is important that the desired value be set at the
beginning of a program. The default STK sample rate is 44100 Hz.
\section error Error Handling
The ToolKit has some basic C++ error handling functionality built in. Classes which access files and/or hardware are most prone to runtime errors. To properly "catch" such errors, the above example should be rewritten as shown below.
The ToolKit has some basic C++ error handling functionality built in.
Classes that access files and/or hardware are most prone to runtime
errors. To properly "catch" such errors, the above example should be
rewritten as shown below.
\code
// sineosc.cpp
\include sineosc.cpp
#include "WaveLoop.h"
#include "WvOut.h"
In this particular case, we simply exit the program if an error occurs
(an error message is automatically printed to stderr). A more refined
program might attempt to recover from or fix a particular problem and,
if successful, continue processing. See the \ref classes to determine
which constructors and functions can throw an error.
int main()
{
// Set the global sample rate before creating class instances.
Stk::setSampleRate( 44100.0 );
WaveLoop *input = 0;
WvOut *output = 0;
try {
// Define and load the sine wave file
input = new WaveLoop( "rawwaves/sinewave.raw", TRUE );
// Define and open a 16-bit, one-channel WAV formatted output file
output = new WvOut( "hellosine.wav", 1, WvOut::WVOUT_WAV, Stk::STK_SINT16 );
}
catch ( StkError & ) {
goto cleanup;
}
input->setFrequency( 440.0 );
// Run the oscillator for 40000 samples, writing to the output file
for ( int i=0; i<40000; i++ ) {
try {
output->tick( input->tick() );
}
catch ( StkError & ) {
goto cleanup;
}
}
cleanup:
delete input;
delete output;
return 0;
}
\endcode
In this particular case, we simply exit the program if an error occurs (an error message is automatically printed to stderr). A more refined program might attempt to recover from or fix a particular problem and, if successful, continue processing. See the \ref classes to determine which constructors and functions can throw an error.
[<A HREF="compile.html">Next tutorial</A>] &nbsp; [<A HREF="tutorial.html">Main tutorial page</A>]
[<A HREF="fundamentals.html">Main tutorial page</A>] &nbsp; [<A HREF="compile.html">Next tutorial</A>]
*/

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@@ -1,10 +1,25 @@
/*! \mainpage <I>The Synthesis ToolKit in C++ (STK)</I>
/*! \mainpage The Synthesis ToolKit in C++ (STK)
\htmlonly
<BODY BGCOLOR="white">
<h3><center><a href="http://www.cs.princeton.edu/~prc/">Perry R. Cook</a> & <a href="http://music.mcgill.ca/~gary/">Gary P. Scavone</a></center></h3>
\endhtmlonly
<center><h3>Perry R. Cook & Gary P. Scavone</h3></center>
The <B>Synthesis ToolKit in C++ (STK)</B> is a set of open source audio signal processing and algorithmic synthesis classes written in C++. STK was designed to facilitate rapid development of music synthesis and audio processing software, with an emphasis on cross-platform functionality, realtime control, ease of use, and educational example code. The Synthesis ToolKit is extremely portable (it's mostly platform-independent C and C++ code), and it's completely user-extensible (all source included, no unusual libraries, and no hidden drivers). We like to think that this increases the chances that our programs will still work in another 5-10 years. In fact, the ToolKit has been working continuously for nearly 8 years now. STK currently runs with "realtime" support (audio and MIDI) on SGI (Irix), 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 <B>Synthesis ToolKit in C++ (STK)</B> is a set of open source
audio signal processing and algorithmic synthesis classes written in
the C++ programming language. STK was designed to facilitate rapid
development of music synthesis and audio processing software, with an
emphasis on cross-platform functionality, realtime control, ease of
use, and educational example code. The Synthesis ToolKit is extremely
portable (it's mostly platform-independent C and C++ code), and it's
completely user-extensible (all source included, no unusual libraries,
and no hidden drivers). We like to think that this increases the
chances that our programs will still work in another 5-10 years. In
fact, the ToolKit has been working continuously for nearly 20 years
now. STK currently runs with realtime support (audio and MIDI) on
Linux, Macintosh OS X, and Windows computer platforms. Generic,
non-realtime support has been tested under NeXTStep, Sun, and other
platforms and should work with any standard C++ compiler.
- \ref information
- \ref classes
@@ -13,6 +28,7 @@ The <B>Synthesis ToolKit in C++ (STK)</B> is a set of open source audio signal p
- \ref maillist
- \ref system
- \ref links
- \ref faq
- \ref tutorial
*/

View File

@@ -2,49 +2,132 @@
<H3>References</H3>
<UL>
<LI><A HREF="Papers/stkicmc99.pdf">ICMC99 Paper</A></LI>
<LI><A HREF="papers/stkupdate.pdf">ICMC2005 Paper</A></LI>
<BR>
A somewhat recent paper by Perry and Gary about the Synthesis ToolKit in C++.
A paper by Gary and Perry detailing recent updates to the Synthesis ToolKit in C++.
<P>
<LI><A HREF="Papers/STKsiggraph96.pdf">SIGGRAPH96 Paper</A></LI>
<LI><A HREF="papers/stkicmc99.pdf">ICMC99 Paper</A></LI>
<BR>
A not-so-recent paper by Perry about the Synthesis ToolKit in C++.
A not-so-recent paper by Perry and Gary about the Synthesis ToolKit in C++.
<P>
<LI><A HREF="http://www.cs.princeton.edu/~prc/NewWork.html#STK">Perry's STK Web Page</A></LI>
<LI>Book Chapter: <A HREF="http://www.akpeters.com/product.asp?ProdCode=1047">Audio Anecdotes</A></LI>
<BR>
This is a link to Perry Cook's STK Web page. He has information about the \ref skini, the protocol used to control STK instruments, as well as a lot of other cool stuff.
Here's a link to a book that includes an chapter on STK.
</UL>
<H4>What is the <I>Synthesis ToolKit</I>?</H4>
The Synthesis ToolKit in C++ (STK) is a set of open source audio signal processing and algorithmic synthesis classes written in C++. STK was designed to facilitate rapid development of music synthesis and audio processing software, with an emphasis on cross-platform functionality, realtime control, ease of use, and educational example code. The Synthesis ToolKit is extremely portable (it's mostly platform-independent C and C++ code), and it's completely user-extensible (all source included, no unusual libraries, and no hidden drivers). We like to think that this increases the chances that our programs will still work in another 5-10 years. In fact, the ToolKit has been working continuously for nearly 8 years now. STK currently runs with "realtime" support (audio and MIDI) on SGI (Irix), Linux, Macintosh OS X, and Windows computer platforms. Generic, non-realtime support has been tested under NeXTStep, Sun, and other platforms and should work with any standard C++ compiler.
The Synthesis ToolKit in C++ (STK) is a set of open source audio signal processing and algorithmic synthesis classes written in the C++ programming language. STK was designed to facilitate rapid development of music synthesis and audio processing software, with an emphasis on cross-platform functionality, realtime control, ease of use, and educational example code. The Synthesis ToolKit is extremely portable (it's mostly platform-independent C and C++ code), and it's completely user-extensible (all source included, no unusual libraries, and no hidden drivers). We like to think that this increases the chances that our programs will still work in another 5-10 years. In fact, the ToolKit has been working continuously for nearly 20 years now. STK currently runs with realtime support (audio and MIDI) on Linux, Macintosh OS X, and Windows computer platforms. Generic, non-realtime support has been tested under NeXTStep, Sun, and other platforms and should work with any standard C++ compiler.
The Synthesis ToolKit is free for non-commercial use. The only parts of the Synthesis ToolKit that are platform-dependent concern real-time audio and MIDI input and output, and that is taken care of with a few special classes. The interface for MIDI input and the simple <A HREF="http://dev.scriptics.com">Tcl/Tk</A> 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. <A HREF="http://www-ccrma.stanford.edu/software/snd/">Snd</A>, Cool Edit, Matlab).
The Synthesis ToolKit is free. The only parts of the Synthesis ToolKit that are platform-dependent concern real-time audio and MIDI input and output, and that is taken care of with a few special classes. The interface for MIDI input and the simple <A HREF="http://dev.scriptics.com">Tcl/Tk</A> 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. <A HREF="http://www-ccrma.stanford.edu/software/snd/">Snd</A>, Cool Edit, Matlab).
<H4>What the <I>Synthesis ToolKit</I> is not.</H4>
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.
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. It is easy to embed STK classes inside a GUI environment but we have chosen to focus our energy on the audio signal processing issues. Spending hundreds of hours making platform-dependent graphical user interfaces 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 <A HREF="http://dev.scriptics.com">Tcl/Tk</A> (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).
For those instances where a simple GUI with sliders and buttons is helpful, we use <A HREF="http://dev.scriptics.com">Tcl/Tk</A> (that 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).
<H4>A brief history of the <I>Synthesis ToolKit in C++.</I></H4>
Perry Cook began developing a pre-cursor to the Synthesis ToolKit (also called STK) under NeXTStep at the Center for Computer Research in Music and Acoustics (CCRMA) at Stanford University in the early-1990s. With his move to Princeton University in 1996, he ported everything to C++ on SGI hardware, added real-time capabilities, and greatly expanded the synthesis techniques available. With the help of Bill Putnam, Perry also made a port of STK to Windows95. Gary Scavone began using STK extensively in the summer of 1997 and completed a full port of STK to Linux early in 1998. He finished the fully compatable Windows port (using Direct Sound API) in June 1998. Numerous improvements and extensions have been made since then.
Perry Cook began developing a pre-cursor to the Synthesis ToolKit
(also called STK) under NeXTStep at the Center for Computer Research
in Music and Acoustics (CCRMA) at Stanford University in the
early-1990s. With his move to Princeton University in 1996, he ported
everything to C++ on SGI hardware, added real-time capabilities, and
greatly expanded the synthesis techniques available. With the help of
Bill Putnam, Perry also made a port of STK to Windows95. Gary Scavone
began using STK extensively in the summer of 1997 and completed a full
port of STK to Linux early in 1998. He finished the fully compatable
Windows port (using Direct Sound API) in June 1998. Numerous
improvements and extensions have been made since then.
The Toolkit has been distributed continuously since 1996 via the <A HREF="http://www.music.princeton.edu/psk">Princeton Sound Kitchen</A>, <A HREF="http://www.cs.princeton.edu/~prc">Perry Cook's home page</A> at Princeton, <A HREF="http://www-ccrma.stanford.edu/~gary/">Gary Scavone's home page</A> at Stanford's Center for Computer Research in Music and Acoustics (CCRMA), and the <A HREF="http://www-ccrma.stanford.edu/software/stk">Synthesis ToolKit home page</A>. The ToolKit has been in included in various collections of software. Much of it has also been ported to MAX/MSP on Macintosh computers by Dan Trueman and Luke Dubois of Columbia University, and is distributed as <A HREF="http://music.columbia.edu/PeRColate">PeRColate</A>. Help on real-time sound and MIDI has been provided by Tim Stilson, Bill Putnam, and Gabriel Maldonado.
The Toolkit has been distributed continuously since 1996 via the <A
HREF="http://www.music.princeton.edu/psk">Princeton Sound Kitchen</A>,
<A HREF="http://www.cs.princeton.edu/~prc">Perry Cook's home page</A>
at Princeton, <A HREF="http://www.music.mcgill.ca/~gary/">Gary
Scavone's home page</A> at McGill University, and the <A HREF="http://ccrma.stanford.edu/software/stk">Synthesis ToolKit
home page</A>. The ToolKit has been included in various collections
of software. Much of it has also been ported to Max/MSP on Macintosh
computers by Dan Trueman and Luke Dubois of Columbia University, and
is distributed as <A
HREF="http://music.columbia.edu/PeRColate">PeRColate</A>. Help on
real-time sound and MIDI has been provided over the years by Tim
Stilson, Bill Putnam, and Gabriel Maldonado.
<H4>Legal and Ethical Notes</H4>
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.
<P>
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 will not state what's freely useable here, but we will try to note within the various classes where certain things are likely to be protected by patents.
Some of the concepts are covered by various patents, some known to us
and likely others that 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 will not state what's freely
useable here, but we will try to note within the various classes where
certain things are likely to be protected by patents.
<H4>License</H4>
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.
<H4>Disclaimer</H4>
STK is free and we do not guarantee anything. We've been hacking on this code for a while now and most of it seems to work pretty well. But, there surely are some bugs floating around. Sometimes things work fine on one computer platform but not so fine on another. FPU overflows and underflows cause <I>very</I> weird behavior which also depends on the particular CPU and OS. Let us know about bugs you find and we'll do our best to correct them.
STK is free and we do not guarantee anything. We've been hacking on this code for a while now and most of it seems to work pretty well. But, there surely are some bugs floating around. Sometimes things work fine on one computer platform but not so fine on another. FPU overflows and underflows cause <I>very</I> weird behavior that also depends on the particular CPU and OS. Let us know about bugs you find and we'll do our best to correct them.
*/
<H4>Perry's Notes From the Original Distribution of STK</H4>
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.
<ol>
<li>I needed to port many of the things I've done into something that is generic enough to port further to different machines.</li>
<li>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.)</li>
<li>The classic difficulties most people have in trying to implement physical models are:
<ul>
<li>They have trouble understanding the papers, and/or in turning the theory into practice.</li>
<li>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.</li>
</ul>
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.</li>
<li>I wanted to try some new stuff with modal synthesis, and implement some classic FM patches as well.</li>
<li>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.</li>
<li>More rationalizations to follow ...</li>
</ol>
*/

View File

@@ -1,73 +1,19 @@
/*! \page instruments Instruments
The ToolKit comes with a wide variety of synthesis algorithms, all of which inherit from the Instrmnt class. In this example, we'll fire up an instance of the BeeThree FM synthesis class and show how it's frequency can be modified over time.
The ToolKit comes with a wide variety of synthesis algorithms, all of which inherit from the stk::Instrmnt class. In this example, we'll fire up an instance of the stk::BeeThree FM synthesis class and show how its frequency can be modified over time.
\code
// bethree.cpp
\include bethree.cpp
#include "BeeThree.h"
#include "RtWvOut.h"
We have used an Instrmnt pointer when referencing the BeeThree
instance above, so it would be simple to replace the BeeThree class
with any other STK instrument class. It should be noted, however,
that a few classes do not respond to the setFrequency() function
(e.g., Shakers, Drummer).
int main()
{
// Set the global sample rate before creating class instances.
Stk::setSampleRate( 44100.0 );
Instrmnt *instrument = 0;
RtWvOut *output = 0;
MY_FLOAT frequency, amplitude, scaler;
long counter, i;
try {
// Define and load the BeeThree instrument
instrument = new BeeThree();
// Define and open the default realtime output device for one-channel playback
output = new RtWvOut(1);
}
catch (StkError &) {
goto cleanup;
}
scaler = 1.0;
frequency = 220.0;
amplitude = 0.5;
instrument->noteOn( frequency, amplitude );
// Play the instrument for 80000 samples, changing the frequency every 2000 samples
counter = 0;
while ( counter < 80000 ) {
for ( i=0; i<2000; i++ ) {
try {
output->tick( instrument->tick() );
}
catch (StkError &) {
goto cleanup;
}
}
counter += 2000;
scaler += 0.025;
instrument->setFrequency( frequency * scaler );
}
// Turn the instrument off with maximum decay envelope.
instrument->noteOff( 1.0 );
cleanup:
delete instrument;
delete output;
return 0;
}
\endcode
We have used an Instrmnt pointer when referencing the BeeThree instance above, so it would be simple to replace the BeeThree class with any other STK instrument class. It should be noted, however, that a few classes do not respond to the setFrequency() function (e.g., Shakers, Drummer).
The noteOn() function initiates an instrument attack. Instruments which are continuously excited (e.g., Clarinet, BeeThree) will continue to sound until stopped with a noteOff(). Impulsively excited instrument sounds (e.g., Plucked, Wurley) typically decay within a few seconds time, requiring subsequent noteOn() messages for re-attack.
The noteOn() function initiates an instrument attack. Instruments that are continuously excited (e.g., stk::Clarinet, stk::BeeThree) will continue to sound until stopped with a noteOff(). Impulsively excited instrument sounds (e.g., stk::Plucked, stk::Wurley) typically decay within a few seconds time, requiring subsequent noteOn() messages for re-attack.
Instrument parameters can be precisely controlled as demonstrated above. A more flexible approach to instrument control, allowing arbitrary scorefile or realtime updates, is described in the next tutorial chapter.
[<A HREF="controlin.html">Next tutorial</A>] &nbsp; [<A HREF="tutorial.html">Main tutorial page</A>]
[<A HREF="tutorial.html">Main tutorial page</A>] &nbsp; [<A HREF="controlin.html">Next tutorial</A>]
*/

View File

@@ -1,19 +1,25 @@
/*! \page links Miscellaneous Links
- <A HREF="http://www-ccrma.stanford.edu/~gary/rtaudio/">The RtAudio WWW site</A>
- <A HREF="http://www.music.mcgill.ca/~gary/rtaudio/">The %RtAudio WWW site</A>
- <A HREF="http://kern.humdrum.net/">Kern Scores: A Library of Electronic Musical Scores</A> (with automatic conversion to SKINI format)
- <A HREF="http://www.music.mcgill.ca/~gary/rtmidi/">The %RtMidi WWW site</A>
- <A HREF="http://momu.stanford.edu/stk/">MoMu-Stk: A lightly modified version of STK that supports the iPhone platform (iPhone, iPad, iPod Touches)</A>
- <A HREF="http://ccrma.stanford.edu/~woony/software/stkx/">StkX: A Cocoa STK Framework for Mac OS X by Woon Seung Yeo</A>
- <A HREF="http://sourceforge.net/projects/mobilestk">Mobile STK: A port of STK for mobile devices by Georg Essl and Michael Rohs</A>
- <A HREF="http://chuck.cs.princeton.edu/">ChucK: Concurrent, On-the-fly Audio Programming Language</A> using STK unit generators
- <A HREF="http://kern.ccarh.org">Kern Scores: A Library of Electronic Musical Scores</A> (with automatic conversion to SKINI format)
- <A HREF="http://stk.sapp.org/midi2skini">MIDI to SKINI file converter</A> by Craig Sapp
- <A HREF="http://stk.sapp.org/kern2skini">Kern Score to SKINI file converter</A> by Craig Sapp
- <A HREF="http://www.artassault.org/software/software.html">Calico - A Polyphonic Score File Parser for STK</A> by Greg Kellum
- <A HREF="http://extra.humdrum.org/example/kern2skini/">Kern Score to SKINI file converter</A> by Craig Sapp
- <A HREF="http://www.music.columbia.edu/PeRColate/">PeRColate: A Port of STK for Max/MSP</A>
- <A HREF="http://mathmorphs.swiki.net/32/">A Partial Port of STK to Squeak</A>
- <a href="http://airy.andre.online.fr/AU/index.html">AUStk: a demo of integration of STK instruments into an AudioUnit</a> by Airy Andre
*/

View File

@@ -1,70 +1,30 @@
/*! \page multichannel Multi-Channel I/O
The ToolKit WvIn and WvOut classes (and their subclasses) support multi-channel audio data input and output. A set of interleaved audio samples representing a single time "slice" is referred to as a <I>sample frame</I>. At a sample rate of 44.1 kHz, a four-channel audio stream will have 44100 sample frames per second and a total of 176400 individual samples per second.
The ToolKit stk::WvIn and stk::WvOut classes (and their subclasses) support multi-channel audio data input and output. Several other abstract base classes, such as stk::Instrmnt, stk::Generator, and stk::Effect, also support multi-channel computations though not all of their subclasses produce or take multi-channel data. A set of interleaved audio samples representing a single time "slice" is referred to as a <I>sample frame</I>. At a sample rate of 44.1 kHz, a four-channel audio stream will have 44100 sample frames per second and a total of 176400 individual samples per second.
Most STK classes process single-sample data streams via their <TT>tick()</TT> function. In order to distinguish single-sample and sample frame calculations, the WvIn and WvOut classes implement both <TT>tick()</TT> and <TT>tickFrame()</TT> functions. The <TT>tickFrame()</TT> functions take or return a pointer to an array of audio data representing one or more sample frames. For single-channel streams, the <TT>tick()</TT> and <TT>tickFrame()</TT> functions produce equivalent results. When <TT>tick()</TT> is called for a multi-channel stream, however, the function either returns a sample frame average (WvIn) or writes a single sample argument to all channels (WvOut).
Most STK classes process single-sample data streams via their
<TT>tick()</TT> function. For classes supporting multi-channel data,
one must distinguish the <TT>tick()</TT> functions taking or producing
single \c StkFloat arguments from those taking stk::StkFrames& arguments. If
a single-sample version of the <TT>tick()</TT> function is called for
these classes, a full sample frame is computed but only a single value
is either input and/or output. For example, if the single-sample
<TT>tick()</TT> function is called for subclasses of WvOut, the sample
argument is written to all channels in the one computed frame. For
classes returning values, an optional \c channel argument specifies
which channel value is returned from the computed frame (the default
is always channel 0). To input and/or output multichannel data to
these classes, the overloaded <TT>tick()</TT> functions taking
StkFrames reference arguments should be used.
Multi-channel support for realtime audio input and output is dependent on the audio device(s) available on your system.
The following example demonstrates the use of the WvOut class for creating a four channel, 16-bit AIFF formatted audio file. We will use four sinewaves of different frequencies for the first two seconds and then a single sinewave for the last two seconds.
The following example demonstrates the use of the stk::FileWvOut class for
creating a four channel, 16-bit AIFF formatted audio file. We will
use four sinewaves of different frequencies for the first two seconds
and then a single sinewave for the last two seconds.
\code
// foursine.cpp
\include foursine.cpp
#include "WaveLoop.h"
#include "WvOut.h"
int main()
{
// Set the global sample rate before creating class instances.
Stk::setSampleRate( 44100.0 );
int i, j;
WvOut *output = 0;
WaveLoop *inputs[4];
for ( i=0; i<4; i++ ) inputs[i] = 0;
// Define and load the sine waves
try {
for ( i=0; i<4; i++ ) {
inputs[i] = new WaveLoop( "rawwaves/sinewave.raw", TRUE );
inputs[i]->setFrequency( 220.0 * (i+1) );
}
}
catch (StkError &) {
goto cleanup;
}
// Define and open a 16-bit, four-channel AIFF formatted output file
try {
output = new WvOut( "foursine.aif", 4, WvOut::WVOUT_AIF, Stk::STK_SINT16 );
}
catch (StkError &) {
goto cleanup;
}
// Write two seconds of four sines to the output file
MY_FLOAT frame[4];
for ( j=0; j<88200; j++ ) {
for ( i=0; i<4; i++ )
frame[i] = inputs[i]->tick();
output->tickFrame( frame );
}
// Now write the first sine to all four channels for two seconds
for ( j=0; j<88200; j++ ) {
output->tick( inputs[0]->tick() );
}
cleanup:
for ( i=0; i<4; i++ ) delete inputs[i];
delete output;
return 0;
}
\endcode
[<A HREF="polyvoices.html">Next tutorial</A>] &nbsp; [<A HREF="tutorial.html">Main tutorial page</A>]
[<A HREF="tutorial.html">Main tutorial page</A>] &nbsp; [<A HREF="polyvoices.html">Next tutorial</A>]
*/

View File

@@ -1,122 +1,22 @@
/*! \page polyvoices Voice Management
The previous tutorial chapters were concerned only with monophonic ToolKit instrument playback and control. At this point, it should be relatively clear that one can instantiate multiple instruments and perhaps sum together their sounds or even direct their sounds to separate output channels. It is less clear how one might go about controlling a group of instruments. The Voicer class is designed to serve just this purpose.
The previous tutorial chapters were concerned only with monophonic ToolKit instrument playback and control. At this point, it should be relatively clear that one can instantiate multiple instruments and perhaps sum together their outputs or even direct their outputs to separate channels. It is less clear how one might go about controlling a group of instruments. The stk::Voicer class is designed to serve just this purpose.
The STK Voicer class is a relatively simple voice manager. The user can dynamically add and delete instruments from its "control", with the option of controlling specific instruments via unique note tags and/or grouping sets of instruments via a "channel" number. All sounding instrument outputs are summed and returned via the <TT>tick()</TT> function. The Voicer class responds to noteOn, noteOff, setFrequency, pitchBend, and controlChange messages, automatically assigning incoming messages to the voices in its control. When all voices are sounding and a new noteOn is encountered, the Voicer interrupts the oldest sounding voice. The user is responsible for creating and deleting all instrument instances.
The stk::Voicer class is a relatively simple voice manager. The user can dynamically add and delete instruments to/from its "control", with the option of controlling specific instruments via unique note tags and/or grouping sets of instruments via a "group" number. All sounding instrument outputs are summed and returned via the <TT>tick()</TT> function. The stk::Voicer class responds to noteOn, noteOff, setFrequency, pitchBend, and controlChange messages, automatically assigning incoming messages to the voices in its control. When all voices are sounding and a new noteOn is encountered, the stk::Voicer interrupts the oldest sounding voice. The user is responsible for creating and deleting all instrument instances.
In the following example, we modify the <TT>controlbee.cpp</TT> program to make use of three BeeThree instruments, all controlled using a Voicer.
In the following example, we modify the <TT>controlbee.cpp</TT> program to make use of three stk::BeeThree instruments, all controlled using a stk::Voicer.
\include threebees.cpp
We have written this program to accept control messages from \c STDIN. Assuming the program is compiled as <TT>threebees</TT>, the three-voice SKINI scorefile <A HREF="tutorial/bachfugue.ski"><TT>bachfugue.ski</TT></A> (located in the <tt>scores</tt> directory with the examples) can be redirected to the program as:
\code
// threebees.cpp
#include "BeeThree.h"
#include "RtWvOut.h"
#include "Messager.h"
#include "Voicer.h"
#include "SKINI.msg"
int main()
{
// Set the global sample rate before creating class instances.
Stk::setSampleRate( 44100.0 );
int i;
RtWvOut *output = 0;
Messager *messager = 0;
Voicer *voicer = 0;
bool done = FALSE;
Instrmnt *instrument[3];
for ( i=0; i<3; i++ ) instrument[i] = 0;
try {
// Define and load the BeeThree instruments
for ( i=0; i<3; i++ )
instrument[i] = new BeeThree();
// Define and open the default realtime output device for one-channel playback
output = new RtWvOut(1);
}
catch (StkError &) {
goto cleanup;
}
try {
// Create a Messager instance to read from a redirected SKINI scorefile.
messager = new Messager();
}
catch (StkError &) {
goto cleanup;
}
// Instantiate the voicer for a maximum of three voices.
voicer = new Voicer( 3 );
for ( i=0; i<3; i++ )
voicer->addInstrument( instrument[i] );
// Play the instrument until the end of the scorefile.
int nTicks, type;
MY_FLOAT byte2, byte3;
while (!done) {
// Look for new messages and return a delta time (in samples).
type = messager->nextMessage();
if (type < 0)
done = TRUE;
nTicks = messager->getDelta();
try {
for ( i=0; i<nTicks; i++ )
output->tick( voicer->tick() );
}
catch (StkError &) {
goto cleanup;
}
if ( type > 0 ) {
// Process the new control message.
byte2 = messager->getByteTwo();
byte3 = messager->getByteThree();
switch(type) {
case __SK_NoteOn_:
voicer->noteOn( byte2, byte3 );
break;
case __SK_NoteOff_:
voicer->noteOff( byte2, byte3 );
break;
case __SK_ControlChange_:
voicer->controlChange( (int) byte2, byte3 );
break;
case __SK_AfterTouch_:
voicer->controlChange( 128, byte2 );
break;
}
}
}
cleanup:
for ( i=0; i<3; i++ ) delete instrument[i];
delete output;
delete messager;
delete voicer;
return 0;
}
threebees < scores/bachfugue.ski
\endcode
Assuming the program is compiled as <TT>threebees</TT>, the three-voice SKINI scorefile <A HREF="tutorial/bachfugue.ski"><TT>bachfugue.ski</TT></A> (also located in the <tt>scores</tt> directory with the examples) could be redirected to the program as:
For more fun, surf to <A HREF="http://kern.humdrum.net/">Kern Scores</A> for a huge assortment of other scorefiles that can be downloaded in the SKINI format.
\code
threebees < bachfugue.ski
\endcode
For more fun, surf to <A HREF="http://kern.humdrum.net/">Kern Scores</A> for a huge assortment of other scorefiles which can be downloaded in the SKINI format.
Another easy extension would be to use the <TT>STK_MIDI</TT> constructor argument to the Messager class and then play the instruments via a MIDI keyboard.
Another easy extension would be to add the \c stk::Messager::startMidiInput() function to the program and then play the instruments via a MIDI keyboard.
[<A HREF="tutorial.html">Main tutorial page</A>]
*/

View File

@@ -1,72 +1,49 @@
/*! \page realtime Realtime Audio
/*! \page realtime Realtime Audio (blocking)
In this section, we modify the <TT>sineosc.cpp</TT> program in order to send the output to the default audio playback device on your system.
In this section, we modify the <TT>sineosc.cpp</TT> program in order
to send the output to the default audio playback device on your
computer system. We also make use of the stk::SineWave class as a
sine-wave oscillator. stk::SineWave computes an internal, static sine-wave
table when its first instance is created. Subsequent instances make
use of the same table. The default table length, specified in
SineWave.h, is 2048 samples.
\include rtsine.cpp
The class stk::RtWvOut is a protected subclass of stk::WvOut. A number of
optional constructor arguments can be used to fine tune its
performance for a given system. stk::RtWvOut provides a "single-sample",
blocking interface to the RtAudio class. Note that stk::RtWvOut (as well
as the stk::RtWvIn class described below) makes use of RtAudio's callback
input/output functionality by creating a large ring-buffer into which
data is written. These classes should not be used when low-latency
and robust performance is necessary
Though not used here, an stk::RtWvIn class exists as well that can be used
to read realtime audio data from an input device. See the
<TT>record.cpp</TT> example program in the <TT>examples</TT> project
for more information.
It may be possible to use an instance of stk::RtWvOut and an instance of
stk::RtWvIn to simultaneously read and write realtime audio to and from a
hardware device or devices. However, it is recommended to instead use
a single instance of RtAudio to achieve this behavior, as described in the next section.
See the <TT>effects</TT> project or the <TT>duplex.cpp</TT> example
program in the <TT>examples</TT> project for more information.
When using any realtime STK class (RtAudio, stk::RtWvOut, stk::RtWvIn, RtMidi, stk::InetWvIn, stk::InetWvOut, stk::Socket, stk::UdpSocket, stk::TcpServer, stk::TcpClient, and stk::Thread), it is necessary to specify an audio/MIDI API preprocessor definition and link with the appropriate libraries or frameworks. For example, the above program could be compiled on a Linux system using the GNU g++ compiler and the ALSA audio API as follows (assuming all necessary files exist in the project directory):
\code
// rtsine.cpp
#include "WaveLoop.h"
#include "RtWvOut.h"
int main()
{
// Set the global sample rate before creating class instances.
Stk::setSampleRate( 44100.0 );
WaveLoop *input = 0;
RtWvOut *output = 0;
try {
// Define and load the sine wave file
input = new WaveLoop( "rawwaves/sinewave.raw", TRUE );
// Define and open the default realtime output device for one-channel playback
output = new RtWvOut(1);
}
catch (StkError &) {
goto cleanup;
}
input->setFrequency(440.0);
// Play the oscillator for 40000 samples
int i;
for ( i=0; i<40000; i++ ) {
try {
output->tick(input->tick());
}
catch (StkError &) {
goto cleanup;
}
}
cleanup:
delete input;
delete output;
return 0;
}
\endcode
The class RtWvOut is a protected subclass of WvOut. A number of optional constructor arguments can be used to fine tune its performance for a given system.
Though not used here, an RtWvIn class exists as well which can be used to read realtime audio data from an input device. See the <TT>record.cpp</TT> example program in the <TT>examples</TT> project for more information.
It is possible to use an instance of RtWvOut and an instance of RtWvIn to simultaneously read and write realtime audio to and from a hardware device or devices. However, it is recommended to instead use a single instance of RtDuplex to achieve this behavior, in that it guarantees better synchronization between the input and output data. See the <TT>effects</TT> project or the <TT>io.cpp</TT> example program in the <TT>examples</TT> project for more information.
When using any realtime STK class (RtAudio, RtWvOut, RtWvIn, RtDuplex, RtMidi, TcpWvIn, TcpWvOut, Socket, and Thread), it is necessary to specify an audio/MIDI API preprocessor definition and link with the appropriate libraries or frameworks. For example, the above program could be compiled on a Linux system using the GNU g++ compiler and the ALSA audio/MIDI API as follows (assuming all necessary files exist in the project directory):
\code
g++ -Wall -D__LINUX_ALSA__ -D__LITTLE_ENDIAN__ -o rtsine Stk.cpp WvIn.cpp WaveLoop.cpp WvOut.cpp \
RtWvOut.cpp RtAudio.cpp rtsine.cpp -lpthread -lasound -lstk
g++ -Wall -D__LINUX_ALSA__ -D__LITTLE_ENDIAN__ -o rtsine Stk.cpp Generator.cpp SineWave.cpp WvOut.cpp \
RtWvOut.cpp RtAudio.cpp rtsine.cpp -lpthread -lasound
\endcode
On a Macintosh OS X system, the syntax would be:
\code
CC -D__MACOSX_CORE__ -o rtsine Stk.cpp WvIn.cpp WaveLoop.cpp WvOut.cpp RtWvOut.cpp RtAudio.cpp \
rtsine.cpp -lpthread -lstdc++ -lstk -framework CoreAudio -framework CoreMIDI -framework CoreFoundation
g++ -Wall -D__MACOSX_CORE__ -o rtsine Stk.cpp Generator.cpp SineWave.cpp WvOut.cpp RtWvOut.cpp RtAudio.cpp \
rtsine.cpp -lpthread -framework CoreAudio -framework CoreMIDI -framework CoreFoundation
\endcode
[<A HREF="instruments.html">Next tutorial</A>] &nbsp; [<A HREF="tutorial.html">Main tutorial page</A>]
[<A HREF="tutorial.html">Main tutorial page</A>] &nbsp; [<A HREF="crealtime.html">Next tutorial</A>]
*/

View File

@@ -8,7 +8,7 @@ This describes the latest (version 1.1) implementation of SKINI for the Synthesi
A SKINI haiku.
\endcode
Profound thanks to Dan Trueman, Brad Garton, and Gary Scavone for input on this revision. Thanks also to MIDI, the NeXT MusicKit, ZIPI and all the creators and modifiers of these for good bases upon/from which to build and depart.
Profound thanks to Dan trueman, Brad Garton, and Gary Scavone for input on this revision. Thanks also to MIDI, the NeXT MusicKit, ZIPI and all the creators and modifiers of these for good bases upon/from which to build and depart.
\section compatibility MIDI Compatibility
@@ -16,7 +16,7 @@ SKINI was designed to be MIDI compatible wherever possible, and extend MIDI in i
Differences from MIDI, and motivations, include:
- Text-based messages are used, with meaningful names wherever possible. This allows any language or system capable of formatted printing to generate SKINI. Similarly, any system capable of reading in a string and turning delimited fields into strings, floats, and ints can consume SKINI for control. More importantly, humans can actually read, and even write if they want, SKINI files and streams. Use an editor and search/replace or macros to change a channel or control number. Load a SKINI score into a spread sheet to apply transformations to time, control parameters, MIDI velocities, etc. Put a monkey on a special typewriter and get your next great work. Life's too short to debug bit/nybble packed variable length mumble messages. Disk space gets cheaper, available bandwidth increases, music takes up so little space and bandwidth compared to video and grapics. Live a little.
- Text-based messages are used, with meaningful names wherever possible. This allows any language or system capable of formatted printing to generate SKINI. Similarly, any system capable of reading in a string and turning delimited fields into strings, floats, and ints can consume SKINI for control. More importantly, humans can actually read, and even write if they want, SKINI files and streams. Use an editor and search/replace or macros to change a channel or control number. Load a SKINI score into a spread sheet to apply transformations to time, control parameters, MIDI velocities, etc. Put a monkey on a special typewriter and get your next great work. Life's too short to debug bit/nybble packed variable length mumble messages. Disk space gets cheaper, available bandwidth increases, music takes up so little space and bandwidth compared to video and graphics. Live a little.
- Floating point numbers are used wherever possible. Note Numbers, Velocities, Controller Values, and Delta and Absolute Times are all represented and scanned as ASCII double-precision floats. MIDI byte values are preserved, so that incoming MIDI bytes from an interface can be put directly into SKINI messages. 60.0 or 60 is middle C, 127.0 or 127 is maximum velocity etc. But, unlike MIDI, 60.5 can cause a 50 cent sharp middle C to be played. As with MIDI byte values like velocity, use of the integer and SKINI-added fractional parts is up to the implementor of the algorithm being controlled by SKINI messages. But the extra precision is there to be used or ignored.
@@ -28,23 +28,25 @@ I am basically a bottom-up designer with an awareness of top-down design ideas,
\section messages SKINI Messages
A basic SKINI message is a line of text. There are only three required fields, the message type (an ASCII name), the time (either delta or absolute), and the channel number. Don't freak out and think that this is MIDI channel 0-15 (which is supported), because the channel number is scanned as a long int. Channels could be socket numbers, machine IDs, serial numbers, or even unique tags for each event in a synthesis. Other fields might be used, as specified in the SKINI.tbl file. This is described in more detail later.
A basic SKINI message is a line of text. There are only three required fields, the message type (an ASCII name), the time (either delta or absolute), and the channel number. Don't freak out and think that this is MIDI channel 0-15 (which is supported), because the channel number is scanned as a long int. Channels could be socket numbers, machine IDs, serial numbers, or even unique tags for each event in a synthesis. Other fields might be used, as specified in the \c SKINI.tbl file. This is described in more detail later.
Fields in a SKINI line are delimited by spaces, commas, or tabs. The SKINI parser only operates on a line at a time, so a newline means the message is over. Multiple messages are NOT allowed directly on a single line (by use of the ; for example in C). This could be supported, but it isn't in version 1.1.
Message types include standard MIDI types like NoteOn, NoteOff, ControlChange, etc. MIDI extension message types (messages which look better than MIDI but actually get turned into MIDI-like messages) include LipTension, StringDamping, etc. Non-MIDI message types include SetPath (sets a path for file use later), and OpenReadFile (for streaming, mixing, and applying effects to soundfiles along with synthesis, for example). Other non-MIDI message types include Trilling, HammerOn, etc. (these translate to gestures, behaviors, and contexts for use by intellegent players and instruments using SKINI). Where possible I will still use these as MIDI extension messages, so foot switches, etc. can be used to control them in real time.
Message types include standard MIDI types like NoteOn, NoteOff, ControlChange, etc. MIDI extension message types (messages which look better than MIDI but actually get turned into MIDI-like messages) include LipTension, StringDamping, etc. Non-MIDI message types include SetPath (sets a path for file use later), and OpenReadFile (for streaming, mixing, and applying effects to soundfiles along with synthesis, for example). Other non-MIDI message types include Trilling, HammerOn, etc. (these translate to gestures, behaviors, and contexts for use by intelligent players and instruments using SKINI). Where possible I will still use these as MIDI extension messages, so foot switches, etc. can be used to control them in real time.
All fields other than type, time, and channel are optional, and the types and useage of the additional fields is defined in the file SKINI.tbl.
All fields other than type, time, and channel are optional, and the
types and useage of the additional fields is defined in the file \c
SKINI.tbl.
The other important file used by SKINI is SKINI.msg, which is a set of #defines to make C code more readable, and to allow reasonably quick re-mapping of control numbers, etc.. All of these defined symbols are assigned integer values. For Java, the #defines could be replaced by declaration and assignment statements, preserving the look and behavior of the rest of the code.
The other important file used by SKINI is \c SKINI.msg, which is a set of #defines to make C code more readable, and to allow reasonably quick re-mapping of control numbers, etc.. All of these defined symbols are assigned integer values. For Java, the #defines could be replaced by declaration and assignment statements, preserving the look and behavior of the rest of the code.
\section cfiles C Files Used To Implement SKINI
\section cfiles Files Used To Implement SKINI
SKINI.cpp is an object which can either open a SKINI file, and successively read and parse lines of text as SKINI strings, or accept strings from another object and parse them. The latter functionality would be used by a socket, pipe, or other connection receiving SKINI messages a line at a time, usually in real time, but not restricted to real time.
Skini is a C++ class which can either open a SKINI file and successively read and parse lines of text as SKINI strings, or accept strings from another object and parse them. The latter functionality would be used by a socket, pipe, or other connection receiving SKINI messages a line at a time, usually in real time, but not restricted to real time.
SKINI.msg should be included by anything wanting to use the SKINI.cpp object. This is not mandatory, but use of the __SK_blah_ symbols which are defined in the .msg file will help to ensure clarity and consistency when messages are added and changed.
\c SKINI.msg should be included by anything wanting to use the Skini object. This is not mandatory, but use of the __SK_blah_ symbols which are defined in the .msg file will help to ensure clarity and consistency when messages are added and changed.
SKINI.tbl is used only by the SKINI parser object (SKINI.cpp). In the file SKINI.tbl, an array of structures is declared and assigned values which instruct the parser as to what the message types are, and what the fields mean for those message types. This table is compiled and linked into applications using SKINI, but could be dynamically loaded and changed in a future version of SKINI.
\c SKINI.tbl is used only by the Skini parser object (Skini.cpp). In the file \c SKINI.tbl, an array of structures is declared and assigned values which instruct the parser as to what the message types are, and what the fields mean for those message types. This table is compiled and linked into applications using SKINI, but could be dynamically loaded and changed in a future version of SKINI.
\section parser SKINI Messages and the SKINI Parser:
@@ -52,8 +54,6 @@ The parser isn't all that smart, but neither am I. Here are the basic rules gov
- If the first (non-delimiter ... see below) character in a SKINI string is '/' that line is treated as a comment and echoed to stdout.
- If there are no characters on a line, that line is treated as blank and echoed to stdout. Tabs and spaces are treated as non-characters.
- Spaces, commas, and tabs delimit the fields in a SKINI message line. (We might allow for multiple messages per line later using the semicolon, but probably not. A series of lines with deltaTimes of 0.0 denotes simultaneous events. For read-ability, multiple messages per line doesn't help much, so it's unlikely to be supported later).
- The first field must be a SKINI message name (like NoteOn). These might become case-insensitive in future versions, so don't plan on exciting clever overloading of names (like noTeOn being different from NoTeON). There can be a number of leading spaces or tabs, but don't exceed 32 or so.
@@ -62,7 +62,7 @@ The parser isn't all that smart, but neither am I. Here are the basic rules gov
- The third field must be an integer channel number. Don't go crazy and think that this is just MIDI channel 0-15 (which is supported). The channel number is scanned as a long int. Channels 0-15 are in general to be treated as MIDI channels. After that it's wide open. Channels could be socket numbers, machine IDs, serial numbers, or even unique tags for each event in a synthesis. A -1 channel can be used as don't care, omni, or other functions depending on your needs and taste.
- All remaining fields are specified in the SKINI.tbl file. In general, there are maximum two more fields, which are either SK_INT (long), SK_DBL (double float), or SK_STR (string). The latter is the mechanism by which more arguments can be specified on the line, but the object using SKINI must take that string apart (retrived by using getRemainderString()) and scan it. Any excess fields are stashed in remainderString.
- All remaining fields are specified in the \c SKINI.tbl file. In general, there are maximum two more fields, which are either SK_INT (long), SK_DBL (double float), or SK_STR (string). The latter is the mechanism by which more arguments can be specified on the line, but the object using SKINI must take that string apart (retrived by using getRemainderString()) and scan it. Any excess fields are stashed in remainderString.
\section file A Short SKINI File:
@@ -80,7 +80,7 @@ The parser isn't all that smart, but neither am I. Here are the basic rules gov
StringDetune 0.100000 2 22
StringDetune 0.100000 2 12
//
StringDamping 0.000100 2 0.0
StringDamping 0.000100 2 0.0
NoteOn 0.000082 2 55 82
NoteOn 0.200000 2 62 82
NoteOn 0.100000 2 71 82
@@ -89,7 +89,7 @@ The parser isn't all that smart, but neither am I. Here are the basic rules gov
NoteOff 0.000000 2 62 82
NoteOff 0.000000 2 71 82
NoteOff 0.000000 2 79 82
StringDamping =4.000000 2 0.0
StringDamping =4.000000 2 0.0
NoteOn 0.000082 2 55 82
NoteOn 0.200000 2 62 82
NoteOn 0.100000 2 71 82
@@ -102,7 +102,7 @@ The parser isn't all that smart, but neither am I. Here are the basic rules gov
\section table The SKINI.tbl File and Message Parsing:
The SKINI.tbl file contains an array of structures which are accessed by the parser object SKINI.cpp. The struct is:
The \c SKINI.tbl file contains an array of structures which are accessed by the parser object Skini.cpp. The struct is:
\code
struct SKINISpec {
@@ -129,9 +129,21 @@ so an assignment of one of these structs looks like:
- SK_DBL : double precision floating point. SKINI uses these in the MIDI context for note numbers with micro tuning, velocities, controller values, etc.
- SK_STR : only valid in final field. This allows (nearly) arbitrary message types to be supported by simply scanning the string to EndOfLine and then passing it to a more intellegent handler. For example, MIDI SYSEX (system exclusive) messages of up to 256 bytes can be read as space-delimited integers into the 1K SK_STR buffer. Longer bulk dumps, soundfiles, etc. should be handled as a new message type pointing to a FileName, Socket, or something else stored in the SK_STR field, or as a new type of multi-line message.
- SK_STR : only valid in final field. This allows (nearly) arbitrary message types to be supported by simply scanning the string to EOL (End Of Line) and then passing it to a more intelligent handler. For example, MIDI SYSEX (system exclusive) messages can be read as space-delimited integers into the SK_STR buffer. Longer bulk dumps, soundfiles, etc. should be handled as a new message type pointing to a FileName, Socket, or something else stored in the SK_STR field, or as a new type of multi-line message.
Here's a couple of lines from the SKINI.tbl file
Each individual SKINI message is parsed and saved to a Skini::Message structure of the form:
\code
struct Message {
long type; /*!< The message type, as defined in SKINI.msg. */
long channel; /*!< The message channel (not limited to 16!). */
StkFloat time; /*!< The message time stamp in seconds (delta or absolute). */
std::vector<StkFloat> floatValues; /*!< The message values read as floats (values are type-specific). */
std::vector<long> intValues; /*!< The message values read as ints (number and values are type-specific). */
std::string remainder; /*!< Any remaining message data, read as ascii text. */
};
\endcode
Here's a couple of lines from the \c SKINI.tbl file
\code
{"NoteOff" , __SK_NoteOff_, SK_DBL, SK_DBL},
@@ -144,7 +156,7 @@ Here's a couple of lines from the SKINI.tbl file
{"StringDetune" , __SK_ControlChange_, __SK_StringDetune_, SK_DBL},
\endcode
The first three are basic MIDI messages. The first two would cause the parser, after recognizing a match of the string "NoteOff" or "NoteOn", to set the message type to 128 or 144 (__SK_NoteOff_ and __SK_NoteOn_ are #defined in the file SKINI.msg to be the MIDI byte value, without channel, of the actual MIDI messages for NoteOn and NoteOff). The parser would then set the time or delta time (this is always done and is therefore not described in the SKINI Message Struct). The next two fields would be scanned as double-precision floats and assigned to the byteTwo and byteThree variables of the SKINI parser. The remainder of the line is stashed in the remainderString variable.
The first three are basic MIDI messages. The first two would cause the parser, after recognizing a match of the string "NoteOff" or "NoteOn", to set the message type to 128 or 144 (__SK_NoteOff_ and __SK_NoteOn_ are #defined in the file \c SKINI.msg to be the MIDI byte value, without channel, of the actual MIDI messages for NoteOn and NoteOff). The parser would then set the time or delta time (this is always done and is therefore not described in the SKINI Message Struct). The next two fields would be scanned either as double-precision \c floats or as <tt>long ints</tt>, depending on the format specified in \c SKINI.tbl, and saved to the corresponding C++ vector variables in the Skini::Message structure (either \c floatValues or \c intValues). Floating-point values are also cast to <tt>ints</tt> (and vice-versa) and stored to their respective variables. For example, an expected integer value of 64 will also be saved as 64.0 in the corresponding \c floatValues variable of the Skini::Message structure. The remainder of the line is stashed in the remainderString variable.
The ControlChange spec is basically the same as NoteOn and NoteOff, but the second data byte is set to an integer (for checking later as to what MIDI control is being changed).
@@ -155,64 +167,60 @@ The Volume spec is a MIDI Extension message, which behaves like a ControlChange
Volume 0.000000 2 64.1
\endcode
I like the 2nd line better, thus my motivation for SKINI in the first place.
I like the second line better, thus my motivation for SKINI in the first place.
The StringDamping and StringDetune messages behave the same as the Volume message, but use Control Numbers which aren't specifically nailed-down in MIDI. Note that these Control Numbers are carried around as long ints, so we're not limited to 0-127. If, however, you want to use a MIDI controller to play an instrument, using controller numbers in the 0-127 range might make sense.
\section using Using SKINI:
Here's a simple example of code which uses the SKINI object to read a SKINI file and control a single instrument.
Here's a simple example of code which uses the Skini object to read a SKINI file and control a single instrument.
\code
Skini score;
Skini::Message message;
instrument = new Mandolin(50.0);
score = new SKINI(argv[1]);
while(score->getType() > 0) {
tempDouble = score->getDelta();
if (tempDouble < 0) {
tempDouble = - tempDouble;
tempDouble = tempDouble - output.getTime();
if (tempDouble < 0) {
printf("Bad News Here!!! Backward Absolute Time Required.\n");
tempDouble = 0.0;
}
score.setFile( argv[1] );
while ( score.nextMessage( message ) != 0 ) {
tempDouble = message.time;
if (tempDouble < 0) {
tempDouble = - tempDouble;
tempDouble = tempDouble - output.getTime();
if (tempDouble < 0) {
printf("Bad News Here!!! Backward Absolute Time Required.\n");
tempDouble = 0.0;
}
tempLong = (long) (tempDouble * Stk::sampleRate());
for (i=0;i<tempLong;i++) {
output.tick(instrument->tick());
}
tempLong = (long) ( tempDouble * Stk::sampleRate() );
for ( i=0; i<tempLong; i++ ) {
output.tick( instrument->tick() );
}
tempDouble3 = message.floatValues[1] * NORM_MIDI;
if ( message.type == __SK_NoteOn_ ) {
if ( tempDouble3 == 0.0 ) {
tempDouble3 = 0.5;
instrument->noteOff( tempDouble3 );
}
tempDouble3 = score->getByteThree();
if (score->getType()== __SK_NoteOn_ ) {
tempDouble3 *= NORM_MIDI;
if (score->getByteThree() == 0) {
tempDouble3 = 0.5;
instrument->noteOff(tempDouble3);
}
else {
tempLong = (int) score->getByteTwo();
tempDouble2 = Midi2Pitch[tempLong];
instrument->noteOn(tempDouble2,tempDouble3);
}
else {
tempLong = message.intValues[0];
tempDouble2 = Midi2Pitch[tempLong];
instrument->noteOn( tempDouble2, tempDouble3 );
}
else if (score->getType() == __SK_NoteOff_) {
tempDouble3 *= NORM_MIDI;
instrument->noteOff(tempDouble3);
}
else if (score->getType() == __SK_ControlChange_) {
tempLong = score->getByteTwoInt();
instrument->controlChange(tempLong,temp3.0);
}
score->nextMessage();
}
else if ( message.type == __SK_NoteOff_ ) {
instrument->noteOff( tempDouble3 );
}
else if ( message.type == __SK_ControlChange_ ) {
tempLong = message.intValues[0];
instrument->controlChange( tempLong, tempDouble3 );
}
}
\endcode
When the score (SKINI object) object is created from the filename in argv[1], the first valid command line is read from the file and parsed.
When a SKINI score is passed to a Skini object using the Skini::setFile() function, valid messages are read from the file and returned using the Skini::nextMessage() function.
The score->getType() retrieves the messageType. If this is -1, there are no more valid messages in the file and the synthesis loop terminates. Otherwise, the message type is returned.
getDelta() retrieves the deltaTime until the current message should occur. If this is greater than 0, synthesis occurs until the deltaTime has elapsed. If deltaTime is less than zero, the time is interpreted as absolute time and the output device is queried as to what time it is now. That is used to form a deltaTime, and if it's positive we synthesize. If it's negative, we print an error and pretend this never happened and we hang around hoping to eventually catch up.
The "time" member of a Skini::Message is the deltaTime until the current message should occur. If this is greater than 0, synthesis occurs until the deltaTime has elapsed. If deltaTime is less than zero, the time is interpreted as absolute time and the output device is queried as to what time it is now. That is used to form a deltaTime, and if it's positive we synthesize. If it's negative, we print an error, pretend this never happened and we hang around hoping to eventually catch up.
The rest of the code sorts out message types NoteOn, NoteOff (including NoteOn with velocity 0), and ControlChange. The code implicitly takes into account the integer type of the control number, but all other data is treated as double float.
The last line reads and parses the next message in the file.
*/
*/

View File

@@ -2,39 +2,34 @@
<B>General:</B>
<UL>
<LI>A MIDI interface to use MIDI input controls. (NOTE: This may be built into the soundcard on your computer.)</LI>
<LI>A MIDI interface to use MIDI input/output controls. (NOTE: This may be built into the soundcard on your computer.)</LI>
<LI><A HREF="http://dev.scriptics.com">Tcl/Tk</A> version 8.0 or higher to use the simple Tcl/Tk GUIs provided with the STK distribution (available free over the WWW for all supported realtime platforms).</LI>
</UL>
<B>Linux (specific):</B>
<UL>
<LI>A soundcard to use realtime audio input/output capabilities. In order to use the <I><B>effects</B></I> project, the soundcard and drivers must support full duplex mode.</LI>
<LI><A HREF="http://www.opensound.com">OSS</A> or <A HREF="http://www.alsa-project.org/">ALSA</A> device drivers for realtime sound output and MIDI input.</LI>
<LI><A HREF="http://www.alsa-project.org/">ALSA</A> device drivers and library for realtime sound and MIDI input/output.</LI>
<LI><A HREF="http://www.opensound.com">OSS</A> device drivers (version 4.0 and higher only) can be used for audio input/output, but MIDI support requires the ALSA library to compile.</LI>
</UL>
<B>Macintosh OS X (specific):</B>
<UL>
<LI>A C++ compiler does not ship by default with OS X. It is necessary to download the Developer Kit from the Apple WWW site in order to compile STK.</LI>
<LI><B>IMPORTANT:</B>The internal Macintosh audio hardware typically supports a sample rate of 44100 Hz only. Therefore, it is necessary to either specify this rate as a command-line option to the STK example programs or to change the default sample rate inside the Stk.h file before compilation. In addition, the RT_BUFFER_SIZE, specified in Stk.h, could be increased (to a higher power of two) for more robust performance.</LI>
<LI>The tcl/tk interpreter does not ship by default with OS X, but must be downloaded from the internet. The latest Tcl/Tk Aqua distribution (http://www.apple.com/downloads/macosx/unix_open_source/tcltk.html) has been successfully tested on a 10.2 system. The default installation will place a link to the wish interpretor at /usr/bin/wish.
<LI>A C++ compiler is not installed by default with OS X. It is necessary to download the Developer Kit from the Apple WWW site in order to compile STK or load it from the installation CD-ROM.</LI>
<LI>If you experience frequent audio input/output "glitches", try increasing the RT_BUFFER_SIZE specified in Stk.h.</LI>
<LI>The tcl/tk interpreter does not ship by default with OS X and must be downloaded from the internet. The latest Tcl/Tk Aqua distribution (http://www.apple.com/downloads/macosx/unix_open_source/tcltk.html) has been successfully tested on 10.2 and 10.3 systems. The default installation will place a link to the wish interpretor at /usr/bin/wish.
Initial tests have shown somewhat poor response between changes made in the tcl/tk script and the resulting audio updates. It is possible to connect a tcl/tk interface to an STK program via a socket connection. However, the tcl/tk interpreter does not appear to properly close the socket connection during disconnection. It is therefore necessary to type "Exit" in the STK program terminal window to properly exit the STK program.</LI>
It appears that socket support in Tcl/Tk uses the Nagle algorithm, which produces poor response between changes made in the tcl/tk script and the resulting audio updates. Note that this is only a problem when using a socket connection from a Tcl/Tk script.</LI>
</UL>
<B>Windows95/98/2000/XP (specific):</B>
<B>Windows95/98/2000/XP/7 (specific):</B>
<UL>
<LI>A soundcard to use realtime audio input/output capabilities. In order to use the <I><B>effects</B></I> project, the soundcard and drivers must support full duplex mode.</LI>
<LI><A HREF="http://www.microsoft.com/directx/">DirectX</A> 5.0 (or higher) runtime libraries to use the precompiled binaries.</LI>
<LI>Visual C++ 6.0 for compiling (though a precompiled distribution is available).</LI>
<LI><A HREF="http://www.microsoft.com/directx/">DirectX</A> 5.0 (or higher) runtime libraries.</LI>
<LI>For compiling the source (if not already in your system): <UL><LI><A HREF="Misc/dsound.h">dsound.h</A> header file (DirectX 6.1) - put somewhere in your header search path</LI><LI><A HREF="Misc/dsound.lib">dsound.lib</A> library file (DirectX 6.1) - put somewhere in your library search path</LI></UL></LI>
</UL>
<B>WindowsNT (specific):</B>
<UL>
<LI>DirectX support for NT is inadequate, so it is not possible to use STK under WindowsNT with realtime DirectX support. It may be possible to use STK under WindowsNT with realtime ASIO support, though this has not been tested.</LI>
</UL>
<P>
*/
*/

View File

@@ -1,23 +1,26 @@
/*! \page tutorial Tutorial
The Synthesis ToolKit is a set of C++ classes. In order to go beyond the simple example programs we provide, it is necessary to know some basics about programming in C or C++. STK's "target audience" includes people who:
The Synthesis ToolKit is a set of C++ classes. In order to go beyond the simple example programs we provide, it is necessary to know some basics about programming in C and C++. STK's "target audience" includes people who:
<UL>
<LI>want to create audio DSP and/or synthesis programs</LI>
<LI>want to save some time by using our unit generators and input/output routines</LI>
<LI>want to use our unit generators and input/output routines rather than code their own</LI>
<LI>want to learn about synthesis and processing algorithms</LI>
<LI>wish to teach real-time synthesis and processing, and wish to use some of our classes and examples</LI>
<LI>wish to teach real-time synthesis and processing and wish to use some of our classes and examples</LI>
</UL>
Most ToolKit programmers will likely end up writing a class or two for their own particular needs, but this task is typically simplified by making use of pre-existing STK classes (filters, oscillators, etc.).
The following tutorial chapters describe many of the fundamental ToolKit concepts and classes. All tutorial programs are included in the <TT>projects/examples</TT> directory.
-# \ref fundamentals
-# \ref hello
-# \ref compile
-# \ref filtering
-# \ref realtime
-# \ref crealtime
-# \ref instruments
-# \ref controlin
-# \ref multichannel
-# \ref polyvoices
*/
*/

View File

@@ -2,6 +2,7 @@
- \ref directory
- \ref compiling
- \ref debug
- \ref control
- \ref voices
- \ref nort
@@ -21,7 +22,7 @@ The top level distribution contains the following directories:
<LI> The <I><B>include</B></I> directory contains the header files for all the STK unit generator and algorithm classes.</LI><P>
<LI> The <I><B>rawwaves</B></I> directory contains various raw, monophonic, 16-bit, big-endian soundfiles used with the STK classes.</LI><P>
<LI> The <I><B>rawwaves</B></I> directory contains various raw, monophonic, 16-bit, big-endian, 22050 Hz soundfiles used with the STK classes.</LI><P>
<LI> The <I><B>doc</B></I> directory contains documentation about STK.</LI><P>
@@ -31,33 +32,37 @@ The top level distribution contains the following directories:
This release of STK comes with four separate "project" directories:
<OL>
<LI> The <I><B>demo</B></I> project is used to demonstrate nearly all of the STK instruments. The <I><B>demo</B></I> program has been written to allow a variety of control input and sound data output options. %Simple graphical user interfaces (GUIs) are also provided.<P></LI>
<LI> The <I><B>demo</B></I> project is used to demonstrate nearly all of the STK instruments. The <I><B>demo</B></I> program has been written to allow a variety of control input and sound data output options. Simple graphical user interfaces (GUIs) are also provided.<P></LI>
<LI> The <I><B>effects</B></I> project demonstrates realtime duplex mode (simultaneous audio input and output) operation, when available, as well as various delay-line based effects algorithms.<P></LI>
<LI> The <I><B>ragamatic</B></I> project is just cool. Fire it up and be enlightened.<P></LI>
<LI> The <I><B>examples</B></I> project contains several simple programs which demonstrate audio input/output, as well as the use of the audio internet streaming classes.</LI>
<LI> The <I><B>eguitar</B></I> project demonstrates how to make an electric guitar with feedback and distortion.<P></LI>
<LI> The <I><B>examples</B></I> project contains several simple programs that demonstrate audio input/output, including the audio internet streaming classes, as well as most of the tutorial programs.</LI>
</OL>
\section compiling Compiling:
<UL>
<LI><B>Windows95/98/2000/XP:</B> Realtime support is available using either DirectSound or ASIO audio drivers. For DirectSound support, use the <TT>__WINDOWS_DS__</TT> preprocessor definition and link with the <TT>dsound.lib</TT>, <TT>winmm.lib</TT>, and <TT>Wsock32.lib</TT> libraries. For ASIO support, use the <TT>__WINDOWS_ASIO__</TT> preprocessor definition, include all the files in the <TT>src/asio/</TT> directory (i.e. <TT>asio.h,cpp</TT>, <TT>asiodrivers.h,cpp</TT>, ...), and link with the <TT>winmm.lib</TT>, and <TT>Wsock32.lib</TT> libraries. In addition, the <TT>__LITTLE_ENDIAN__</TT> preprocessor definition is necessary for all Windows systems. A distribution of the release is available with precompiled binaries (using DirectSound) for all the projects. In order for these binaries to function properly, your system must have the DirectX 5.0 (or higher) runtime libraries installed (available from <A HREF="http://www.microsoft.com/directx/">Microsoft</A>). Further, the <I><B>effects</B></I> project requires that your soundcard and drivers provide full duplex mode capabilities. Visual C++ 6.0 project files are provided in each project directory as well should you wish to compile your own binaries. It is important to link with the non-debug libraries when compiling "release" program versions and debug libraries when compiling "debug" program versions.</LI>
<LI><B>Windows95/98/2000/XP/7:</B> Realtime support is available using either DirectSound, ASIO or WASAPI audio drivers. For DirectSound support, use the <TT>__WINDOWS_DS__</TT> preprocessor definition and link with the <TT>dsound.lib</TT>, <TT>winmm.lib</TT>, and <TT>Wsock32.lib</TT> libraries. For ASIO support, use the <TT>__WINDOWS_ASIO__</TT> preprocessor definition, include all the files in the <TT>src/asio/</TT> directory (i.e. <TT>asio.h,cpp</TT>, <TT>asiodrivers.h,cpp</TT>, ...), and link with the <TT>winmm.lib</TT>, and <TT>Wsock32.lib</TT> libraries. For WASAPI support, use the <TT>__WINDOWS_WASAPI__</TT> preprocessor definition. In addition, the <TT>__LITTLE_ENDIAN__</TT> and <TT>__WINDOWS_MM__</TT> preprocessor definitions are necessary for all Windows systems (RtMidi uses the Windows MultiMedia MIDI API). Fairly old Visual C++ project files are provided in each project directory, though they may not work on newer versions of MSVS. As well, the MinGW compiler is supported (see below). It is important to link with the non-debug libraries when compiling "release" program versions and debug libraries when compiling "debug" program versions.</LI>
<LI><B>WindowsNT:</B> DirectX support for NT is inadequate, so it is not possible to use STK under WindowsNT with realtime DirectX support. It may be possible to use STK under WindowsNT with realtime ASIO support, though this has not been tested.</LI>
<LI><B>Unix Systems:</B> A GNU <TT>configure</TT> shell script is included in the distribution for unix-based systems. From the top-level distribution directory, type <TT>'./configure'</TT> and the script will create <TT>Makefiles</TT> in each project directory specific to the characteristics of the host computer. Then from within any given project directory (example <TT>demo</TT>), type <TT>'make'</TT> to compile the project. In addition, an STK library can be compiled from within the <TT>src</TT> directory.
<LI><B>Unix (and MinGW) Systems:</B> A GNU <TT>configure</TT> shell script is included in the distribution for unix-based systems. From the top-level distribution directory, type <TT>'./configure'</TT> and the script will create <TT>Makefiles</TT> in each project directory specific to the characteristics of the host computer. Then from within any given project directory (example <TT>demo</TT>), type <TT>'make'</TT> to compile the project. In addition, an STK library can be compiled from within the <TT>src</TT> directory.
Several options can be supplied to the <TT>configure</TT> script to customize the build behavior:
<UL>
<LI><TT>--disable-realtime</TT> to only compile generic non-realtime classes</LI>
<LI><TT>--enable-debug</TT> to enable various debug output</LI>
<LI><TT>--enable-midiator</TT> to enable native MS-124W MIDI support (linux only)</LI>
<LI><TT>--with-alsa</TT> to choose native ALSA API support (linux only)</LI>
<LI><TT>--with-alsa</TT> to choose native ALSA API support (default, linux only)</LI>
<LI><TT>--with-oss</TT> to choose native OSS audio API support (linux only, no native OSS MIDI support)</LI>
<LI><TT>--with-jack</TT> to choose native JACK API support (linux and Macintosh OS-X)</LI>
<LI><TT>--with-core</TT> to choose Core Audio API support (Macintosh OS-X)</LI>
<LI><TT>--with-asio</TT> to choose ASIO Audio API support (Windows)</LI>
<LI><TT>--with-ds</TT> to choose Windows Direct Sound Audio API support (Windows)</LI>
</UL>
<P>
In addition, it is possible to specify the location of the STK rawwaves and the STK include path as follows:
Note that it is possible to specify as many of the "--with-" options as desired to compile multi-API support. In addition, it is possible to specify the location of the STK rawwaves and the STK include path as follows:
\code
./configure RAWWAVE_PATH="/home/gary/rawwaves/"
./configure INCLUDE_PATH="/home/gary/include/"
@@ -68,15 +73,16 @@ For novice STK users, the default configuration should be adequate.
For those who wish to create their own system-specific <TT>Makefiles</TT>:
<UL>
<LI><B>Linux:</B> Realtime support is enabled with either the <TT>__LINUX_OSS__</TT> or <TT>__LINUX_ALSA__</TT> preprocessor definitions, which are used to select the underlying audio/MIDI system API. Realtime programs must also link with the <TT>pthread</TT> library. When using the ALSA API, it is also necessary to link with the <TT>asound</TT> library. In addition, the <TT>__LITTLE_ENDIAN__</TT> preprocessor definition is necessary if compiling on a little-endian system. Special support exists under Linux for the MIDIator serial MIDI device, enabled using the <TT>__MIDIATOR__</TT> preprocessor definition (together with either the <TT>__LINUX_ALSA__</TT> or <TT>__LINUX_OSS__</TT> definitions). See the README-Linux file for further system configuration information.</LI>
<LI><B>Linux:</B> Realtime audio support is enabled with either the <TT>__LINUX_ALSA__</TT>, <TT>__UNIX_JACK__</TT>, and/or <TT>__LINUX_OSS__</TT> preprocessor definitions, which are used to select the underlying audio system API(s). Because the ALSA library is now integrated into the standard Linux kernel, it is the default audio/MIDI API with STK versions 4.2 and higher. The <TT>__LINUX_ALSASEQ__</TT> preprocessor definition must be included for MIDI support. Note that native OSS MIDI support no longer exists in RtMidi. If the <TT>__LINUX_OSS__</TT> preprocessor definition is specified, only OSS (version 4.0) audio support will be compiled and RtMidi will still be compiled using the ALSA API (assuming the <TT>__LINUX_ALSASEQ__</TT> definition is defined). For this reason, STK now requires the <TT>asound</TT> library for realtime support. Realtime programs must also link with the <TT>pthread</TT> library. In addition, the <TT>__LITTLE_ENDIAN__</TT> preprocessor definition is necessary if compiling on a little-endian system. See the README-Linux file for further system configuration information.</LI>
<LI><B>Macintosh OS X:</B> Realtime support is enabled with the <TT>__MACOSX_CORE__</TT> preprocessor definitions, which incorporates the CoreAudio audio/MIDI API. Realtime programs must also link with the <TT>pthread</TT> library and the <TT>CoreAudio</TT>, <TT>CoreMIDI</TT>, and <TT>CoreFoundation</TT> frameworks. See the README-MacOSX file for further system configuration information.</LI>
<LI><B>Macintosh OS X:</B> Realtime support is enabled with the <TT>__MACOSX_CORE__</TT> and <TT>__UNIX_JACK__</TT> preprocessor definitions, which incorporate the CoreAudio audio/MIDI API and/or the JACK API. Realtime programs must also link with the <TT>pthread</TT> library and the <TT>CoreAudio</TT>, <TT>CoreMIDI</TT>, and <TT>CoreFoundation</TT> frameworks (for Core Audio support) and/or the JACK library. See the README-MacOSX file for further system configuration information.</LI>
<LI><B>SGI:</B> Realtime support is enabled with the <TT>__IRIX_AL__</TT> preprocessor definition and linkage with the <TT>audio</TT>, <TT>md</TT>, and <TT>pthread</TT> libraries. STK 4.0 (and higher) is confirmed to compile using CC version 7.30. There may be problems with old compiler versions.</LI>
<LI><B>Generic (non-realtime):</B> Most STK classes are operating system <I>independent</I> and can be compiled using any current C++ compiler. STK assumes big-endian host byte order by default, so if your system is little-endian (i.e. Intel processor), you must provide the <TT>__LITTLE_ENDIAN__</TT> preprocessor definition to your compiler. The <I><B>demo</B></I> project will compile without realtime support, allowing the use of SKINI scorefiles for input control and output to a variety of soundfile formats. The following classes <I>cannot</I> be used without realtime support: RtAudio, RtWvIn, RtWvOut, RtDuplex, RtMidi, Socket, Thread, TcpWvIn, TcpWvOut. Because of this, it is not possible to compile the <I><B>effects</B></I>, <I><B>ragamatic</B></I>, and most of the <I><B>examples</B></I> projects for non-realtime use.</LI>
<LI><B>Generic (non-realtime):</B> Most STK classes are operating system <I>independent</I> and can be compiled using any current C++ compiler. STK assumes big-endian host byte order by default, so if your system is little-endian (i.e. Intel processor), you must provide the <TT>__LITTLE_ENDIAN__</TT> preprocessor definition to your compiler. The <I><B>demo</B></I> project will compile without realtime support, allowing the use of SKINI scorefiles for input control and output to a variety of soundfile formats. The following classes <I>cannot</I> be used without realtime support: RtAudio, RtWvIn, RtWvOut, RtDuplex, RtMidi, Socket, Thread, Mutex, TcpWvIn, TcpWvOut. Because of this, it is not possible to compile the <I><B>effects</B></I>, <I><B>ragamatic</B></I>, and most of the <I><B>examples</B></I> projects for non-realtime use.</LI>
</UL>
\section debug Debugging:
When developing applications with STK, it is recommended that you define the preprocessor definition <TT>_STK_DEBUG_</TT> when compiling (or specify the <TT>--enable-debug</TT> option to the <TT>configure</TT> script). This will enable all levels of function argument and error checking within the STK classes. Without this definition, argument checking does not occur in functions that are expected to be called frequently in an iterative manner.
\section control Control Data:
@@ -85,11 +91,10 @@ All STK programs in this distribution take input control data in the form of <A
<OL>
<LI>Redirect or pipe SKINI scorefiles to an executable.</LI>
<LI>Pipe realtime SKINI input messages to an executable (not possible under Windows95/98).</LI>
<LI>Socket realtime SKINI input messages to an executable.</LI>
<LI>Acquire realtime MIDI messages from a MIDI port on your computer.</LI>
</OL>
<A HREF="http://dev.scriptics.com">Tcl/Tk</A> graphical user interfaces (GUI) are provided with this distribution which can generate realtime SKINI messages. Note that the Messager class allows multiple simultaneous socket client connections, together with MIDI and/or piped input. The <I><B>Md2Skini</B></I> program (in the <I><B>demo</B></I> directory) is mostly obsolete but can be used to create SKINI scorefiles from realtime MIDI input.
<A HREF="http://dev.scriptics.com">Tcl/Tk</A> graphical user interfaces (GUI) are provided with this distribution that can generate realtime SKINI messages. Note that the Messager class allows multiple simultaneous socket client connections, together with MIDI and/or piped input. The <I><B>Md2Skini</B></I> program (in the <I><B>demo</B></I> directory) is mostly obsolete but can be used to create SKINI scorefiles from realtime MIDI input.
\section voices Demo: STK Instruments
@@ -98,7 +103,7 @@ The <I><B>demo</B></I> project demonstrates the behavior of all the distributed
<UL>
<LI>Clarinet: Pretty good physical model of the clarinet</LI>
<LI>BlowHole: A clarinet physical model with one tonehole and one register vent</LI>
<LI>Saxofony: A psuedo-conical bore reed instrument which sometimes sounds like a saxophone</LI>
<LI>Saxofony: A psuedo-conical bore reed instrument that sometimes sounds like a saxophone</LI>
<LI>Flute: Pretty good physical model of the flute</LI>
<LI>Brass: Not so bad physical model of a brass instrument</LI>
<LI>BlowBotl: A basic helmholtz resonator and air jet model</LI>
@@ -132,21 +137,15 @@ See the information above with respect to compiling STK for non-realtime use.
In non-realtime mode, it is assumed that input control messages are provided from a SKINI scorefile and that audio output is written to a soundfile (.snd, .wav, .aif, .mat, .raw). A number of SKINI scorefiles are provided in the <I>scores</I> directory of the <I><B>demo</B></I> project. Assuming a successful compilation of the <I><B>demo</B></I> program, typing:
\code
cat scores/bookert.ski | demo BeeThree -ow myfile.wav
demo BeeThree -ow myfile.wav -if scores/bookert.ski
\endcode
or (on WindowsXX and/or Unix)
\code
demo BeeThree -ow myfile.wav < scores\bookert.ski
\endcode
from the <I><B>demo</B></I> directory will play the scorefile <I>bookert.ski</I> using the STK BeeThree instrument and write the resulting audio data to a WAV formatted soundfile called "myfile.wav". Typing <TT>demo</TT> without any arguments will provide a full program usage description.
from the <I><B>demo</B></I> directory will play the scorefile <I>bookert.ski</I> using the STK BeeThree instrument and write the resulting audio data to a WAV formatted soundfile called "myfile.wav" (note that you may need to append <TT>./</TT> to the program name if your default shell setup is not set to look in the current directory). Typing <TT>demo</TT> without any arguments will provide a full program usage description.
\section rt Demo: Realtime Use
STK realtime audio and MIDI input/output and realtime SKINI control input via socketing support is provided for Linux, SGI, Mac OS X, and Windows95/98/2000/XP operating systems. STK realtime SKINI control input via piping is possible under Linux, SGI, Mac OS X, and Windows2000/XP only.
STK realtime audio and MIDI input/output and realtime SKINI control input via socketing support is provided for Linux, Mac OS-X, and Windows95/98/2000/XP operating systems. STK realtime SKINI control input via piping is possible under Linux, Mac OS X, and Windows2000/XP only.
<P>
Control input and audio output options are typically specified as command-line arguments to STK programs. For example, the <I><B>demo</B></I> program is invoked as:
@@ -157,27 +156,21 @@ demo instrument flags
where instruments include those described above and flags can be any or all of:
<UL>
<LI><I>-or</I> for realtime audio output,</LI>
<LI><I>-ow <file name></I> for WAV soundfile output,</LI>
<LI><I>-os <file name></I> for SND (AU) soundfile output,</LI>
<LI><I>-om <file name></I> for MAT-file output,</LI>
<LI><I>-ow \<file name\></I> for WAV soundfile output,</LI>
<LI><I>-os \<file name\></I> for SND (AU) soundfile output,</LI>
<LI><I>-om \<file name\></I> for MAT-file output,</LI>
<LI><I>-if \<file name\></I> for a SKINI formatted control file,</LI>
<LI><I>-ip</I> for realtime SKINI control input via piping,</LI>
<LI><I>-is <port></I> > for realtime SKINI control input via socketing (with an optional port number),</LI>
<LI><I>-im <file name></I> for MIDI control input</LI>
<LI><I>-s RATE</I> to specify a sample rate</LI>
<LI><I>-im \<port\></I> for MIDI control input (with optional port, -1 = virtual port where possible),</LI>
<LI><I>-s RATE</I> to specify a sample rate,</LI>
<LI><I>-n NUMBER</I> to specify multivoice polyphony</LI>
</UL>
The <-ip> and <-is> flags must be used when piping or socketing realtime SKINI control data to an STK program. The <-im> flag must be used to read MIDI control input from your MIDI port. Note that you can use all three input types simultaneously.
The <i>-ip</i> flag must be used when piping realtime SKINI control data to an STK program. The <i>-im</i> flag must be used to read MIDI control input from your MIDI port. Note that you can use both input types simultaneously.
Assuming a successful compilation of the <I><B>demo</B></I> program, typing:
\code
cat scores/bookert.ski | demo BeeThree -or
\endcode
or (on WindowsXX and/or Unix)
\code
demo BeeThree -or < scores\bookert.ski
demo BeeThree -or -if scores/bookert.ski
\endcode
from the <I><B>demo</B></I> directory will play the scorefile <I>bookert.ski</I> using the STK BeeThree instrument and stream the resulting audio data in realtime to the audio output channel of your computer. Typing <TT>demo</TT> without any arguments will provide a full program usage description.
@@ -191,16 +184,6 @@ There are a number of <A HREF="http://dev.scriptics.com">Tcl/Tk</A> GUIs supplie
wish < tcl/Physical.tcl | demo Clarinet -or -ip
\endcode
On WindowsXX and Unix platforms, the following operations are necessary to establish a socket connection between the Tcl/Tk GUI and the STK program:
<OL>
<LI>Open a DOS shell and start the STK program with the <I>-is</I> flag (ex. <I><B>demo Clarinet -or -is</B></I>).</LI>
<LI>Open the Tcl/Tk GUI (e.g. tcl/Physical.tcl) by double-clicking on it, or type <TT>wish < tcl/Physical.tcl</TT> in another DOS shell.</LI>
<LI>Establish the socket connection by selecting <I>Socket</I> under the Communications menu item in the Tcl/Tk GUI.</LI>
</OL>
Note that it is possible to specify a hostname when establishing the socket connection from the socket client. Thus, the STK socket server program and the Tcl/Tk GUI need not necessarily reside on the same computer.
\section midi Realtime MIDI Control Input:
On all supported realtime platforms, you can direct realtime MIDI input to the STK Clarinet by typing:
@@ -209,6 +192,7 @@ On all supported realtime platforms, you can direct realtime MIDI input to the S
demo Clarinet -or -im
\endcode
This will attempt to use the default MIDI port for input. An optional MIDI port number can be specified after the <TT>-im</TT> flag. Valid MIDI ports are numbered from 0 (default) and higher. On Linux and Macintosh OS-X systems, it is possible to open a virtual MIDI input port (that other software applications can connect to) by specifying a port identifier of -1.
\section polyphony Polyphony:

179
doc/hierarchy.txt Normal file
View File

@@ -0,0 +1,179 @@
STK: A ToolKit of Audio Synthesis Classes and Instruments in C++
By Perry R. Cook and Gary P. Scavone, 1995--2014.
STK Classes - See the HTML documentation in the html directory for complete information.
.- Generator - (Modulate, Noise, SingWave, Envelope, ADSR, Asymp, SineWave, Blit, BlitSaw, BlitSquare, Granulate)
|
|- Function - (BowTable, JetTable, ReedTable)
|
|- FileRead, FileWrite
|
|- WvIn - (FileWvIn, RtWvIn, InetWvIn)
| |
| FileLoop
|
|- WvOut - (FileWvOut, RtWvOut, TcpWvOut)
|
|- Filter - (OnePole, OneZero, TwoPole, TwoZero, PoleZero, Biquad, FormSwep, Delay, DelayL, DelayA, TapDelay)
|
|- RtAudio, RtMidi, Socket, Thread, Mutex
| |
Stk -| UdpSocket
| TcpServer
| TcpClient
|
|- StkFrames
|
|- Effect - (Echo, Chorus, PitShift, LentPitShift, PRCRev, JCRev, NRev, FreeVerb)
|
|- Voicer, Message, Skini, MidiFileIn, Phonemes, Sphere, Vector3D
|
|- Messager
|
|- Twang, Guitar
|
| .- FM - (HevyMetl, PercFlut, Rhodey, Wurley, TubeBell, BeeThree, FMVoices)
| |
| |- Modal - ModalBar
| |
| |- VoicForm
| |
| |- Sampler - Moog
| |
| |- Resonate
| |
| |- Mandolin
.- Instrmnt -|
|- Drummer
|
|- Clarinet, BlowHole, Saxofony, Flute, Brass, BlowBotl, Bowed, Plucked, StifKarp, Sitar
|
|- Shakers
|
|- BandedWG
|
|- Mesh2D
|
.- Whistle
*********** UNIT GENERATORS **************
Master Class: Stk.cpp Sample rate, byte-swapping, error handling functionality
Sources: Generator.h Abstract base class for various source signal classes
Function.h Abstract base class for various input/output mapping classes
Envelope.cpp Linearly goes to target by rate
ADSR.cpp ADSR envelope
Asymp.cpp Exponentially approaches target
Noise.cpp Random number generator
SineWave.cpp Sinusoidal oscillator with internally computed static table
Blit.cpp Bandlimited impulse train
BlitSaw.cpp Bandlimited sawtooth generator
BlitSquare.cpp Bandlimited square wave generator
Granulate.cpp Granular synthesis class that processes a monophonic audio file
FileRead.cpp Audio file input class (no internal data storage) for RAW, WAV, SND (AU), AIFF, MAT-file files
WvIn.h Abstract base class for audio data input classes
FileWvIn.cpp Audio file input interface class with interpolation
FileLoop.cpp Wavetable looping (subclass of FileWvIn)
RtWvIn.cpp Realtime audio input class (subclass of WvIn)
InetWvIn.cpp Audio streaming (socket server) input class (subclass of WvIn)
Sinks: FileWrite.cpp Audio file output class (no internal data storage) for RAW, WAV, SND (AU), AIFF, MAT-file files
WvOut.h Abstract base class for audio data output classes
FileWvOut.cpp Audio file output interface class to FileWrite
RtWvOut.cpp Realtime audio output class (subclass of WvOut)
InetWvOut.cpp Audio streaming (socket client) output class (subclass of WvOut)
Filters: Filter.h Filter master class
Iir.h General infinite-impulse response filter
Fir.h General finite-impulse response filter
OneZero.cpp One zero filter
OnePole.cpp One pole filter
PoleZero.cpp One pole/one zero filter
TwoZero.cpp Two zero filter
TwoPole.cpp Two pole filter
BiQuad.cpp Two pole/two zero filter
FormSwep.cpp Sweepable biquad filter (goes to target by rate)
Delay.cpp Non-interpolating delay line class
DelayL.cpp Linearly interpolating delay line
DelayA.cpp Allpass interpolating delay line
TapDelay.cpp Multi-tap non-interpolating delay line class
Non-Linear: JetTabl.h Cubic jet non-linearity
BowTabl.h x^(-3) Bow non-linearity
ReedTabl.h One breakpoint saturating reed non-linearity
Derived: Modulate.cpp Periodic and random vibrato: WvIn, Noise, OnePole
SingWave.cpp Looping wave table with randomness: Modulate, FileLoop, Envelope
********** INSTRUMENTS AND ALGORITHMS **************
Each class is listed either with some of the unit generators it uses,
or in terms of the algorithm it implements. All inherit from Instrmnt,
which inherits from Stk.
Simple.cpp Simple Instrument Pulse oscillator + resonant filtered noise
Plucked.cpp Basic Plucked String DelayA, OneZero, OnePole, Noise
Twang.cpp Not So Basic Pluck DelayL, DlineA, Fir, allows commuted synthesis
Mandolin.cpp Commuted Mandolin 2 Twangs
Guitar.cpp N-String Guitar N Twangs, bridge coupling, allows feedback and body filter
StifKarp.cpp Plucked String with Stiffness DelayA, DelayL, OneZero, BiQuad, Noise
Bowed.cpp So So Bowed String DelayL, BowTabl, OnePole, BiQuad, WaveLoop, ADSR
Brass.cpp Not So Bad Brass Instrument DelayA, BiQuad, PoleZero, ADSR, WaveLoop
Clarinet.cpp Pretty Good Clarinet DelayL, ReedTabl, OneZero, Envelope, Noise, WaveLoop
BlowHole.cpp Clarinet w/ Tone & Vent Holes DelayL, ReedTabl, OneZero, Envelope, Noise, WaveLoop, PoleZero
Saxofony.cpp A Faux Saxophone DelayL, ReedTabl, OneZero, Envelope, Noise, WaveLoop
Flute.cpp Pretty Good Flute JetTabl, DelayL, OnePole, PoleZero, Noise, ADSR, WaveLoop
BlowBotl.cpp Blown Bottle JetTabl, BiQuad, PoleZero, Noise, ADSR, WaveLoop
BandedWG.cpp Banded Waveguide Meta-Object Delay, BowTabl, ADSR, BiQuad
Modal.cpp N Resonances Envelope, WaveLoop, BiQuad, OnePole
ModalBar.cpp Various presets 4 Resonance Models
FM.cpp N Operator FM Master ADSR, WaveLoop, TwoZero
HevyMetl.cpp Distorted FM Synthesizer 3 Cascade with FB Modulator
PercFlut.cpp Percussive Flute 3 Cascade Operators
Rhodey.cpp Rhodes-Like Electric Piano 2 Parallel Simple FMs
Wurley.cpp Wurlitzer Electric Piano 2 Parallel Simple FMs
TubeBell.cpp Classic FM Bell 2 Parallel Simple FMs
FMVoices.cpp 3 Formant FM Voice 3 Carriers Share 1 Modulator
VoicForm.cpp 4 Formant Voice Synthesis FormSwep, SingWave, OnePole, OneZero, Envelope, Noise
BeeThree.cpp Cheezy Additive Organ 4 Oscillators Additive
Sampler.cpp Sampling Synthesizer 5 each ADSR, WvIn, WaveLoop, OnePole
Moog.cpp Swept Filter Sampler with Swept Filter
Resonate.cpp Filtered Noise ADSR, BiQuad, Noise
Drummer.cpp Drum Synthesizer Bunch of WvIns, and OnePole
Shakers.cpp PhISM statistical model for shakers and real-world sound effects
Mesh2D.cpp Two-dimensional, rectilinear digital waveguide mesh.
Whistle.cpp Hybrid physical/spectral model of a police whistle.
Effect.h Effects Processor Base Class
JCRev.cpp Chowning Reverberator 3 series allpass units, 4 parallel combs, 2 stereo delays
NRev.cpp Another famous CCRMA Reverb 8 allpass, 6 parallel comb filters
PRCRev.cpp Dirt Cheap Reverb by Cook 2 allpass, 2 comb filters
FreeVerb.cpp Jezar at Dreampoint's FreeVerb 4 allpass, 8 lowpass comb filters
Flanger.cpp Flanger Effects Processor DelayL, WaveLoop
Chorus.cpp Chorus Effects Processor DelayL, WaveLoop
PitShift.cpp Cheap Pitch Shifter DelayL
LentPitShift.cpp Pitch Shifter based Lent Algorithm
*********** OTHER SUPPORT CLASSES AND FILES **************
RtAudio.cpp Multi-OS/API audio I/O routines
RtMidi.cpp Multi-OS/API MIDI I/O routines
Messager.cpp Pipe, socket, and MIDI control message handling
Voicer.cpp Multi-instrument voice manager
demo.cpp Demonstration program for most synthesis algorithms
effects.cpp Effects demonstration program
ragamatic.cpp Nirvana just waiting to happen
Skini.cpp SKINI file/message parser object
SKINI.msg #defines for often used and universal MIDI/SKINI symbols
SKINI.tbl Table of SKINI messages

72
iOS/README-iOS.md Normal file
View File

@@ -0,0 +1,72 @@
##Setup
1. Clone or [download][download_link] the STK into your project's directory.
1. Open the **STK for iOS** folder, and drag and drop **STK.xcodeproj** into your Xcode project.
1. Open your project's settings, open the *Build Phases* tab. In the *Link Binary with Libraries* section, add **libSTK.a**.
![][linking_libSTK_screenshot]
1. In your project's settings, open the *Build Settings* tab. In the *Search Paths* section, double click on the field to the right of *Header Search Paths*, and add the path to the STK's **include** directory relative to your Xcode project's directory.
![][header_search_paths_screenshot]
##Usage
1. Import the STK classes in the source files you require.
* E.g. `#import "SineWave.h"`
1. Change the extension of Objective-C files that import STK files to **.mm**.
* E.g. **ViewController.m** —> **ViewController.mm**
You can also look at the [iOS Demo project](..projects/demo/iOS%20Demo) for a sample usage.
##Troubleshooting
###'FileName.h' file not found
If you get this error when `#import`ing an STK header, you have added the wrong header search path for the STK in your project's settings (see Step 4 in Setup)
The STK's header search path you need to add is the path to the STK's **include** directory relative to your project's directory (as if you were `cd`ing into it). For example, it is `stk/include/` if the stk directory is inside your project's directory, but it is `../stk/include/` if both share the same directory.
If this problem doesn't go away:
1. Delete **STK.xcodeproj** from your Xcode project
1. Move the STK directory within your project's directory.
1. Follow step 1 from **Setup**, add `stk/include` to the *Header Search Paths*.
###FileRead::open: could not open or find file (../../rawwaves/filename.raw)!
If you use a class that makes use of raw waves (such as `Mandolin`, `Wurley`, or `Rhodey`) you need to copy the STK's raw wave files into your bundle. You'll know you need to if you get this runtime error:
`FileRead::open: could not open or find file (../../rawwaves/filename.raw)!`
1. Open your project's settings, open the *Build Phases* tab.
1. In the *Copy Bundle Resources*, drag and drop **rawwaves.bundle** (it's located in **STK.xcodeproj**'s **Helpers** folder).
1. Then add this code before using a class that needs the raw waves:
```objective-c
NSBundle *rawwaveBundle = [NSBundle bundleWithURL:[[NSBundle mainBundle] URLForResource:@"rawwaves" withExtension:@"bundle"]];
stk::Stk::setRawwavePath([[rawwaveBundle resourcePath] UTF8String]);
```
###rawwaves.bundle: No such file or directory
This means that **rawwaves.bundle** hasn't been copied to the build folder, so you'll need to do it manually:
Select the rawwaves scheme:
![][rawwaves_scheme_screenshot]
Build it (⌘+B) then build your project's main scheme.
###Apple Mach-O Linker Error
This means that **STKLib.a** isn't being linked to your binary. Follow step 2 above in [Setup](#setup).
[download_link]: https://github.com/thestk/stk/archive/master.zip
[linking_libSTK_screenshot]: http://i.imgur.com/cLbGrtq.png
[header_search_paths_screenshot]: http://i.imgur.com/iBTC06h.png
[rawwaves_scheme_screenshot]: http://i.imgur.com/PKd7epf.png

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:STK for iOS.xcodeproj">
</FileRef>
</Workspace>

10
iOS/demo/README.MD Normal file
View File

@@ -0,0 +1,10 @@
##iOS Demo Xcode project
This project briefly shows how to manually integrate the STK static library into an Xcode project. See the **README** file in the STK's `iOS` directory for precise instructions.
Currently, this project does not output sound, it only shows how to generate audio samples from the STK classes within an iOS project, and how to control STK objects via UI controls.
Note the following:
* ViewController needs to be renamed with the **.mm** extension as it's importing STK files, which are C++.
* The header search paths in the *Build Settings* of **iOS Demo.xcodeproj** point to `../../include/` because the STK's `include` directory is two directories up relative to it.

View File

@@ -0,0 +1,524 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
B02FD53618C520D60009ECA9 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B02FD53518C520D60009ECA9 /* Foundation.framework */; };
B02FD53818C520D60009ECA9 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B02FD53718C520D60009ECA9 /* CoreGraphics.framework */; };
B02FD53A18C520D60009ECA9 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B02FD53918C520D60009ECA9 /* UIKit.framework */; };
B02FD54018C520D60009ECA9 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = B02FD53E18C520D60009ECA9 /* InfoPlist.strings */; };
B02FD54218C520D60009ECA9 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = B02FD54118C520D60009ECA9 /* main.m */; };
B02FD54618C520D60009ECA9 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = B02FD54518C520D60009ECA9 /* AppDelegate.m */; };
B02FD54818C520D60009ECA9 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B02FD54718C520D60009ECA9 /* Images.xcassets */; };
B02FD54F18C520D70009ECA9 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B02FD54E18C520D70009ECA9 /* XCTest.framework */; };
B02FD55018C520D70009ECA9 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B02FD53518C520D60009ECA9 /* Foundation.framework */; };
B02FD55118C520D70009ECA9 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B02FD53918C520D60009ECA9 /* UIKit.framework */; };
B02FD55918C520D70009ECA9 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = B02FD55718C520D70009ECA9 /* InfoPlist.strings */; };
B02FD55B18C520D70009ECA9 /* iOS_DemoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B02FD55A18C520D70009ECA9 /* iOS_DemoTests.m */; };
B02FD57018C521560009ECA9 /* ViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = B02FD56F18C521560009ECA9 /* ViewController.mm */; };
B0779A8718D376F5004DA9B7 /* libSTK.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B0779A8418D376A6004DA9B7 /* libSTK.a */; };
B0779A8B18D37C13004DA9B7 /* rawwaves.bundle in Resources */ = {isa = PBXBuildFile; fileRef = B0779A8618D376A6004DA9B7 /* rawwaves.bundle */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
B02FD55218C520D70009ECA9 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = B02FD52A18C520D60009ECA9 /* Project object */;
proxyType = 1;
remoteGlobalIDString = B02FD53118C520D60009ECA9;
remoteInfo = "iOS Demo";
};
B0779A8318D376A6004DA9B7 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = B0779A7E18D376A5004DA9B7 /* STK.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = B0AC5BEE18CB31DE00D860C0;
remoteInfo = STK;
};
B0779A8518D376A6004DA9B7 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = B0779A7E18D376A5004DA9B7 /* STK.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = B0EC33B718CB73A70005787B;
remoteInfo = rawwaves;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
B02FD53218C520D60009ECA9 /* iOS Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "iOS Demo.app"; sourceTree = BUILT_PRODUCTS_DIR; };
B02FD53518C520D60009ECA9 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
B02FD53718C520D60009ECA9 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
B02FD53918C520D60009ECA9 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
B02FD53D18C520D60009ECA9 /* iOS Demo-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "iOS Demo-Info.plist"; sourceTree = "<group>"; };
B02FD53F18C520D60009ECA9 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
B02FD54118C520D60009ECA9 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
B02FD54318C520D60009ECA9 /* iOS Demo-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "iOS Demo-Prefix.pch"; sourceTree = "<group>"; };
B02FD54418C520D60009ECA9 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
B02FD54518C520D60009ECA9 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
B02FD54718C520D60009ECA9 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
B02FD54D18C520D70009ECA9 /* iOS DemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "iOS DemoTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
B02FD54E18C520D70009ECA9 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
B02FD55618C520D70009ECA9 /* iOS DemoTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "iOS DemoTests-Info.plist"; sourceTree = "<group>"; };
B02FD55818C520D70009ECA9 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
B02FD55A18C520D70009ECA9 /* iOS_DemoTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = iOS_DemoTests.m; sourceTree = "<group>"; };
B02FD56E18C521560009ECA9 /* ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = "<group>"; };
B02FD56F18C521560009ECA9 /* ViewController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ViewController.mm; sourceTree = "<group>"; };
B0779A7E18D376A5004DA9B7 /* STK.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = STK.xcodeproj; path = ../STK.xcodeproj; sourceTree = "<group>"; };
B0779A8918D37977004DA9B7 /* README.MD */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README.MD; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
B02FD52F18C520D60009ECA9 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
B0779A8718D376F5004DA9B7 /* libSTK.a in Frameworks */,
B02FD53818C520D60009ECA9 /* CoreGraphics.framework in Frameworks */,
B02FD53A18C520D60009ECA9 /* UIKit.framework in Frameworks */,
B02FD53618C520D60009ECA9 /* Foundation.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
B02FD54A18C520D70009ECA9 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
B02FD54F18C520D70009ECA9 /* XCTest.framework in Frameworks */,
B02FD55118C520D70009ECA9 /* UIKit.framework in Frameworks */,
B02FD55018C520D70009ECA9 /* Foundation.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
B02FD52918C520D60009ECA9 = {
isa = PBXGroup;
children = (
B0779A8918D37977004DA9B7 /* README.MD */,
B0779A7E18D376A5004DA9B7 /* STK.xcodeproj */,
B02FD53B18C520D60009ECA9 /* iOS Demo */,
B02FD55418C520D70009ECA9 /* iOS DemoTests */,
B02FD53418C520D60009ECA9 /* Frameworks */,
B02FD53318C520D60009ECA9 /* Products */,
);
sourceTree = "<group>";
};
B02FD53318C520D60009ECA9 /* Products */ = {
isa = PBXGroup;
children = (
B02FD53218C520D60009ECA9 /* iOS Demo.app */,
B02FD54D18C520D70009ECA9 /* iOS DemoTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
B02FD53418C520D60009ECA9 /* Frameworks */ = {
isa = PBXGroup;
children = (
B02FD53518C520D60009ECA9 /* Foundation.framework */,
B02FD53718C520D60009ECA9 /* CoreGraphics.framework */,
B02FD53918C520D60009ECA9 /* UIKit.framework */,
B02FD54E18C520D70009ECA9 /* XCTest.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
B02FD53B18C520D60009ECA9 /* iOS Demo */ = {
isa = PBXGroup;
children = (
B02FD54418C520D60009ECA9 /* AppDelegate.h */,
B02FD54518C520D60009ECA9 /* AppDelegate.m */,
B02FD56E18C521560009ECA9 /* ViewController.h */,
B02FD56F18C521560009ECA9 /* ViewController.mm */,
B02FD54718C520D60009ECA9 /* Images.xcassets */,
B02FD53C18C520D60009ECA9 /* Supporting Files */,
);
path = "iOS Demo";
sourceTree = "<group>";
};
B02FD53C18C520D60009ECA9 /* Supporting Files */ = {
isa = PBXGroup;
children = (
B02FD53D18C520D60009ECA9 /* iOS Demo-Info.plist */,
B02FD53E18C520D60009ECA9 /* InfoPlist.strings */,
B02FD54118C520D60009ECA9 /* main.m */,
B02FD54318C520D60009ECA9 /* iOS Demo-Prefix.pch */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
B02FD55418C520D70009ECA9 /* iOS DemoTests */ = {
isa = PBXGroup;
children = (
B02FD55A18C520D70009ECA9 /* iOS_DemoTests.m */,
B02FD55518C520D70009ECA9 /* Supporting Files */,
);
path = "iOS DemoTests";
sourceTree = "<group>";
};
B02FD55518C520D70009ECA9 /* Supporting Files */ = {
isa = PBXGroup;
children = (
B02FD55618C520D70009ECA9 /* iOS DemoTests-Info.plist */,
B02FD55718C520D70009ECA9 /* InfoPlist.strings */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
B0779A7F18D376A5004DA9B7 /* Products */ = {
isa = PBXGroup;
children = (
B0779A8418D376A6004DA9B7 /* libSTK.a */,
B0779A8618D376A6004DA9B7 /* rawwaves.bundle */,
);
name = Products;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
B02FD53118C520D60009ECA9 /* iOS Demo */ = {
isa = PBXNativeTarget;
buildConfigurationList = B02FD55E18C520D70009ECA9 /* Build configuration list for PBXNativeTarget "iOS Demo" */;
buildPhases = (
B02FD52E18C520D60009ECA9 /* Sources */,
B02FD52F18C520D60009ECA9 /* Frameworks */,
B02FD53018C520D60009ECA9 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = "iOS Demo";
productName = "iOS Demo";
productReference = B02FD53218C520D60009ECA9 /* iOS Demo.app */;
productType = "com.apple.product-type.application";
};
B02FD54C18C520D70009ECA9 /* iOS DemoTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = B02FD56118C520D70009ECA9 /* Build configuration list for PBXNativeTarget "iOS DemoTests" */;
buildPhases = (
B02FD54918C520D70009ECA9 /* Sources */,
B02FD54A18C520D70009ECA9 /* Frameworks */,
B02FD54B18C520D70009ECA9 /* Resources */,
);
buildRules = (
);
dependencies = (
B02FD55318C520D70009ECA9 /* PBXTargetDependency */,
);
name = "iOS DemoTests";
productName = "iOS DemoTests";
productReference = B02FD54D18C520D70009ECA9 /* iOS DemoTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
B02FD52A18C520D60009ECA9 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0510;
ORGANIZATIONNAME = "Ariel Elkin";
TargetAttributes = {
B02FD54C18C520D70009ECA9 = {
TestTargetID = B02FD53118C520D60009ECA9;
};
};
};
buildConfigurationList = B02FD52D18C520D60009ECA9 /* Build configuration list for PBXProject "iOS Demo" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = B02FD52918C520D60009ECA9;
productRefGroup = B02FD53318C520D60009ECA9 /* Products */;
projectDirPath = "";
projectReferences = (
{
ProductGroup = B0779A7F18D376A5004DA9B7 /* Products */;
ProjectRef = B0779A7E18D376A5004DA9B7 /* STK.xcodeproj */;
},
);
projectRoot = "";
targets = (
B02FD53118C520D60009ECA9 /* iOS Demo */,
B02FD54C18C520D70009ECA9 /* iOS DemoTests */,
);
};
/* End PBXProject section */
/* Begin PBXReferenceProxy section */
B0779A8418D376A6004DA9B7 /* libSTK.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libSTK.a;
remoteRef = B0779A8318D376A6004DA9B7 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
B0779A8618D376A6004DA9B7 /* rawwaves.bundle */ = {
isa = PBXReferenceProxy;
fileType = wrapper.cfbundle;
path = rawwaves.bundle;
remoteRef = B0779A8518D376A6004DA9B7 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
/* End PBXReferenceProxy section */
/* Begin PBXResourcesBuildPhase section */
B02FD53018C520D60009ECA9 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
B0779A8B18D37C13004DA9B7 /* rawwaves.bundle in Resources */,
B02FD54018C520D60009ECA9 /* InfoPlist.strings in Resources */,
B02FD54818C520D60009ECA9 /* Images.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
B02FD54B18C520D70009ECA9 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
B02FD55918C520D70009ECA9 /* InfoPlist.strings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
B02FD52E18C520D60009ECA9 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
B02FD57018C521560009ECA9 /* ViewController.mm in Sources */,
B02FD54618C520D60009ECA9 /* AppDelegate.m in Sources */,
B02FD54218C520D60009ECA9 /* main.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
B02FD54918C520D70009ECA9 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
B02FD55B18C520D70009ECA9 /* iOS_DemoTests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
B02FD55318C520D70009ECA9 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = B02FD53118C520D60009ECA9 /* iOS Demo */;
targetProxy = B02FD55218C520D70009ECA9 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
B02FD53E18C520D60009ECA9 /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
B02FD53F18C520D60009ECA9 /* en */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
};
B02FD55718C520D70009ECA9 /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
B02FD55818C520D70009ECA9 /* en */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
B02FD55C18C520D70009ECA9 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
};
name = Debug;
};
B02FD55D18C520D70009ECA9 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = YES;
ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
B02FD55F18C520D70009ECA9 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "iOS Demo/iOS Demo-Prefix.pch";
HEADER_SEARCH_PATHS = (
../../include/,
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
);
INFOPLIST_FILE = "iOS Demo/iOS Demo-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
name = Debug;
};
B02FD56018C520D70009ECA9 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "iOS Demo/iOS Demo-Prefix.pch";
HEADER_SEARCH_PATHS = (
../../include/,
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
);
INFOPLIST_FILE = "iOS Demo/iOS Demo-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
name = Release;
};
B02FD56218C520D70009ECA9 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/iOS Demo.app/iOS Demo";
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
"$(DEVELOPER_FRAMEWORKS_DIR)",
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "iOS Demo/iOS Demo-Prefix.pch";
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
INFOPLIST_FILE = "iOS DemoTests/iOS DemoTests-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUNDLE_LOADER)";
WRAPPER_EXTENSION = xctest;
};
name = Debug;
};
B02FD56318C520D70009ECA9 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/iOS Demo.app/iOS Demo";
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
"$(DEVELOPER_FRAMEWORKS_DIR)",
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "iOS Demo/iOS Demo-Prefix.pch";
INFOPLIST_FILE = "iOS DemoTests/iOS DemoTests-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUNDLE_LOADER)";
WRAPPER_EXTENSION = xctest;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
B02FD52D18C520D60009ECA9 /* Build configuration list for PBXProject "iOS Demo" */ = {
isa = XCConfigurationList;
buildConfigurations = (
B02FD55C18C520D70009ECA9 /* Debug */,
B02FD55D18C520D70009ECA9 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
B02FD55E18C520D70009ECA9 /* Build configuration list for PBXNativeTarget "iOS Demo" */ = {
isa = XCConfigurationList;
buildConfigurations = (
B02FD55F18C520D70009ECA9 /* Debug */,
B02FD56018C520D70009ECA9 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
B02FD56118C520D70009ECA9 /* Build configuration list for PBXNativeTarget "iOS DemoTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
B02FD56218C520D70009ECA9 /* Debug */,
B02FD56318C520D70009ECA9 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = B02FD52A18C520D60009ECA9 /* Project object */;
}

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:iOS Demo.xcodeproj">
</FileRef>
</Workspace>

View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDESourceControlProjectFavoriteDictionaryKey</key>
<false/>
<key>IDESourceControlProjectIdentifier</key>
<string>4E1BA790-84C0-4F40-AECE-98269B537CE6</string>
<key>IDESourceControlProjectName</key>
<string>iOS Demo</string>
<key>IDESourceControlProjectOriginsDictionary</key>
<dict>
<key>CB047168-D1C4-40BC-85A3-6EB0A20AD217</key>
<string>ssh://github.com/arielelkin/stk.git</string>
</dict>
<key>IDESourceControlProjectPath</key>
<string>iOS/Demo/iOS Demo.xcodeproj/project.xcworkspace</string>
<key>IDESourceControlProjectRelativeInstallPathDictionary</key>
<dict>
<key>CB047168-D1C4-40BC-85A3-6EB0A20AD217</key>
<string>../../../..</string>
</dict>
<key>IDESourceControlProjectURL</key>
<string>ssh://github.com/arielelkin/stk.git</string>
<key>IDESourceControlProjectVersion</key>
<integer>110</integer>
<key>IDESourceControlProjectWCCIdentifier</key>
<string>CB047168-D1C4-40BC-85A3-6EB0A20AD217</string>
<key>IDESourceControlProjectWCConfigurations</key>
<array>
<dict>
<key>IDESourceControlRepositoryExtensionIdentifierKey</key>
<string>public.vcs.git</string>
<key>IDESourceControlWCCIdentifierKey</key>
<string>CB047168-D1C4-40BC-85A3-6EB0A20AD217</string>
<key>IDESourceControlWCCName</key>
<string>stk</string>
</dict>
</array>
</dict>
</plist>

View File

@@ -0,0 +1,14 @@
//
// AppDelegate.h
// iOS Demo
//
// Created by Ariel Elkin on 03/03/2014.
//
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end

View File

@@ -0,0 +1,25 @@
//
// AppDelegate.m
// iOS Demo
//
// Created by Ariel Elkin on 03/03/2014.
//
#import "AppDelegate.h"
#import "ViewController.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
ViewController *vc = [[ViewController alloc] initWithNibName:nil bundle:nil];
[self.window setRootViewController:vc];
[self.window makeKeyAndVisible];
return YES;
}
@end

View File

@@ -0,0 +1,23 @@
{
"images" : [
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@@ -0,0 +1,23 @@
{
"images" : [
{
"orientation" : "portrait",
"idiom" : "iphone",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "2x"
},
{
"orientation" : "portrait",
"idiom" : "iphone",
"subtype" : "retina4",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@@ -0,0 +1,12 @@
//
// ViewController.h
// iOS Demo
//
// Created by Ariel Elkin on 03/03/2014.
//
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@end

View File

@@ -0,0 +1,102 @@
//
// ViewController.m
// iOS Demo
//
// Created by Ariel Elkin on 03/03/2014.
//
#import "ViewController.h"
#import "SineWave.h"
#import "Brass.h"
#import "Mandolin.h"
@implementation ViewController {
stk::SineWave *sineWave;
stk::Brass *brass;
}
- (void)loadView {
self.view = [UIView new];
[self.view setBackgroundColor:[UIColor whiteColor]];
[self setupUI];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSUInteger samplesToGenerate = 1000;
//Test SineWave:
sineWave = new stk::SineWave();
for (NSUInteger i = 0; i < samplesToGenerate; i ++) {
float sample = sineWave->tick();
NSLog(@"SineWave sample: %f", sample);
}
//Test Brass:
brass = new stk::Brass();
brass->noteOn(400, 1);
for (NSUInteger i = 0; i < samplesToGenerate; i ++) {
float sample = brass->tick();
NSLog(@"Brass sample: %f", sample);
}
//Test Mandolin:
stk::Mandolin *mandolin = new stk::Mandolin(400);
mandolin->pluck(1);
for (NSUInteger i = 0; i < samplesToGenerate; i ++) {
float sample = mandolin->tick();
NSLog(@"Mandolin sample: %f", sample);
}
#pragma mark TODO - Audio playback
}
- (void)sineSliderMoved:(UISlider *)slider {
sineWave->setFrequency(slider.value);
NSLog(@"Setting SineWave frequency to %.2f", slider.value);
}
- (void)brassSliderMoved:(UISlider *)slider {
brass->setFrequency(slider.value);
NSLog(@"Setting Brass frequency to %.2f", slider.value);
}
- (void)setupUI {
//Add slider to control sine wave frequency:
UISlider *sineSlider = [[UISlider alloc] init];
[sineSlider addTarget:self action:@selector(sineSliderMoved:) forControlEvents:UIControlEventValueChanged];
[sineSlider setMinimumValue:0];
[sineSlider setMaximumValue:800];
[sineSlider setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.view addSubview:sineSlider];
NSDictionary *metrics = @{@"sliderWidth": @200};
NSArray *sliderConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-40-[sineSlider(sliderWidth)]" options:0 metrics:metrics views:@{@"sineSlider": sineSlider}];
[self.view addConstraints:sliderConstraints];
//Add slider to control brass's frequency:
UISlider *brassSlider = [[UISlider alloc] init];
[brassSlider addTarget:self action:@selector(brassSliderMoved:) forControlEvents:UIControlEventValueChanged];
[brassSlider setMinimumValue:0];
[brassSlider setMaximumValue:800];
[brassSlider setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.view addSubview:brassSlider];
sliderConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-40-[brassSlider(sliderWidth)]" options:0 metrics:metrics views:@{@"brassSlider": brassSlider}];
[self.view addConstraints:sliderConstraints];
sliderConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-40-[sineSlider]-[brassSlider]" options:0 metrics:nil views:@{@"sineSlider": sineSlider, @"brassSlider": brassSlider}];
[self.view addConstraints:sliderConstraints];
}
@end

View File

@@ -0,0 +1,2 @@
/* Localized versions of Info.plist keys */

View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>stk.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>

View File

@@ -0,0 +1,16 @@
//
// Prefix header
//
// The contents of this file are implicitly included at the beginning of every source file.
//
#import <Availability.h>
#ifndef __IPHONE_3_0
#warning "This project uses features only available in iOS SDK 3.0 and later."
#endif
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#endif

18
iOS/demo/iOS Demo/main.m Normal file
View File

@@ -0,0 +1,18 @@
//
// main.m
// iOS Demo
//
// Created by Ariel Elkin on 03/03/2014.
// Copyright (c) 2014 Ariel Elkin. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char * argv[])
{
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}

View File

@@ -0,0 +1,2 @@
/* Localized versions of Info.plist keys */

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>stk.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>

View File

@@ -0,0 +1,34 @@
//
// iOS_DemoTests.m
// iOS DemoTests
//
// Created by Ariel Elkin on 03/03/2014.
// Copyright (c) 2014 Ariel Elkin. All rights reserved.
//
#import <XCTest/XCTest.h>
@interface iOS_DemoTests : XCTestCase
@end
@implementation iOS_DemoTests
- (void)setUp
{
[super setUp];
// Put setup code here. This method is called before the invocation of each test method in the class.
}
- (void)tearDown
{
// Put teardown code here. This method is called after the invocation of each test method in the class.
[super tearDown];
}
- (void)testExample
{
XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__);
}
@end

View File

@@ -1,88 +1,179 @@
#ifndef STK_ADSR_H
#define STK_ADSR_H
#include "Generator.h"
namespace stk {
/***************************************************/
/*! \class ADSR
\brief STK ADSR envelope class.
This Envelope subclass implements a
traditional ADSR (Attack, Decay,
Sustain, Release) envelope. It
responds to simple keyOn and keyOff
messages, keeping track of its state.
The \e state = ADSR::DONE after the
envelope value reaches 0.0 in the
ADSR::RELEASE state.
This class implements a traditional ADSR (Attack, Decay, Sustain,
Release) envelope. It responds to simple keyOn and keyOff
messages, keeping track of its state. The \e state = ADSR::IDLE
before being triggered and after the envelope value reaches 0.0 in
the ADSR::RELEASE state. All rate, target and level settings must
be non-negative. All time settings are in seconds and must be
positive.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995--2014.
*/
/***************************************************/
#if !defined(__ADSR_H)
#define __ADSR_H
#include "Envelope.h"
class ADSR : public Envelope
class ADSR : public Generator
{
public:
//! Envelope states.
enum { ATTACK, DECAY, SUSTAIN, RELEASE, DONE };
//! ADSR envelope states.
enum {
ATTACK, /*!< Attack */
DECAY, /*!< Decay */
SUSTAIN, /*!< Sustain */
RELEASE, /*!< Release */
IDLE /*!< Before attack / after release */
};
//! Default constructor.
ADSR(void);
ADSR( void );
//! Class destructor.
~ADSR(void);
~ADSR( void );
//! Set target = 1, state = \e ADSR::ATTACK.
void keyOn(void);
void keyOn( void );
//! Set target = 0, state = \e ADSR::RELEASE.
void keyOff(void);
void keyOff( void );
//! Set the attack rate.
void setAttackRate(MY_FLOAT aRate);
//! Set the attack rate (gain / sample).
void setAttackRate( StkFloat rate );
//! Set the decay rate.
void setDecayRate(MY_FLOAT aRate);
//! Set the target value for the attack (default = 1.0).
void setAttackTarget( StkFloat target );
//! Set the decay rate (gain / sample).
void setDecayRate( StkFloat rate );
//! Set the sustain level.
void setSustainLevel(MY_FLOAT aLevel);
void setSustainLevel( StkFloat level );
//! Set the release rate.
void setReleaseRate(MY_FLOAT aRate);
//! Set the release rate (gain / sample).
void setReleaseRate( StkFloat rate );
//! Set the attack rate based on a time duration.
void setAttackTime(MY_FLOAT aTime);
//! Set the attack rate based on a time duration (seconds).
void setAttackTime( StkFloat time );
//! Set the decay rate based on a time duration.
void setDecayTime(MY_FLOAT aTime);
//! Set the decay rate based on a time duration (seconds).
void setDecayTime( StkFloat time );
//! Set the release rate based on a time duration.
void setReleaseTime(MY_FLOAT aTime);
//! Set the release rate based on a time duration (seconds).
void setReleaseTime( StkFloat time );
//! Set sustain level and attack, decay, and release state rates based on time durations.
void setAllTimes(MY_FLOAT aTime, MY_FLOAT dTime, MY_FLOAT sLevel, MY_FLOAT rTime);
//! Set sustain level and attack, decay, and release time durations (seconds).
void setAllTimes( StkFloat aTime, StkFloat dTime, StkFloat sLevel, StkFloat rTime );
//! Set the target value.
void setTarget(MY_FLOAT aTarget);
//! Set a sustain target value and attack or decay from current value to target.
void setTarget( StkFloat target );
//! Return the current envelope \e state (ATTACK, DECAY, SUSTAIN, RELEASE, DONE).
int getState(void) const;
//! Return the current envelope \e state (ATTACK, DECAY, SUSTAIN, RELEASE, IDLE).
int getState( void ) const { return state_; };
//! Set to state = ADSR::SUSTAIN with current and target values of \e aValue.
void setValue(MY_FLOAT aValue);
//! Set to state = ADSR::SUSTAIN with current and target values of \e value.
void setValue( StkFloat value );
//! Return one envelope output value.
MY_FLOAT tick(void);
//! Return the last computed output value.
StkFloat lastOut( void ) const { return lastFrame_[0]; };
//! Return \e vectorSize envelope outputs in \e vector.
MY_FLOAT *tick(MY_FLOAT *vector, unsigned int vectorSize);
//! Compute and return one output sample.
StkFloat tick( void );
//! Fill a channel of the StkFrames object with computed outputs.
/*!
The \c channel argument must be less than the number of
channels in the StkFrames argument (the first channel is specified
by 0). However, range checking is only performed if _STK_DEBUG_
is defined during compilation, in which case an out-of-range value
will trigger an StkError exception.
*/
StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
protected:
MY_FLOAT attackRate;
MY_FLOAT decayRate;
MY_FLOAT sustainLevel;
MY_FLOAT releaseRate;
void sampleRateChanged( StkFloat newRate, StkFloat oldRate );
int state_;
StkFloat value_;
StkFloat target_;
StkFloat attackRate_;
StkFloat decayRate_;
StkFloat releaseRate_;
StkFloat releaseTime_;
StkFloat sustainLevel_;
};
inline StkFloat ADSR :: tick( void )
{
switch ( state_ ) {
case ATTACK:
value_ += attackRate_;
if ( value_ >= target_ ) {
value_ = target_;
target_ = sustainLevel_;
state_ = DECAY;
}
lastFrame_[0] = value_;
break;
case DECAY:
if ( value_ > sustainLevel_ ) {
value_ -= decayRate_;
if ( value_ <= sustainLevel_ ) {
value_ = sustainLevel_;
state_ = SUSTAIN;
}
}
else {
value_ += decayRate_; // attack target < sustain level
if ( value_ >= sustainLevel_ ) {
value_ = sustainLevel_;
state_ = SUSTAIN;
}
}
lastFrame_[0] = value_;
break;
case RELEASE:
value_ -= releaseRate_;
if ( value_ <= 0.0 ) {
value_ = 0.0;
state_ = IDLE;
}
lastFrame_[0] = value_;
}
return value_;
}
inline StkFrames& ADSR :: tick( StkFrames& frames, unsigned int channel )
{
#if defined(_STK_DEBUG_)
if ( channel >= frames.channels() ) {
oStream_ << "ADSR::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
StkFloat *samples = &frames[channel];
unsigned int hop = frames.channels();
for ( unsigned int i=0; i<frames.frames(); i++, samples += hop )
*samples = ADSR::tick();
return frames;
}
} // stk namespace
#endif

146
include/Asymp.h Normal file
View File

@@ -0,0 +1,146 @@
#ifndef STK_ASYMP_H
#define STK_ASYMP_H
#include "Generator.h"
namespace stk {
/***************************************************/
/*! \class Asymp
\brief STK asymptotic curve envelope class
This class implements a simple envelope generator
which asymptotically approaches a target value.
The algorithm used is of the form:
y[n] = a y[n-1] + (1-a) target,
where a = exp(-T/tau), T is the sample period, and
tau is a time constant. The user can set the time
constant (default value = 0.3) and target value.
Theoretically, this recursion never reaches its
target, though the calculations in this class are
stopped when the current value gets within a small
threshold value of the target (at which time the
current value is set to the target). It responds
to \e keyOn and \e keyOff messages by ramping to
1.0 on keyOn and to 0.0 on keyOff.
by Perry R. Cook and Gary P. Scavone, 1995--2014.
*/
/***************************************************/
const StkFloat TARGET_THRESHOLD = 0.000001;
class Asymp : public Generator
{
public:
//! Default constructor.
Asymp( void );
//! Class destructor.
~Asymp( void );
//! Set target = 1.
void keyOn( void );
//! Set target = 0.
void keyOff( void );
//! Set the asymptotic rate via the time factor \e tau (must be > 0).
/*!
The rate is computed as described above. The value of \e tau
must be greater than zero. Values of \e tau close to zero produce
fast approach rates, while values greater than 1.0 produce rather
slow rates.
*/
void setTau( StkFloat tau );
//! Set the asymptotic rate based on a time duration (must be > 0).
void setTime( StkFloat time );
//! Set the asymptotic rate such that the target value is perceptually reached (to within -60dB of the target) in \e t60 seconds.
void setT60( StkFloat t60 );
//! Set the target value.
void setTarget( StkFloat target );
//! Set current and target values to \e value.
void setValue( StkFloat value );
//! Return the current envelope \e state (0 = at target, 1 otherwise).
int getState( void ) const { return state_; };
//! Return the last computed output value.
StkFloat lastOut( void ) const { return lastFrame_[0]; };
//! Compute and return one output sample.
StkFloat tick( void );
//! Fill a channel of the StkFrames object with computed outputs.
/*!
The \c channel argument must be less than the number of
channels in the StkFrames argument (the first channel is specified
by 0). However, range checking is only performed if _STK_DEBUG_
is defined during compilation, in which case an out-of-range value
will trigger an StkError exception.
*/
StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
protected:
void sampleRateChanged( StkFloat newRate, StkFloat oldRate );
StkFloat value_;
StkFloat target_;
StkFloat factor_;
StkFloat constant_;
int state_;
};
inline StkFloat Asymp :: tick( void )
{
if ( state_ ) {
value_ = factor_ * value_ + constant_;
// Check threshold.
if ( target_ > value_ ) {
if ( target_ - value_ <= TARGET_THRESHOLD ) {
value_ = target_;
state_ = 0;
}
}
else {
if ( value_ - target_ <= TARGET_THRESHOLD ) {
value_ = target_;
state_ = 0;
}
}
lastFrame_[0] = value_;
}
return value_;
}
inline StkFrames& Asymp :: tick( StkFrames& frames, unsigned int channel )
{
#if defined(_STK_DEBUG_)
if ( channel >= frames.channels() ) {
oStream_ << "Asymp::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
StkFloat *samples = &frames[channel];
unsigned int hop = frames.channels();
for ( unsigned int i=0; i<frames.frames(); i++, samples += hop )
*samples = Asymp::tick();
return frames;
}
} // stk namespace
#endif

View File

@@ -1,3 +1,14 @@
#ifndef STK_BANDEDWG_H
#define STK_BANDEDWG_H
#include "Instrmnt.h"
#include "DelayL.h"
#include "BowTable.h"
#include "ADSR.h"
#include "BiQuad.h"
namespace stk {
/***************************************************/
/*! \class BandedWG
\brief Banded waveguide modeling class.
@@ -24,89 +35,119 @@
- Glass Harmonica = 2
- Tibetan Bowl = 3
by Georg Essl, 1999 - 2002.
Modified for Stk 4.0 by Gary Scavone.
by Georg Essl, 1999 - 2004.
Modified for STK 4.0 by Gary Scavone.
*/
/***************************************************/
#if !defined(__BANDEDWG_H)
#define __BANDEDWG_H
#define MAX_BANDED_MODES 20
#include "Instrmnt.h"
#include "DelayL.h"
#include "BowTabl.h"
#include "ADSR.h"
#include "BiQuad.h"
const int MAX_BANDED_MODES = 20;
class BandedWG : public Instrmnt
{
public:
//! Class constructor.
BandedWG();
BandedWG( void );
//! Class destructor.
~BandedWG();
~BandedWG( void );
//! Reset and clear all internal state.
void clear();
void clear( void );
//! Set strike position (0.0 - 1.0).
void setStrikePosition(MY_FLOAT position);
void setStrikePosition( StkFloat position );
//! Select a preset.
void setPreset(int preset);
void setPreset( int preset );
//! Set instrument parameters for a particular frequency.
void setFrequency(MY_FLOAT frequency);
void setFrequency( StkFloat frequency );
//! Apply bow velocity/pressure to instrument with given amplitude and rate of increase.
void startBowing(MY_FLOAT amplitude, MY_FLOAT rate);
void startBowing( StkFloat amplitude, StkFloat rate );
//! Decrease bow velocity/breath pressure with given rate of decrease.
void stopBowing(MY_FLOAT rate);
void stopBowing( StkFloat rate );
//! Pluck the instrument with given amplitude.
void pluck(MY_FLOAT amp);
void pluck( StkFloat amp );
//! Start a note with the given frequency and amplitude.
void noteOn(MY_FLOAT frequency, MY_FLOAT amplitude);
void noteOn( StkFloat frequency, StkFloat amplitude );
//! Stop a note with the given amplitude (speed of decay).
void noteOff(MY_FLOAT amplitude);
//! Compute one output sample.
MY_FLOAT tick();
void noteOff( StkFloat amplitude );
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
void controlChange(int number, MY_FLOAT value);
void controlChange( int number, StkFloat value );
//! Compute and return one output sample.
StkFloat tick( unsigned int channel = 0 );
//! Fill a channel of the StkFrames object with computed outputs.
/*!
The \c channel argument must be less than the number of
channels in the StkFrames argument (the first channel is specified
by 0). However, range checking is only performed if _STK_DEBUG_
is defined during compilation, in which case an out-of-range value
will trigger an StkError exception.
*/
StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
protected:
bool doPluck;
bool trackVelocity;
int nModes;
int presetModes;
BowTabl *bowTabl;
ADSR *adsr;
BiQuad *bandpass;
DelayL *delay;
MY_FLOAT maxVelocity;
MY_FLOAT modes[MAX_BANDED_MODES];
MY_FLOAT freakency;
MY_FLOAT baseGain;
MY_FLOAT gains[MAX_BANDED_MODES];
MY_FLOAT basegains[MAX_BANDED_MODES];
MY_FLOAT excitation[MAX_BANDED_MODES];
MY_FLOAT integrationConstant;
MY_FLOAT velocityInput;
MY_FLOAT bowVelocity;
MY_FLOAT bowTarget;
MY_FLOAT bowPosition;
MY_FLOAT strikeAmp;
int strikePosition;
bool doPluck_;
bool trackVelocity_;
int nModes_;
int presetModes_;
BowTable bowTable_;
ADSR adsr_;
BiQuad bandpass_[MAX_BANDED_MODES];
DelayL delay_[MAX_BANDED_MODES];
StkFloat maxVelocity_;
StkFloat modes_[MAX_BANDED_MODES];
StkFloat frequency_;
StkFloat baseGain_;
StkFloat gains_[MAX_BANDED_MODES];
StkFloat basegains_[MAX_BANDED_MODES];
StkFloat excitation_[MAX_BANDED_MODES];
StkFloat integrationConstant_;
StkFloat velocityInput_;
StkFloat bowVelocity_;
StkFloat bowTarget_;
StkFloat bowPosition_;
StkFloat strikeAmp_;
int strikePosition_;
};
inline StkFrames& BandedWG :: tick( StkFrames& frames, unsigned int channel )
{
unsigned int nChannels = lastFrame_.channels();
#if defined(_STK_DEBUG_)
if ( channel > frames.channels() - nChannels ) {
oStream_ << "BandedWG::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
StkFloat *samples = &frames[channel];
unsigned int j, hop = frames.channels() - nChannels;
if ( nChannels == 1 ) {
for ( unsigned int i=0; i<frames.frames(); i++, samples += hop )
*samples++ = tick();
}
else {
for ( unsigned int i=0; i<frames.frames(); i++, samples += hop ) {
*samples++ = tick();
for ( j=1; j<nChannels; j++ )
*samples++ = lastFrame_[j];
}
}
return frames;
}
} // stk namespace
#endif

View File

@@ -1,3 +1,10 @@
#ifndef STK_BEETHREE_H
#define STK_BEETHREE_H
#include "FM.h"
namespace stk {
/***************************************************/
/*! \class BeeThree
\brief STK Hammond-oid organ FM synthesis instrument.
@@ -28,29 +35,93 @@
type who should worry about this (making
money) worry away.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995--2014.
*/
/***************************************************/
#if !defined(__BEETHREE_H)
#define __BEETHREE_H
#include "FM.h"
class BeeThree : public FM
{
public:
//! Class constructor.
BeeThree();
/*!
An StkError will be thrown if the rawwave path is incorrectly set.
*/
BeeThree( void );
//! Class destructor.
~BeeThree();
~BeeThree( void );
//! Start a note with the given frequency and amplitude.
void noteOn(MY_FLOAT frequency, MY_FLOAT amplitude);
void noteOn( StkFloat frequency, StkFloat amplitude );
//! Compute and return one output sample.
StkFloat tick( unsigned int channel = 0 );
//! Fill a channel of the StkFrames object with computed outputs.
/*!
The \c channel argument must be less than the number of
channels in the StkFrames argument (the first channel is specified
by 0). However, range checking is only performed if _STK_DEBUG_
is defined during compilation, in which case an out-of-range value
will trigger an StkError exception.
*/
StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
protected:
//! Compute one output sample.
MY_FLOAT tick();
};
inline StkFloat BeeThree :: tick( unsigned int )
{
StkFloat temp;
if ( modDepth_ > 0.0 ) {
temp = 1.0 + ( modDepth_ * vibrato_.tick() * 0.1 );
waves_[0]->setFrequency( baseFrequency_ * temp * ratios_[0] );
waves_[1]->setFrequency( baseFrequency_ * temp * ratios_[1] );
waves_[2]->setFrequency( baseFrequency_ * temp * ratios_[2] );
waves_[3]->setFrequency( baseFrequency_ * temp * ratios_[3] );
}
waves_[3]->addPhaseOffset( twozero_.lastOut() );
temp = control1_ * 2.0 * gains_[3] * adsr_[3]->tick() * waves_[3]->tick();
twozero_.tick( temp );
temp += control2_ * 2.0 * gains_[2] * adsr_[2]->tick() * waves_[2]->tick();
temp += gains_[1] * adsr_[1]->tick() * waves_[1]->tick();
temp += gains_[0] * adsr_[0]->tick() * waves_[0]->tick();
lastFrame_[0] = temp * 0.125;
return lastFrame_[0];
}
inline StkFrames& BeeThree :: tick( StkFrames& frames, unsigned int channel )
{
unsigned int nChannels = lastFrame_.channels();
#if defined(_STK_DEBUG_)
if ( channel > frames.channels() - nChannels ) {
oStream_ << "BeeThree::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
StkFloat *samples = &frames[channel];
unsigned int j, hop = frames.channels() - nChannels;
if ( nChannels == 1 ) {
for ( unsigned int i=0; i<frames.frames(); i++, samples += hop )
*samples++ = tick();
}
else {
for ( unsigned int i=0; i<frames.frames(); i++, samples += hop ) {
*samples++ = tick();
for ( j=1; j<nChannels; j++ )
*samples++ = lastFrame_[j];
}
}
return frames;
}
} // stk namespace
#endif

View File

@@ -1,23 +1,23 @@
#ifndef STK_BIQUAD_H
#define STK_BIQUAD_H
#include "Filter.h"
namespace stk {
/***************************************************/
/*! \class BiQuad
\brief STK biquad (two-pole, two-zero) filter class.
This protected Filter subclass implements a
two-pole, two-zero digital filter. A method
is provided for creating a resonance in the
frequency response while maintaining a constant
filter gain.
This class implements a two-pole, two-zero digital filter.
Methods are provided for creating a resonance or notch in the
frequency response while maintaining a constant filter gain.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995--2014.
*/
/***************************************************/
#if !defined(__BIQUAD_H)
#define __BIQUAD_H
#include "Filter.h"
class BiQuad : protected Filter
class BiQuad : public Filter
{
public:
@@ -25,25 +25,28 @@ public:
BiQuad();
//! Class destructor.
virtual ~BiQuad();
~BiQuad();
//! Clears all internal states of the filter.
void clear(void);
//! A function to enable/disable the automatic updating of class data when the STK sample rate changes.
void ignoreSampleRateChange( bool ignore = true ) { ignoreSampleRateChange_ = ignore; };
//! Set all filter coefficients.
void setCoefficients( StkFloat b0, StkFloat b1, StkFloat b2, StkFloat a1, StkFloat a2, bool clearState = false );
//! Set the b[0] coefficient value.
void setB0(MY_FLOAT b0);
void setB0( StkFloat b0 ) { b_[0] = b0; };
//! Set the b[1] coefficient value.
void setB1(MY_FLOAT b1);
void setB1( StkFloat b1 ) { b_[1] = b1; };
//! Set the b[2] coefficient value.
void setB2(MY_FLOAT b2);
void setB2( StkFloat b2 ) { b_[2] = b2; };
//! Set the a[1] coefficient value.
void setA1(MY_FLOAT a1);
void setA1( StkFloat a1 ) { a_[1] = a1; };
//! Set the a[2] coefficient value.
void setA2(MY_FLOAT a2);
void setA2( StkFloat a2 ) { a_[2] = a2; };
//! Sets the filter coefficients for a resonance at \e frequency (in Hz).
/*!
@@ -56,17 +59,20 @@ public:
filter frequency response has a resonance at the given \e
frequency. The closer the poles are to the unit-circle (\e radius
close to one), the narrower the resulting resonance width.
An unstable filter will result for \e radius >= 1.0. The
\e frequency value should be between zero and half the sample rate.
*/
void setResonance(MY_FLOAT frequency, MY_FLOAT radius, bool normalize = FALSE);
void setResonance( StkFloat frequency, StkFloat radius, bool normalize = false );
//! Set the filter coefficients for a notch at \e frequency (in Hz).
/*!
This method determines the filter coefficients corresponding to
two complex-conjugate zeros with the given \e frequency (in Hz)
and \e radius from the z-plane origin. No filter normalization
is attempted.
and \e radius from the z-plane origin. No filter normalization is
attempted. The \e frequency value should be between zero and half
the sample rate. The \e radius value should be positive.
*/
void setNotch(MY_FLOAT frequency, MY_FLOAT radius);
void setNotch( StkFloat frequency, StkFloat radius );
//! Sets the filter zeroes for equal resonance gain.
/*!
@@ -75,26 +81,106 @@ public:
where R is the pole radius setting.
*/
void setEqualGainZeroes();
//! Set the filter gain.
/*!
The gain is applied at the filter input and does not affect the
coefficient values. The default gain value is 1.0.
*/
void setGain(MY_FLOAT theGain);
//! Return the current filter gain.
MY_FLOAT getGain(void) const;
void setEqualGainZeroes( void );
//! Return the last computed output value.
MY_FLOAT lastOut(void) const;
StkFloat lastOut( void ) const { return lastFrame_[0]; };
//! Input one sample to the filter and return one output.
MY_FLOAT tick(MY_FLOAT sample);
//! Input one sample to the filter and return a reference to one output.
StkFloat tick( StkFloat input );
//! Input \e vectorSize samples to the filter and return an equal number of outputs in \e vector.
MY_FLOAT *tick(MY_FLOAT *vector, unsigned int vectorSize);
//! Take a channel of the StkFrames object as inputs to the filter and replace with corresponding outputs.
/*!
The StkFrames argument reference is returned. The \c channel
argument must be less than the number of channels in the
StkFrames argument (the first channel is specified by 0).
However, range checking is only performed if _STK_DEBUG_ is
defined during compilation, in which case an out-of-range value
will trigger an StkError exception.
*/
StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
//! Take a channel of the \c iFrames object as inputs to the filter and write outputs to the \c oFrames object.
/*!
The \c iFrames object reference is returned. Each channel
argument must be less than the number of channels in the
corresponding StkFrames argument (the first channel is specified
by 0). However, range checking is only performed if _STK_DEBUG_
is defined during compilation, in which case an out-of-range value
will trigger an StkError exception.
*/
StkFrames& tick( StkFrames& iFrames, StkFrames &oFrames, unsigned int iChannel = 0, unsigned int oChannel = 0 );
protected:
virtual void sampleRateChanged( StkFloat newRate, StkFloat oldRate );
};
inline StkFloat BiQuad :: tick( StkFloat input )
{
inputs_[0] = gain_ * input;
lastFrame_[0] = b_[0] * inputs_[0] + b_[1] * inputs_[1] + b_[2] * inputs_[2];
lastFrame_[0] -= a_[2] * outputs_[2] + a_[1] * outputs_[1];
inputs_[2] = inputs_[1];
inputs_[1] = inputs_[0];
outputs_[2] = outputs_[1];
outputs_[1] = lastFrame_[0];
return lastFrame_[0];
}
inline StkFrames& BiQuad :: tick( StkFrames& frames, unsigned int channel )
{
#if defined(_STK_DEBUG_)
if ( channel >= frames.channels() ) {
oStream_ << "BiQuad::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
StkFloat *samples = &frames[channel];
unsigned int hop = frames.channels();
for ( unsigned int i=0; i<frames.frames(); i++, samples += hop ) {
inputs_[0] = gain_ * *samples;
*samples = b_[0] * inputs_[0] + b_[1] * inputs_[1] + b_[2] * inputs_[2];
*samples -= a_[2] * outputs_[2] + a_[1] * outputs_[1];
inputs_[2] = inputs_[1];
inputs_[1] = inputs_[0];
outputs_[2] = outputs_[1];
outputs_[1] = *samples;
}
lastFrame_[0] = outputs_[1];
return frames;
}
inline StkFrames& BiQuad :: tick( StkFrames& iFrames, StkFrames& oFrames, unsigned int iChannel, unsigned int oChannel )
{
#if defined(_STK_DEBUG_)
if ( iChannel >= iFrames.channels() || oChannel >= oFrames.channels() ) {
oStream_ << "BiQuad::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
StkFloat *iSamples = &iFrames[iChannel];
StkFloat *oSamples = &oFrames[oChannel];
unsigned int iHop = iFrames.channels(), oHop = oFrames.channels();
for ( unsigned int i=0; i<iFrames.frames(); i++, iSamples += iHop, oSamples += oHop ) {
inputs_[0] = gain_ * *iSamples;
*oSamples = b_[0] * inputs_[0] + b_[1] * inputs_[1] + b_[2] * inputs_[2];
*oSamples -= a_[2] * outputs_[2] + a_[1] * outputs_[1];
inputs_[2] = inputs_[1];
inputs_[1] = inputs_[0];
outputs_[2] = outputs_[1];
outputs_[1] = *oSamples;
}
lastFrame_[0] = outputs_[1];
return iFrames;
}
} // stk namespace
#endif

151
include/Blit.h Normal file
View File

@@ -0,0 +1,151 @@
#ifndef STK_BLIT_H
#define STK_BLIT_H
#include "Generator.h"
#include <cmath>
#include <limits>
namespace stk {
/***************************************************/
/*! \class Blit
\brief STK band-limited impulse train class.
This class generates a band-limited impulse train using a
closed-form algorithm reported by Stilson and Smith in "Alias-Free
Digital Synthesis of Classic Analog Waveforms", 1996. The user
can specify both the fundamental frequency of the impulse train
and the number of harmonics contained in the resulting signal.
The signal is normalized so that the peak value is +/-1.0.
If nHarmonics is 0, then the signal will contain all harmonics up
to half the sample rate. Note, however, that this setting may
produce aliasing in the signal when the frequency is changing (no
automatic modification of the number of harmonics is performed by
the setFrequency() function).
Original code by Robin Davies, 2005.
Revisions by Gary Scavone for STK, 2005.
*/
/***************************************************/
class Blit: public Generator
{
public:
//! Default constructor that initializes BLIT frequency to 220 Hz.
Blit( StkFloat frequency = 220.0 );
//! Class destructor.
~Blit();
//! Resets the oscillator state and phase to 0.
void reset();
//! Set the phase of the signal.
/*!
Set the phase of the signal, in the range 0 to 1.
*/
void setPhase( StkFloat phase ) { phase_ = PI * phase; };
//! Get the current phase of the signal.
/*!
Get the phase of the signal, in the range [0 to 1.0).
*/
StkFloat getPhase() const { return phase_ / PI; };
//! Set the impulse train rate in terms of a frequency in Hz.
void setFrequency( StkFloat frequency );
//! Set the number of harmonics generated in the signal.
/*!
This function sets the number of harmonics contained in the
resulting signal. It is equivalent to (2 * M) + 1 in the BLIT
algorithm. The default value of 0 sets the algorithm for maximum
harmonic content (harmonics up to half the sample rate). This
parameter is not checked against the current sample rate and
fundamental frequency. Thus, aliasing can result if one or more
harmonics for a given fundamental frequency exceeds fs / 2. This
behavior was chosen over the potentially more problematic solution
of automatically modifying the M parameter, which can produce
audible clicks in the signal.
*/
void setHarmonics( unsigned int nHarmonics = 0 );
//! Return the last computed output value.
StkFloat lastOut( void ) const { return lastFrame_[0]; };
//! Compute and return one output sample.
StkFloat tick( void );
//! Fill a channel of the StkFrames object with computed outputs.
/*!
The \c channel argument must be less than the number of
channels in the StkFrames argument (the first channel is specified
by 0). However, range checking is only performed if _STK_DEBUG_
is defined during compilation, in which case an out-of-range value
will trigger an StkError exception.
*/
StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
protected:
void updateHarmonics( void );
unsigned int nHarmonics_;
unsigned int m_;
StkFloat rate_;
StkFloat phase_;
StkFloat p_;
};
inline StkFloat Blit :: tick( void )
{
// The code below implements the SincM algorithm of Stilson and
// Smith with an additional scale factor of P / M applied to
// normalize the output.
// A fully optimized version of this code would replace the two sin
// calls with a pair of fast sin oscillators, for which stable fast
// two-multiply algorithms are well known. In the spirit of STK,
// which favors clarity over performance, the optimization has not
// been made here.
// Avoid a divide by zero at the sinc peak, which has a limiting
// value of 1.0.
StkFloat tmp, denominator = sin( phase_ );
if ( denominator <= std::numeric_limits<StkFloat>::epsilon() )
tmp = 1.0;
else {
tmp = sin( m_ * phase_ );
tmp /= m_ * denominator;
}
phase_ += rate_;
if ( phase_ >= PI ) phase_ -= PI;
lastFrame_[0] = tmp;
return lastFrame_[0];
}
inline StkFrames& Blit :: tick( StkFrames& frames, unsigned int channel )
{
#if defined(_STK_DEBUG_)
if ( channel >= frames.channels() ) {
oStream_ << "Blit::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
StkFloat *samples = &frames[channel];
unsigned int hop = frames.channels();
for ( unsigned int i=0; i<frames.frames(); i++, samples += hop )
*samples = Blit::tick();
return frames;
}
} // stk namespace
#endif

148
include/BlitSaw.h Normal file
View File

@@ -0,0 +1,148 @@
#ifndef STK_BLITSAW_H
#define STK_BLITSAW_H
#include "Generator.h"
#include <cmath>
#include <limits>
namespace stk {
/***************************************************/
/*! \class BlitSaw
\brief STK band-limited sawtooth wave class.
This class generates a band-limited sawtooth waveform using a
closed-form algorithm reported by Stilson and Smith in "Alias-Free
Digital Synthesis of Classic Analog Waveforms", 1996. The user
can specify both the fundamental frequency of the sawtooth and the
number of harmonics contained in the resulting signal.
If nHarmonics is 0, then the signal will contain all harmonics up
to half the sample rate. Note, however, that this setting may
produce aliasing in the signal when the frequency is changing (no
automatic modification of the number of harmonics is performed by
the setFrequency() function).
Based on initial code of Robin Davies, 2005.
Modified algorithm code by Gary Scavone, 2005.
*/
/***************************************************/
class BlitSaw: public Generator
{
public:
//! Class constructor.
BlitSaw( StkFloat frequency = 220.0 );
//! Class destructor.
~BlitSaw();
//! Resets the oscillator state and phase to 0.
void reset();
//! Set the sawtooth oscillator rate in terms of a frequency in Hz.
void setFrequency( StkFloat frequency );
//! Set the number of harmonics generated in the signal.
/*!
This function sets the number of harmonics contained in the
resulting signal. It is equivalent to (2 * M) + 1 in the BLIT
algorithm. The default value of 0 sets the algorithm for maximum
harmonic content (harmonics up to half the sample rate). This
parameter is not checked against the current sample rate and
fundamental frequency. Thus, aliasing can result if one or more
harmonics for a given fundamental frequency exceeds fs / 2. This
behavior was chosen over the potentially more problematic solution
of automatically modifying the M parameter, which can produce
audible clicks in the signal.
*/
void setHarmonics( unsigned int nHarmonics = 0 );
//! Return the last computed output value.
StkFloat lastOut( void ) const { return lastFrame_[0]; };
//! Compute and return one output sample.
StkFloat tick( void );
//! Fill a channel of the StkFrames object with computed outputs.
/*!
The \c channel argument must be less than the number of
channels in the StkFrames argument (the first channel is specified
by 0). However, range checking is only performed if _STK_DEBUG_
is defined during compilation, in which case an out-of-range value
will trigger an StkError exception.
*/
StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
protected:
void updateHarmonics( void );
unsigned int nHarmonics_;
unsigned int m_;
StkFloat rate_;
StkFloat phase_;
StkFloat p_;
StkFloat C2_;
StkFloat a_;
StkFloat state_;
};
inline StkFloat BlitSaw :: tick( void )
{
// The code below implements the BLIT algorithm of Stilson and
// Smith, followed by a summation and filtering operation to produce
// a sawtooth waveform. After experimenting with various approaches
// to calculate the average value of the BLIT over one period, I
// found that an estimate of C2_ = 1.0 / period (in samples) worked
// most consistently. A "leaky integrator" is then applied to the
// difference of the BLIT output and C2_. (GPS - 1 October 2005)
// A fully optimized version of this code would replace the two sin
// calls with a pair of fast sin oscillators, for which stable fast
// two-multiply algorithms are well known. In the spirit of STK,
// which favors clarity over performance, the optimization has
// not been made here.
// Avoid a divide by zero, or use of a denormalized divisor
// at the sinc peak, which has a limiting value of m_ / p_.
StkFloat tmp, denominator = sin( phase_ );
if ( fabs(denominator) <= std::numeric_limits<StkFloat>::epsilon() )
tmp = a_;
else {
tmp = sin( m_ * phase_ );
tmp /= p_ * denominator;
}
tmp += state_ - C2_;
state_ = tmp * 0.995;
phase_ += rate_;
if ( phase_ >= PI ) phase_ -= PI;
lastFrame_[0] = tmp;
return lastFrame_[0];
}
inline StkFrames& BlitSaw :: tick( StkFrames& frames, unsigned int channel )
{
#if defined(_STK_DEBUG_)
if ( channel >= frames.channels() ) {
oStream_ << "BlitSaw::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
StkFloat *samples = &frames[channel];
unsigned int hop = frames.channels();
for ( unsigned int i=0; i<frames.frames(); i++, samples += hop )
*samples = BlitSaw::tick();
return frames;
}
} // stk namespace
#endif

170
include/BlitSquare.h Normal file
View File

@@ -0,0 +1,170 @@
#ifndef STK_BLITSQUARE_H
#define STK_BLITSQUARE_H
#include "Generator.h"
#include <cmath>
#include <limits>
namespace stk {
/***************************************************/
/*! \class BlitSquare
\brief STK band-limited square wave class.
This class generates a band-limited square wave signal. It is
derived in part from the approach reported by Stilson and Smith in
"Alias-Free Digital Synthesis of Classic Analog Waveforms", 1996.
The algorithm implemented in this class uses a SincM function with
an even M value to achieve a bipolar bandlimited impulse train.
This signal is then integrated to achieve a square waveform. The
integration process has an associated DC offset so a DC blocking
filter is applied at the output.
The user can specify both the fundamental frequency of the
waveform and the number of harmonics contained in the resulting
signal.
If nHarmonics is 0, then the signal will contain all harmonics up
to half the sample rate. Note, however, that this setting may
produce aliasing in the signal when the frequency is changing (no
automatic modification of the number of harmonics is performed by
the setFrequency() function). Also note that the harmonics of a
square wave fall at odd integer multiples of the fundamental, so
aliasing will happen with a lower fundamental than with the other
Blit waveforms. This class is not guaranteed to be well behaved
in the presence of significant aliasing.
Based on initial code of Robin Davies, 2005.
Modified algorithm code by Gary Scavone, 2005 - 2006.
*/
/***************************************************/
class BlitSquare: public Generator
{
public:
//! Default constructor that initializes BLIT frequency to 220 Hz.
BlitSquare( StkFloat frequency = 220.0 );
//! Class destructor.
~BlitSquare();
//! Resets the oscillator state and phase to 0.
void reset();
//! Set the phase of the signal.
/*!
Set the phase of the signal, in the range 0 to 1.
*/
void setPhase( StkFloat phase ) { phase_ = PI * phase; };
//! Get the current phase of the signal.
/*!
Get the phase of the signal, in the range [0 to 1.0).
*/
StkFloat getPhase() const { return phase_ / PI; };
//! Set the impulse train rate in terms of a frequency in Hz.
void setFrequency( StkFloat frequency );
//! Set the number of harmonics generated in the signal.
/*!
This function sets the number of harmonics contained in the
resulting signal. It is equivalent to (2 * M) + 1 in the BLIT
algorithm. The default value of 0 sets the algorithm for maximum
harmonic content (harmonics up to half the sample rate). This
parameter is not checked against the current sample rate and
fundamental frequency. Thus, aliasing can result if one or more
harmonics for a given fundamental frequency exceeds fs / 2. This
behavior was chosen over the potentially more problematic solution
of automatically modifying the M parameter, which can produce
audible clicks in the signal.
*/
void setHarmonics( unsigned int nHarmonics = 0 );
//! Return the last computed output value.
StkFloat lastOut( void ) const { return lastFrame_[0]; };
//! Compute and return one output sample.
StkFloat tick( void );
//! Fill a channel of the StkFrames object with computed outputs.
/*!
The \c channel argument must be less than the number of
channels in the StkFrames argument (the first channel is specified
by 0). However, range checking is only performed if _STK_DEBUG_
is defined during compilation, in which case an out-of-range value
will trigger an StkError exception.
*/
StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
protected:
void updateHarmonics( void );
unsigned int nHarmonics_;
unsigned int m_;
StkFloat rate_;
StkFloat phase_;
StkFloat p_;
StkFloat a_;
StkFloat lastBlitOutput_;
StkFloat dcbState_;
};
inline StkFloat BlitSquare :: tick( void )
{
StkFloat temp = lastBlitOutput_;
// A fully optimized version of this would replace the two sin calls
// with a pair of fast sin oscillators, for which stable fast
// two-multiply algorithms are well known. In the spirit of STK,
// which favors clarity over performance, the optimization has
// not been made here.
// Avoid a divide by zero, or use of a denomralized divisor
// at the sinc peak, which has a limiting value of 1.0.
StkFloat denominator = sin( phase_ );
if ( fabs( denominator ) < std::numeric_limits<StkFloat>::epsilon() ) {
// Inexact comparison safely distinguishes betwen *close to zero*, and *close to PI*.
if ( phase_ < 0.1f || phase_ > TWO_PI - 0.1f )
lastBlitOutput_ = a_;
else
lastBlitOutput_ = -a_;
}
else {
lastBlitOutput_ = sin( m_ * phase_ );
lastBlitOutput_ /= p_ * denominator;
}
lastBlitOutput_ += temp;
// Now apply DC blocker.
lastFrame_[0] = lastBlitOutput_ - dcbState_ + 0.999 * lastFrame_[0];
dcbState_ = lastBlitOutput_;
phase_ += rate_;
if ( phase_ >= TWO_PI ) phase_ -= TWO_PI;
return lastFrame_[0];
}
inline StkFrames& BlitSquare :: tick( StkFrames& frames, unsigned int channel )
{
#if defined(_STK_DEBUG_)
if ( channel >= frames.channels() ) {
oStream_ << "BlitSquare::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
StkFloat *samples = &frames[channel];
unsigned int hop = frames.channels();
for ( unsigned int i=0; i<frames.frames(); i++, samples += hop )
*samples = BlitSquare::tick();
return frames;
}
} // stk namespace
#endif

View File

@@ -1,3 +1,16 @@
#ifndef STK_BLOWBOTL_H
#define STK_BLOWBOTL_H
#include "Instrmnt.h"
#include "JetTable.h"
#include "BiQuad.h"
#include "PoleZero.h"
#include "Noise.h"
#include "ADSR.h"
#include "SineWave.h"
namespace stk {
/***************************************************/
/*! \class BlowBotl
\brief STK blown bottle instrument class.
@@ -12,66 +25,120 @@
- Vibrato Gain = 1
- Volume = 128
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995--2014.
*/
/***************************************************/
#if !defined(__BOTTLE_H)
#define __BOTTLE_H
#include "Instrmnt.h"
#include "JetTabl.h"
#include "BiQuad.h"
#include "PoleZero.h"
#include "Noise.h"
#include "ADSR.h"
#include "WaveLoop.h"
class BlowBotl : public Instrmnt
{
public:
//! Class constructor.
BlowBotl();
/*!
An StkError will be thrown if the rawwave path is incorrectly set.
*/
BlowBotl( void );
//! Class destructor.
~BlowBotl();
~BlowBotl( void );
//! Reset and clear all internal state.
void clear();
void clear( void );
//! Set instrument parameters for a particular frequency.
void setFrequency(MY_FLOAT frequency);
void setFrequency( StkFloat frequency );
//! Apply breath velocity to instrument with given amplitude and rate of increase.
void startBlowing(MY_FLOAT amplitude, MY_FLOAT rate);
void startBlowing( StkFloat amplitude, StkFloat rate );
//! Decrease breath velocity with given rate of decrease.
void stopBlowing(MY_FLOAT rate);
void stopBlowing( StkFloat rate );
//! Start a note with the given frequency and amplitude.
void noteOn(MY_FLOAT frequency, MY_FLOAT amplitude);
void noteOn( StkFloat frequency, StkFloat amplitude );
//! Stop a note with the given amplitude (speed of decay).
void noteOff(MY_FLOAT amplitude);
//! Compute one output sample.
MY_FLOAT tick();
void noteOff( StkFloat amplitude );
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
void controlChange(int number, MY_FLOAT value);
void controlChange( int number, StkFloat value );
protected:
JetTabl *jetTable;
BiQuad *resonator;
PoleZero *dcBlock;
Noise *noise;
ADSR *adsr;
WaveLoop *vibrato;
MY_FLOAT maxPressure;
MY_FLOAT noiseGain;
MY_FLOAT vibratoGain;
MY_FLOAT outputGain;
//! Compute and return one output sample.
StkFloat tick( unsigned int channel = 0 );
//! Fill a channel of the StkFrames object with computed outputs.
/*!
The \c channel argument must be less than the number of
channels in the StkFrames argument (the first channel is specified
by 0). However, range checking is only performed if _STK_DEBUG_
is defined during compilation, in which case an out-of-range value
will trigger an StkError exception.
*/
StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
protected:
JetTable jetTable_;
BiQuad resonator_;
PoleZero dcBlock_;
Noise noise_;
ADSR adsr_;
SineWave vibrato_;
StkFloat maxPressure_;
StkFloat noiseGain_;
StkFloat vibratoGain_;
StkFloat outputGain_;
};
inline StkFloat BlowBotl :: tick( unsigned int )
{
StkFloat breathPressure;
StkFloat randPressure;
StkFloat pressureDiff;
// Calculate the breath pressure (envelope + vibrato)
breathPressure = maxPressure_ * adsr_.tick();
breathPressure += vibratoGain_ * vibrato_.tick();
pressureDiff = breathPressure - resonator_.lastOut();
randPressure = noiseGain_ * noise_.tick();
randPressure *= breathPressure;
randPressure *= (1.0 + pressureDiff);
resonator_.tick( breathPressure + randPressure - ( jetTable_.tick( pressureDiff ) * pressureDiff ) );
lastFrame_[0] = 0.2 * outputGain_ * dcBlock_.tick( pressureDiff );
return lastFrame_[0];
}
inline StkFrames& BlowBotl :: tick( StkFrames& frames, unsigned int channel )
{
unsigned int nChannels = lastFrame_.channels();
#if defined(_STK_DEBUG_)
if ( channel > frames.channels() - nChannels ) {
oStream_ << "BlowBotl::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
StkFloat *samples = &frames[channel];
unsigned int j, hop = frames.channels() - nChannels;
if ( nChannels == 1 ) {
for ( unsigned int i=0; i<frames.frames(); i++, samples += hop )
*samples++ = tick();
}
else {
for ( unsigned int i=0; i<frames.frames(); i++, samples += hop ) {
*samples++ = tick();
for ( j=1; j<nChannels; j++ )
*samples++ = lastFrame_[j];
}
}
return frames;
}
} // stk namespace
#endif

View File

@@ -1,3 +1,17 @@
#ifndef STK_BLOWHOLE_H
#define STK_BLOWHOLE_H
#include "Instrmnt.h"
#include "DelayL.h"
#include "ReedTable.h"
#include "OneZero.h"
#include "PoleZero.h"
#include "Envelope.h"
#include "Noise.h"
#include "SineWave.h"
namespace stk {
/***************************************************/
/*! \class BlowHole
\brief STK clarinet physical model with one
@@ -29,80 +43,143 @@
- Register State = 1
- Breath Pressure = 128
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995--2014.
*/
/***************************************************/
#if !defined(__BLOWHOLE_H)
#define __BLOWHOLE_H
#include "Instrmnt.h"
#include "DelayL.h"
#include "ReedTabl.h"
#include "OneZero.h"
#include "PoleZero.h"
#include "Envelope.h"
#include "Noise.h"
#include "WaveLoop.h"
class BlowHole : public Instrmnt
{
public:
//! Class constructor.
BlowHole(MY_FLOAT lowestFrequency);
/*!
An StkError will be thrown if the rawwave path is incorrectly set.
*/
BlowHole( StkFloat lowestFrequency );
//! Class destructor.
~BlowHole();
~BlowHole( void );
//! Reset and clear all internal state.
void clear();
void clear( void );
//! Set instrument parameters for a particular frequency.
void setFrequency(MY_FLOAT frequency);
void setFrequency( StkFloat frequency );
//! Set the tonehole state (0.0 = closed, 1.0 = fully open).
void setTonehole(MY_FLOAT newValue);
void setTonehole( StkFloat newValue );
//! Set the register hole state (0.0 = closed, 1.0 = fully open).
void setVent(MY_FLOAT newValue);
void setVent( StkFloat newValue );
//! Apply breath pressure to instrument with given amplitude and rate of increase.
void startBlowing(MY_FLOAT amplitude, MY_FLOAT rate);
void startBlowing( StkFloat amplitude, StkFloat rate );
//! Decrease breath pressure with given rate of decrease.
void stopBlowing(MY_FLOAT rate);
void stopBlowing( StkFloat rate );
//! Start a note with the given frequency and amplitude.
void noteOn(MY_FLOAT frequency, MY_FLOAT amplitude);
void noteOn( StkFloat frequency, StkFloat amplitude );
//! Stop a note with the given amplitude (speed of decay).
void noteOff(MY_FLOAT amplitude);
//! Compute one output sample.
MY_FLOAT tick();
void noteOff( StkFloat amplitude );
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
void controlChange(int number, MY_FLOAT value);
void controlChange( int number, StkFloat value );
protected:
DelayL *delays[3];
ReedTabl *reedTable;
OneZero *filter;
PoleZero *tonehole;
PoleZero *vent;
Envelope *envelope;
Noise *noise;
WaveLoop *vibrato;
long length;
MY_FLOAT scatter;
MY_FLOAT th_coeff;
MY_FLOAT r_th;
MY_FLOAT rh_coeff;
MY_FLOAT rh_gain;
MY_FLOAT outputGain;
MY_FLOAT noiseGain;
MY_FLOAT vibratoGain;
//! Compute and return one output sample.
StkFloat tick( unsigned int channel = 0 );
//! Fill a channel of the StkFrames object with computed outputs.
/*!
The \c channel argument must be less than the number of
channels in the StkFrames argument (the first channel is specified
by 0). However, range checking is only performed if _STK_DEBUG_
is defined during compilation, in which case an out-of-range value
will trigger an StkError exception.
*/
StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
protected:
DelayL delays_[3];
ReedTable reedTable_;
OneZero filter_;
PoleZero tonehole_;
PoleZero vent_;
Envelope envelope_;
Noise noise_;
SineWave vibrato_;
StkFloat scatter_;
StkFloat thCoeff_;
StkFloat rhGain_;
StkFloat outputGain_;
StkFloat noiseGain_;
StkFloat vibratoGain_;
};
inline StkFloat BlowHole :: tick( unsigned int )
{
StkFloat pressureDiff;
StkFloat breathPressure;
StkFloat temp;
// Calculate the breath pressure (envelope + noise + vibrato)
breathPressure = envelope_.tick();
breathPressure += breathPressure * noiseGain_ * noise_.tick();
breathPressure += breathPressure * vibratoGain_ * vibrato_.tick();
// Calculate the differential pressure = reflected - mouthpiece pressures
pressureDiff = delays_[0].lastOut() - breathPressure;
// Do two-port junction scattering for register vent
StkFloat pa = breathPressure + pressureDiff * reedTable_.tick( pressureDiff );
StkFloat pb = delays_[1].lastOut();
vent_.tick( pa+pb );
lastFrame_[0] = delays_[0].tick( vent_.lastOut()+pb );
lastFrame_[0] *= outputGain_;
// Do three-port junction scattering (under tonehole)
pa += vent_.lastOut();
pb = delays_[2].lastOut();
StkFloat pth = tonehole_.lastOut();
temp = scatter_ * (pa + pb - 2 * pth);
delays_[2].tick( filter_.tick(pa + temp) * -0.95 );
delays_[1].tick( pb + temp );
tonehole_.tick( pa + pb - pth + temp );
return lastFrame_[0];
}
inline StkFrames& BlowHole :: tick( StkFrames& frames, unsigned int channel )
{
unsigned int nChannels = lastFrame_.channels();
#if defined(_STK_DEBUG_)
if ( channel > frames.channels() - nChannels ) {
oStream_ << "BlowHole::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
StkFloat *samples = &frames[channel];
unsigned int j, hop = frames.channels() - nChannels;
if ( nChannels == 1 ) {
for ( unsigned int i=0; i<frames.frames(); i++, samples += hop )
*samples++ = tick();
}
else {
for ( unsigned int i=0; i<frames.frames(); i++, samples += hop ) {
*samples++ = tick();
for ( j=1; j<nChannels; j++ )
*samples++ = lastFrame_[j];
}
}
return frames;
}
} // stk namespace
#endif

View File

@@ -1,62 +0,0 @@
/***************************************************/
/*! \class BowTabl
\brief STK bowed string table class.
This class implements a simple bowed string
non-linear function, as described by Smith (1986).
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
*/
/***************************************************/
#if !defined(__BOWTABL_H)
#define __BOWTABL_H
#include "Stk.h"
class BowTabl : public Stk
{
public:
//! Default constructor.
BowTabl();
//! Class destructor.
~BowTabl();
//! Set the table offset value.
/*!
The table offset is a bias which controls the
symmetry of the friction. If you want the
friction to vary with direction, use a non-zero
value for the offset. The default value is zero.
*/
void setOffset(MY_FLOAT aValue);
//! Set the table slope value.
/*!
The table slope controls the width of the friction
pulse, which is related to bow force.
*/
void setSlope(MY_FLOAT aValue);
//! Return the last output value.
MY_FLOAT lastOut(void) const;
//! Return the function value for \e input.
/*!
The function input represents differential
string-to-bow velocity.
*/
MY_FLOAT tick(const MY_FLOAT input);
//! Take \e vectorSize inputs and return the corresponding function values in \e vector.
MY_FLOAT *tick(MY_FLOAT *vector, unsigned int vectorSize);
protected:
MY_FLOAT offSet;
MY_FLOAT slope;
MY_FLOAT lastOutput;
};
#endif

150
include/BowTable.h Normal file
View File

@@ -0,0 +1,150 @@
#ifndef STK_BOWTABL_H
#define STK_BOWTABL_H
#include "Function.h"
#include <cmath>
namespace stk {
/***************************************************/
/*! \class BowTable
\brief STK bowed string table class.
This class implements a simple bowed string
non-linear function, as described by Smith
(1986). The output is an instantaneous
reflection coefficient value.
by Perry R. Cook and Gary P. Scavone, 1995--2014.
*/
/***************************************************/
class BowTable : public Function
{
public:
//! Default constructor.
BowTable( void ) : offset_(0.0), slope_(0.1), minOutput_(0.01), maxOutput_(0.98) {};
//! Set the table offset value.
/*!
The table offset is a bias which controls the
symmetry of the friction. If you want the
friction to vary with direction, use a non-zero
value for the offset. The default value is zero.
*/
void setOffset( StkFloat offset ) { offset_ = offset; };
//! Set the table slope value.
/*!
The table slope controls the width of the friction
pulse, which is related to bow force.
*/
void setSlope( StkFloat slope ) { slope_ = slope; };
//! Set the minimum table output value (0.0 - 1.0).
void setMinOutput( StkFloat minimum ) { minOutput_ = minimum; };
//! Set the maximum table output value (0.0 - 1.0).
void setMaxOutput( StkFloat maximum ) { maxOutput_ = maximum; };
//! Take one sample input and map to one sample of output.
StkFloat tick( StkFloat input );
//! Take a channel of the StkFrames object as inputs to the table and replace with corresponding outputs.
/*!
The StkFrames argument reference is returned. The \c channel
argument must be less than the number of channels in the
StkFrames argument (the first channel is specified by 0).
However, range checking is only performed if _STK_DEBUG_ is
defined during compilation, in which case an out-of-range value
will trigger an StkError exception.
*/
StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
//! Take a channel of the \c iFrames object as inputs to the table and write outputs to the \c oFrames object.
/*!
The \c iFrames object reference is returned. Each channel
argument must be less than the number of channels in the
corresponding StkFrames argument (the first channel is specified
by 0). However, range checking is only performed if _STK_DEBUG_
is defined during compilation, in which case an out-of-range value
will trigger an StkError exception.
*/
StkFrames& tick( StkFrames& iFrames, StkFrames &oFrames, unsigned int iChannel = 0, unsigned int oChannel = 0 );
protected:
StkFloat offset_;
StkFloat slope_;
StkFloat minOutput_;
StkFloat maxOutput_;
};
inline StkFloat BowTable :: tick( StkFloat input )
{
// The input represents differential string vs. bow velocity.
StkFloat sample = input + offset_; // add bias to input
sample *= slope_; // then scale it
lastFrame_[0] = (StkFloat) fabs( (double) sample ) + (StkFloat) 0.75;
lastFrame_[0] = (StkFloat) pow( lastFrame_[0], (StkFloat) -4.0 );
// Set minimum threshold
if ( lastFrame_[0] < minOutput_ ) lastFrame_[0] = minOutput_;
// Set maximum threshold
if ( lastFrame_[0] > maxOutput_ ) lastFrame_[0] = maxOutput_;
return lastFrame_[0];
}
inline StkFrames& BowTable :: tick( StkFrames& frames, unsigned int channel )
{
#if defined(_STK_DEBUG_)
if ( channel >= frames.channels() ) {
oStream_ << "BowTable::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
StkFloat *samples = &frames[channel];
unsigned int hop = frames.channels();
for ( unsigned int i=0; i<frames.frames(); i++, samples += hop ) {
*samples = *samples + offset_;
*samples *= slope_;
*samples = (StkFloat) fabs( (double) *samples ) + 0.75;
*samples = (StkFloat) pow( *samples, (StkFloat) -4.0 );
if ( *samples > 1.0) *samples = 1.0;
}
lastFrame_[0] = *(samples-hop);
return frames;
}
inline StkFrames& BowTable :: tick( StkFrames& iFrames, StkFrames& oFrames, unsigned int iChannel, unsigned int oChannel )
{
#if defined(_STK_DEBUG_)
if ( iChannel >= iFrames.channels() || oChannel >= oFrames.channels() ) {
oStream_ << "BowTable::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
StkFloat *iSamples = &iFrames[iChannel];
StkFloat *oSamples = &oFrames[oChannel];
unsigned int iHop = iFrames.channels(), oHop = oFrames.channels();
for ( unsigned int i=0; i<iFrames.frames(); i++, iSamples += iHop, oSamples += oHop ) {
*oSamples = *iSamples + offset_;
*oSamples *= slope_;
*oSamples = (StkFloat) fabs( (double) *oSamples ) + 0.75;
*oSamples = (StkFloat) pow( *oSamples, (StkFloat) -4.0 );
if ( *oSamples > 1.0) *oSamples = 1.0;
}
lastFrame_[0] = *(oSamples-oHop);
return iFrames;
}
} // stk namespace
#endif

View File

@@ -1,3 +1,16 @@
#ifndef STK_BOWED_H
#define STK_BOWED_H
#include "Instrmnt.h"
#include "DelayL.h"
#include "BowTable.h"
#include "OnePole.h"
#include "BiQuad.h"
#include "SineWave.h"
#include "ADSR.h"
namespace stk {
/***************************************************/
/*! \class Bowed
\brief STK bowed string instrument class.
@@ -15,72 +28,130 @@
- Bow Position = 4
- Vibrato Frequency = 11
- Vibrato Gain = 1
- Bow Velocity = 100
- Frequency = 101
- Volume = 128
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995--2014.
Contributions by Esteban Maestre, 2011.
*/
/***************************************************/
#if !defined(__BOWED_H)
#define __BOWED_H
#include "Instrmnt.h"
#include "DelayL.h"
#include "BowTabl.h"
#include "OnePole.h"
#include "BiQuad.h"
#include "WaveLoop.h"
#include "ADSR.h"
class Bowed : public Instrmnt
{
public:
//! Class constructor, taking the lowest desired playing frequency.
Bowed(MY_FLOAT lowestFrequency);
Bowed( StkFloat lowestFrequency = 8.0 );
//! Class destructor.
~Bowed();
~Bowed( void );
//! Reset and clear all internal state.
void clear();
void clear( void );
//! Set instrument parameters for a particular frequency.
void setFrequency(MY_FLOAT frequency);
void setFrequency( StkFloat frequency );
//! Set vibrato gain.
void setVibrato(MY_FLOAT gain);
void setVibrato( StkFloat gain ) { vibratoGain_ = gain; };
//! Apply breath pressure to instrument with given amplitude and rate of increase.
void startBowing(MY_FLOAT amplitude, MY_FLOAT rate);
void startBowing( StkFloat amplitude, StkFloat rate );
//! Decrease breath pressure with given rate of decrease.
void stopBowing(MY_FLOAT rate);
void stopBowing( StkFloat rate );
//! Start a note with the given frequency and amplitude.
void noteOn(MY_FLOAT frequency, MY_FLOAT amplitude);
void noteOn( StkFloat frequency, StkFloat amplitude );
//! Stop a note with the given amplitude (speed of decay).
void noteOff(MY_FLOAT amplitude);
//! Compute one output sample.
MY_FLOAT tick();
void noteOff( StkFloat amplitude );
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
void controlChange(int number, MY_FLOAT value);
void controlChange( int number, StkFloat value );
protected:
DelayL *neckDelay;
DelayL *bridgeDelay;
BowTabl *bowTable;
OnePole *stringFilter;
BiQuad *bodyFilter;
WaveLoop *vibrato;
ADSR *adsr;
MY_FLOAT maxVelocity;
MY_FLOAT baseDelay;
MY_FLOAT vibratoGain;
MY_FLOAT betaRatio;
//! Compute and return one output sample.
StkFloat tick( unsigned int channel = 0 );
//! Fill a channel of the StkFrames object with computed outputs.
/*!
The \c channel argument must be less than the number of
channels in the StkFrames argument (the first channel is specified
by 0). However, range checking is only performed if _STK_DEBUG_
is defined during compilation, in which case an out-of-range value
will trigger an StkError exception.
*/
StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
protected:
DelayL neckDelay_;
DelayL bridgeDelay_;
BowTable bowTable_;
OnePole stringFilter_;
BiQuad bodyFilters_[6];
SineWave vibrato_;
ADSR adsr_;
bool bowDown_;
StkFloat maxVelocity_;
StkFloat baseDelay_;
StkFloat vibratoGain_;
StkFloat betaRatio_;
};
inline StkFloat Bowed :: tick( unsigned int )
{
StkFloat bowVelocity = maxVelocity_ * adsr_.tick();
StkFloat bridgeReflection = -stringFilter_.tick( bridgeDelay_.lastOut() );
StkFloat nutReflection = -neckDelay_.lastOut();
StkFloat stringVelocity = bridgeReflection + nutReflection;
StkFloat deltaV = bowVelocity - stringVelocity; // Differential velocity
StkFloat newVelocity = 0.0;
if ( bowDown_ )
newVelocity = deltaV * bowTable_.tick( deltaV ); // Non-Linear bow function
neckDelay_.tick( bridgeReflection + newVelocity); // Do string propagations
bridgeDelay_.tick(nutReflection + newVelocity);
if ( vibratoGain_ > 0.0 ) {
neckDelay_.setDelay( (baseDelay_ * (1.0 - betaRatio_) ) +
(baseDelay_ * vibratoGain_ * vibrato_.tick()) );
}
lastFrame_[0] = 0.1248 * bodyFilters_[5].tick( bodyFilters_[4].tick( bodyFilters_[3].tick( bodyFilters_[2].tick( bodyFilters_[1].tick( bodyFilters_[0].tick( bridgeDelay_.lastOut() ) ) ) ) ) );
return lastFrame_[0];
}
inline StkFrames& Bowed :: tick( StkFrames& frames, unsigned int channel )
{
unsigned int nChannels = lastFrame_.channels();
#if defined(_STK_DEBUG_)
if ( channel > frames.channels() - nChannels ) {
oStream_ << "Bowed::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
StkFloat *samples = &frames[channel];
unsigned int j, hop = frames.channels() - nChannels;
if ( nChannels == 1 ) {
for ( unsigned int i=0; i<frames.frames(); i++, samples += hop )
*samples++ = tick();
}
else {
for ( unsigned int i=0; i<frames.frames(); i++, samples += hop ) {
*samples++ = tick();
for ( j=1; j<nChannels; j++ )
*samples++ = lastFrame_[j];
}
}
return frames;
}
} // stk namespace
#endif

View File

@@ -1,3 +1,15 @@
#ifndef STK_BRASS_H
#define STK_BRASS_H
#include "Instrmnt.h"
#include "DelayA.h"
#include "BiQuad.h"
#include "PoleZero.h"
#include "ADSR.h"
#include "SineWave.h"
namespace stk {
/***************************************************/
/*! \class Brass
\brief STK simple brass instrument class.
@@ -16,68 +28,120 @@
- Vibrato Gain = 1
- Volume = 128
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995--2014.
*/
/***************************************************/
#if !defined(__BRASS_H)
#define __BRASS_H
#include "Instrmnt.h"
#include "DelayA.h"
#include "BiQuad.h"
#include "PoleZero.h"
#include "ADSR.h"
#include "WaveLoop.h"
class Brass: public Instrmnt
{
public:
//! Class constructor, taking the lowest desired playing frequency.
Brass(MY_FLOAT lowestFrequency);
/*!
An StkError will be thrown if the rawwave path is incorrectly set.
*/
Brass( StkFloat lowestFrequency = 8.0 );
//! Class destructor.
~Brass();
~Brass( );
//! Reset and clear all internal state.
void clear();
void clear( );
//! Set instrument parameters for a particular frequency.
void setFrequency(MY_FLOAT frequency);
void setFrequency( StkFloat frequency );
//! Set the lips frequency.
void setLip(MY_FLOAT frequency);
void setLip( StkFloat frequency );
//! Apply breath pressure to instrument with given amplitude and rate of increase.
void startBlowing(MY_FLOAT amplitude,MY_FLOAT rate);
void startBlowing( StkFloat amplitude, StkFloat rate );
//! Decrease breath pressure with given rate of decrease.
void stopBlowing(MY_FLOAT rate);
void stopBlowing( StkFloat rate );
//! Start a note with the given frequency and amplitude.
void noteOn(MY_FLOAT frequency, MY_FLOAT amplitude);
void noteOn( StkFloat frequency, StkFloat amplitude );
//! Stop a note with the given amplitude (speed of decay).
void noteOff(MY_FLOAT amplitude);
//! Compute one output sample.
MY_FLOAT tick();
void noteOff( StkFloat amplitude );
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
void controlChange(int number, MY_FLOAT value);
void controlChange( int number, StkFloat value );
protected:
DelayA *delayLine;
BiQuad *lipFilter;
PoleZero *dcBlock;
ADSR *adsr;
WaveLoop *vibrato;
long length;
MY_FLOAT lipTarget;
MY_FLOAT slideTarget;
MY_FLOAT vibratoGain;
MY_FLOAT maxPressure;
//! Compute and return one output sample.
StkFloat tick( unsigned int channel = 0 );
//! Fill a channel of the StkFrames object with computed outputs.
/*!
The \c channel argument must be less than the number of
channels in the StkFrames argument (the first channel is specified
by 0). However, range checking is only performed if _STK_DEBUG_
is defined during compilation, in which case an out-of-range value
will trigger an StkError exception.
*/
StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
protected:
DelayA delayLine_;
BiQuad lipFilter_;
PoleZero dcBlock_;
ADSR adsr_;
SineWave vibrato_;
StkFloat lipTarget_;
StkFloat slideTarget_;
StkFloat vibratoGain_;
StkFloat maxPressure_;
};
inline StkFloat Brass :: tick( unsigned int )
{
StkFloat breathPressure = maxPressure_ * adsr_.tick();
breathPressure += vibratoGain_ * vibrato_.tick();
StkFloat mouthPressure = 0.3 * breathPressure;
StkFloat borePressure = 0.85 * delayLine_.lastOut();
StkFloat deltaPressure = mouthPressure - borePressure; // Differential pressure.
deltaPressure = lipFilter_.tick( deltaPressure ); // Force - > position.
deltaPressure *= deltaPressure; // Basic position to area mapping.
if ( deltaPressure > 1.0 ) deltaPressure = 1.0; // Non-linear saturation.
// The following input scattering assumes the mouthPressure = area.
lastFrame_[0] = deltaPressure * mouthPressure + ( 1.0 - deltaPressure) * borePressure;
lastFrame_[0] = delayLine_.tick( dcBlock_.tick( lastFrame_[0] ) );
return lastFrame_[0];
}
inline StkFrames& Brass :: tick( StkFrames& frames, unsigned int channel )
{
unsigned int nChannels = lastFrame_.channels();
#if defined(_STK_DEBUG_)
if ( channel > frames.channels() - nChannels ) {
oStream_ << "Brass::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
StkFloat *samples = &frames[channel];
unsigned int j, hop = frames.channels() - nChannels;
if ( nChannels == 1 ) {
for ( unsigned int i=0; i<frames.frames(); i++, samples += hop )
*samples++ = tick();
}
else {
for ( unsigned int i=0; i<frames.frames(); i++, samples += hop ) {
*samples++ = tick();
for ( j=1; j<nChannels; j++ )
*samples++ = lastFrame_[j];
}
}
return frames;
}
} // stk namespace
#endif

View File

@@ -1,65 +1,172 @@
#ifndef STK_CHORUS_H
#define STK_CHORUS_H
#include "Effect.h"
#include "DelayL.h"
#include "SineWave.h"
namespace stk {
/***************************************************/
/*! \class Chorus
\brief STK chorus effect class.
This class implements a chorus effect.
This class implements a chorus effect. It takes a monophonic
input signal and produces a stereo output signal.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995--2014.
*/
/***************************************************/
#if !defined(__CHORUS_H)
#define __CHORUS_H
#include "Stk.h"
#include "DelayL.h"
#include "WaveLoop.h"
class Chorus : public Stk
class Chorus : public Effect
{
public:
//! Class constructor, taking the longest desired delay length.
Chorus(MY_FLOAT baseDelay);
//! Class destructor.
~Chorus();
//! Class constructor, taking the median desired delay length.
/*!
An StkError can be thrown if the rawwave path is incorrect.
*/
Chorus( StkFloat baseDelay = 6000 );
//! Reset and clear all internal state.
void clear();
void clear( void );
//! Set modulation depth.
void setModDepth(MY_FLOAT depth);
//! Set modulation depth in range 0.0 - 1.0.
void setModDepth( StkFloat depth );
//! Set modulation frequency.
void setModFrequency(MY_FLOAT frequency);
void setModFrequency( StkFloat frequency );
//! Set the mixture of input and processed levels in the output (0.0 = input only, 1.0 = processed only).
void setEffectMix(MY_FLOAT mix);
//! Return the specified channel value of the last computed stereo frame.
/*!
Use the lastFrame() function to get both values of the last
computed stereo frame. The \c channel argument must be 0 or 1
(the first channel is specified by 0). However, range checking is
only performed if _STK_DEBUG_ is defined during compilation, in
which case an out-of-range value will trigger an StkError
exception.
*/
StkFloat lastOut( unsigned int channel = 0 );
//! Return the last output value.
MY_FLOAT lastOut() const;
//! Input one sample to the effect and return the specified \c channel value of the computed stereo frame.
/*!
Use the lastFrame() function to get both values of the computed
stereo output frame. The \c channel argument must be 0 or 1 (the
first channel is specified by 0). However, range checking is only
performed if _STK_DEBUG_ is defined during compilation, in which
case an out-of-range value will trigger an StkError exception.
*/
StkFloat tick( StkFloat input, unsigned int channel = 0 );
//! Return the last left output value.
MY_FLOAT lastOutLeft() const;
//! Take a channel of the StkFrames object as inputs to the effect and replace with stereo outputs.
/*!
The StkFrames argument reference is returned. The stereo
outputs are written to the StkFrames argument starting at the
specified \c channel. Therefore, the \c channel argument must be
less than ( channels() - 1 ) of the StkFrames argument (the first
channel is specified by 0). However, range checking is only
performed if _STK_DEBUG_ is defined during compilation, in which
case an out-of-range value will trigger an StkError exception.
*/
StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
//! Return the last right output value.
MY_FLOAT lastOutRight() const;
//! Take a channel of the \c iFrames object as inputs to the effect and write stereo outputs to the \c oFrames object.
/*!
The \c iFrames object reference is returned. The \c iChannel
argument must be less than the number of channels in the \c
iFrames argument (the first channel is specified by 0). The \c
oChannel argument must be less than ( channels() - 1 ) of the \c
oFrames argument. However, range checking is only performed if
_STK_DEBUG_ is defined during compilation, in which case an
out-of-range value will trigger an StkError exception.
*/
StkFrames& tick( StkFrames& iFrames, StkFrames &oFrames, unsigned int iChannel = 0, unsigned int oChannel = 0 );
//! Compute one output sample.
MY_FLOAT tick(MY_FLOAT input);
protected:
//! Take \e vectorSize inputs, compute the same number of outputs and return them in \e vector.
MY_FLOAT *tick(MY_FLOAT *vector, unsigned int vectorSize);
protected:
DelayL *delayLine[2];
WaveLoop *mods[2];
MY_FLOAT baseLength;
MY_FLOAT modDepth;
MY_FLOAT lastOutput[2];
MY_FLOAT effectMix;
DelayL delayLine_[2];
SineWave mods_[2];
StkFloat baseLength_;
StkFloat modDepth_;
};
inline StkFloat Chorus :: lastOut( unsigned int channel )
{
#if defined(_STK_DEBUG_)
if ( channel > 1 ) {
oStream_ << "Chorus::lastOut(): channel argument must be less than 2!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
return lastFrame_[channel];
}
inline StkFloat Chorus :: tick( StkFloat input, unsigned int channel )
{
#if defined(_STK_DEBUG_)
if ( channel > 1 ) {
oStream_ << "Chorus::tick(): channel argument must be less than 2!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
delayLine_[0].setDelay( baseLength_ * 0.707 * ( 1.0 + modDepth_ * mods_[0].tick() ) );
delayLine_[1].setDelay( baseLength_ * 0.5 * ( 1.0 - modDepth_ * mods_[1].tick() ) );
lastFrame_[0] = effectMix_ * ( delayLine_[0].tick( input ) - input ) + input;
lastFrame_[1] = effectMix_ * ( delayLine_[1].tick( input ) - input ) + input;
return lastFrame_[channel];
}
inline StkFrames& Chorus :: tick( StkFrames& frames, unsigned int channel )
{
#if defined(_STK_DEBUG_)
if ( channel >= frames.channels() - 1 ) {
oStream_ << "Chorus::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
StkFloat *samples = &frames[channel];
unsigned int hop = frames.channels() - 1;
for ( unsigned int i=0; i<frames.frames(); i++, samples += hop ) {
delayLine_[0].setDelay( baseLength_ * 0.707 * ( 1.0 + modDepth_ * mods_[0].tick() ) );
delayLine_[1].setDelay( baseLength_ * 0.5 * ( 1.0 - modDepth_ * mods_[1].tick() ) );
*samples = effectMix_ * ( delayLine_[0].tick( *samples ) - *samples ) + *samples;
samples++;
*samples = effectMix_ * ( delayLine_[1].tick( *samples ) - *samples ) + *samples;
}
lastFrame_[0] = *(samples-hop);
lastFrame_[1] = *(samples-hop+1);
return frames;
}
inline StkFrames& Chorus :: tick( StkFrames& iFrames, StkFrames& oFrames, unsigned int iChannel, unsigned int oChannel )
{
#if defined(_STK_DEBUG_)
if ( iChannel >= iFrames.channels() || oChannel >= oFrames.channels() - 1 ) {
oStream_ << "Chorus::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
StkFloat *iSamples = &iFrames[iChannel];
StkFloat *oSamples = &oFrames[oChannel];
unsigned int iHop = iFrames.channels(), oHop = oFrames.channels();
for ( unsigned int i=0; i<iFrames.frames(); i++, iSamples += iHop, oSamples += oHop ) {
delayLine_[0].setDelay( baseLength_ * 0.707 * ( 1.0 + modDepth_ * mods_[0].tick() ) );
delayLine_[1].setDelay( baseLength_ * 0.5 * ( 1.0 - modDepth_ * mods_[1].tick() ) );
*oSamples = effectMix_ * ( delayLine_[0].tick( *iSamples ) - *iSamples ) + *iSamples;
*(oSamples+1) = effectMix_ * ( delayLine_[1].tick( *iSamples ) - *iSamples ) + *iSamples;
}
lastFrame_[0] = *(oSamples-oHop);
lastFrame_[1] = *(oSamples-oHop+1);
return iFrames;
}
} // stk namespace
#endif

View File

@@ -1,3 +1,16 @@
#ifndef STK_CLARINET_H
#define STK_CLARINET_H
#include "Instrmnt.h"
#include "DelayL.h"
#include "ReedTable.h"
#include "OneZero.h"
#include "Envelope.h"
#include "Noise.h"
#include "SineWave.h"
namespace stk {
/***************************************************/
/*! \class Clarinet
\brief STK clarinet physical model class.
@@ -18,66 +31,122 @@
- Vibrato Gain = 1
- Breath Pressure = 128
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995--2014.
*/
/***************************************************/
#if !defined(__CLARINET_H)
#define __CLARINET_H
#include "Instrmnt.h"
#include "DelayL.h"
#include "ReedTabl.h"
#include "OneZero.h"
#include "Envelope.h"
#include "Noise.h"
#include "WaveLoop.h"
class Clarinet : public Instrmnt
{
public:
//! Class constructor, taking the lowest desired playing frequency.
Clarinet(MY_FLOAT lowestFrequency);
/*!
An StkError will be thrown if the rawwave path is incorrectly set.
*/
Clarinet( StkFloat lowestFrequency = 8.0 );
//! Class destructor.
~Clarinet();
~Clarinet( void );
//! Reset and clear all internal state.
void clear();
void clear( void );
//! Set instrument parameters for a particular frequency.
void setFrequency(MY_FLOAT frequency);
void setFrequency( StkFloat frequency );
//! Apply breath pressure to instrument with given amplitude and rate of increase.
void startBlowing(MY_FLOAT amplitude, MY_FLOAT rate);
void startBlowing( StkFloat amplitude, StkFloat rate );
//! Decrease breath pressure with given rate of decrease.
void stopBlowing(MY_FLOAT rate);
void stopBlowing( StkFloat rate );
//! Start a note with the given frequency and amplitude.
void noteOn(MY_FLOAT frequency, MY_FLOAT amplitude);
void noteOn( StkFloat frequency, StkFloat amplitude );
//! Stop a note with the given amplitude (speed of decay).
void noteOff(MY_FLOAT amplitude);
//! Compute one output sample.
MY_FLOAT tick();
void noteOff( StkFloat amplitude );
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
void controlChange(int number, MY_FLOAT value);
void controlChange( int number, StkFloat value );
//! Compute and return one output sample.
StkFloat tick( unsigned int channel = 0 );
//! Fill a channel of the StkFrames object with computed outputs.
/*!
The \c channel argument must be less than the number of
channels in the StkFrames argument (the first channel is specified
by 0). However, range checking is only performed if _STK_DEBUG_
is defined during compilation, in which case an out-of-range value
will trigger an StkError exception.
*/
StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
protected:
DelayL *delayLine;
ReedTabl *reedTable;
OneZero *filter;
Envelope *envelope;
Noise *noise;
WaveLoop *vibrato;
long length;
MY_FLOAT outputGain;
MY_FLOAT noiseGain;
MY_FLOAT vibratoGain;
DelayL delayLine_;
ReedTable reedTable_;
OneZero filter_;
Envelope envelope_;
Noise noise_;
SineWave vibrato_;
StkFloat outputGain_;
StkFloat noiseGain_;
StkFloat vibratoGain_;
};
inline StkFloat Clarinet :: tick( unsigned int )
{
StkFloat pressureDiff;
StkFloat breathPressure;
// Calculate the breath pressure (envelope + noise + vibrato)
breathPressure = envelope_.tick();
breathPressure += breathPressure * noiseGain_ * noise_.tick();
breathPressure += breathPressure * vibratoGain_ * vibrato_.tick();
// Perform commuted loss filtering.
pressureDiff = -0.95 * filter_.tick( delayLine_.lastOut() );
// Calculate pressure difference of reflected and mouthpiece pressures.
pressureDiff = pressureDiff - breathPressure;
// Perform non-linear scattering using pressure difference in reed function.
lastFrame_[0] = delayLine_.tick(breathPressure + pressureDiff * reedTable_.tick(pressureDiff));
// Apply output gain.
lastFrame_[0] *= outputGain_;
return lastFrame_[0];
}
inline StkFrames& Clarinet :: tick( StkFrames& frames, unsigned int channel )
{
unsigned int nChannels = lastFrame_.channels();
#if defined(_STK_DEBUG_)
if ( channel > frames.channels() - nChannels ) {
oStream_ << "Clarinet::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
StkFloat *samples = &frames[channel];
unsigned int j, hop = frames.channels() - nChannels;
if ( nChannels == 1 ) {
for ( unsigned int i=0; i<frames.frames(); i++, samples += hop )
*samples++ = tick();
}
else {
for ( unsigned int i=0; i<frames.frames(); i++, samples += hop ) {
*samples++ = tick();
for ( j=1; j<nChannels; j++ )
*samples++ = lastFrame_[j];
}
}
return frames;
}
} // stk namespace
#endif

138
include/Cubic.h Normal file
View File

@@ -0,0 +1,138 @@
#ifndef STK_CUBIC_H
#define STK_CUBIC_H
#include "Function.h"
#include <cmath>
namespace stk {
/***************************************************/
/*! \class Cubic
\brief STK cubic non-linearity class.
This class implements the cubic non-linearity
that was used in SynthBuilder.
The formula implemented is:
\code
output = gain * (a1 * input + a2 * input^2 + a3 * input^3)
\endcode
followed by a limiter for values outside +-threshold.
Ported to STK by Nick Porcaro, 2007. Updated for inclusion
in STK distribution by Gary Scavone, 2011.
*/
/***************************************************/
class Cubic : public Function
{
public:
//! Default constructor.
Cubic( void ) : a1_(0.5), a2_(0.5), a3_(0.5), gain_(1.0), threshold_(1.0) {};
//! Set the a1 coefficient value.
void setA1( StkFloat a1 ) { a1_ = a1; };
//! Set the a2 coefficient value.
void setA2( StkFloat a2 ) { a2_ = a2; };
//! Set the a3 coefficient value.
void setA3( StkFloat a3 ) { a3_ = a3; };
//! Set the gain value.
void setGain( StkFloat gain ) { gain_ = gain; };
//! Set the threshold value.
void setThreshold( StkFloat threshold ) { threshold_ = threshold; };
//! Input one sample to the function and return one output.
StkFloat tick( StkFloat input );
//! Take a channel of the StkFrames object as inputs to the function and replace with corresponding outputs.
/*!
The StkFrames argument reference is returned. The \c channel
argument must be less than the number of channels in the
StkFrames argument (the first channel is specified by 0).
However, range checking is only performed if _STK_DEBUG_ is
defined during compilation, in which case an out-of-range value
will trigger an StkError exception.
*/
StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
//! Take a channel of the \c iFrames object as inputs to the function and write outputs to the \c oFrames object.
/*!
The \c iFrames object reference is returned. Each channel
argument must be less than the number of channels in the
corresponding StkFrames argument (the first channel is specified
by 0). However, range checking is only performed if _STK_DEBUG_
is defined during compilation, in which case an out-of-range value
will trigger an StkError exception.
*/
StkFrames& tick( StkFrames& iFrames, StkFrames &oFrames, unsigned int iChannel = 0, unsigned int oChannel = 0 );
protected:
StkFloat a1_;
StkFloat a2_;
StkFloat a3_;
StkFloat gain_;
StkFloat threshold_;
};
inline StkFloat Cubic :: tick( StkFloat input )
{
StkFloat inSquared = input * input;
StkFloat inCubed = inSquared * input;
lastFrame_[0] = gain_ * (a1_ * input + a2_ * inSquared + a3_ * inCubed);
// Apply threshold if we are out of range.
if ( fabs( lastFrame_[0] ) > threshold_ ) {
lastFrame_[0] = ( lastFrame_[0] < 0 ? -threshold_ : threshold_ );
}
return lastFrame_[0];
}
inline StkFrames& Cubic :: tick( StkFrames& frames, unsigned int channel )
{
#if defined(_STK_DEBUG_)
if ( channel >= frames.channels() ) {
oStream_ << "Cubic::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
StkFloat *samples = &frames[channel];
unsigned int hop = frames.channels();
for ( unsigned int i=0; i<frames.frames(); i++, samples += hop )
*samples = tick( *samples );
lastFrame_[0] = *(samples-hop);
return frames;
}
inline StkFrames& Cubic :: tick( StkFrames& iFrames, StkFrames& oFrames, unsigned int iChannel, unsigned int oChannel )
{
#if defined(_STK_DEBUG_)
if ( iChannel >= iFrames.channels() || oChannel >= oFrames.channels() ) {
oStream_ << "Cubic::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
StkFloat *iSamples = &iFrames[iChannel];
StkFloat *oSamples = &oFrames[oChannel];
unsigned int iHop = iFrames.channels(), oHop = oFrames.channels();
for ( unsigned int i=0; i<iFrames.frames(); i++, iSamples += iHop, oSamples += oHop )
*oSamples = tick( *iSamples );
lastFrame_[0] = *(oSamples-oHop);
return iFrames;
}
} // stk namespace
#endif

View File

@@ -1,55 +1,62 @@
#ifndef STK_DELAY_H
#define STK_DELAY_H
#include "Filter.h"
namespace stk {
/***************************************************/
/*! \class Delay
\brief STK non-interpolating delay line class.
This protected Filter subclass implements
a non-interpolating digital delay-line.
A fixed maximum length of 4095 and a delay
of zero is set using the default constructor.
Alternatively, the delay and maximum length
can be set during instantiation with an
overloaded constructor.
This class implements a non-interpolating digital delay-line. If
the delay and maximum length are not specified during
instantiation, a fixed maximum length of 4095 and a delay of zero
is set.
A non-interpolating delay line is typically
used in fixed delay-length applications, such
as for reverberation.
A non-interpolating delay line is typically used in fixed
delay-length applications, such as for reverberation.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995--2014.
*/
/***************************************************/
#if !defined(__DELAY_H)
#define __DELAY_H
#include "Filter.h"
class Delay : protected Filter
class Delay : public Filter
{
public:
//! Default constructor creates a delay-line with maximum length of 4095 samples and zero delay.
Delay();
//! Overloaded constructor which specifies the current and maximum delay-line lengths.
Delay(long theDelay, long maxDelay);
//! The default constructor creates a delay-line with maximum length of 4095 samples and zero delay.
/*!
An StkError will be thrown if the delay parameter is less than
zero, the maximum delay parameter is less than one, or the delay
parameter is greater than the maxDelay value.
*/
Delay( unsigned long delay = 0, unsigned long maxDelay = 4095 );
//! Class destructor.
virtual ~Delay();
~Delay();
//! Clears the internal state of the delay line.
void clear();
//! Get the maximum delay-line length.
unsigned long getMaximumDelay( void ) { return inputs_.size() - 1; };
//! Set the maximum delay-line length.
/*!
This method should generally only be used during initial setup
of the delay line. If it is used between calls to the tick()
function, without a call to clear(), a signal discontinuity will
likely occur. If the current maximum length is greater than the
new length, no memory allocation change is made.
*/
void setMaximumDelay( unsigned long delay );
//! Set the delay-line length.
/*!
The valid range for \e theDelay is from 0 to the maximum delay-line length.
The valid range for \e delay is from 0 to the maximum delay-line length.
*/
void setDelay(long theDelay);
void setDelay( unsigned long delay );
//! Return the current delay-line length.
long getDelay(void) const;
//! Calculate and return the signal energy in the delay-line.
MY_FLOAT energy(void) const;
unsigned long getDelay( void ) const { return delay_; };
//! Return the value at \e tapDelay samples from the delay-line input.
/*!
@@ -57,29 +64,125 @@ public:
relative to the last input value (i.e., a tapDelay of zero returns
the last input value).
*/
MY_FLOAT contentsAt(unsigned long tapDelay) const;
StkFloat tapOut( unsigned long tapDelay );
//! Set the \e value at \e tapDelay samples from the delay-line input.
void tapIn( StkFloat value, unsigned long tapDelay );
//! Sum the provided \e value into the delay line at \e tapDelay samples from the input.
/*!
The new value is returned. The tap point is determined modulo
the delay-line length and is relative to the last input value
(i.e., a tapDelay of zero sums into the last input value).
*/
StkFloat addTo( StkFloat value, unsigned long tapDelay );
//! Return the last computed output value.
MY_FLOAT lastOut(void) const;
StkFloat lastOut( void ) const { return lastFrame_[0]; };
//! Return the value which will be output by the next call to tick().
//! Return the value that will be output by the next call to tick().
/*!
This method is valid only for delay settings greater than zero!
*/
virtual MY_FLOAT nextOut(void) const;
StkFloat nextOut( void ) { return inputs_[outPoint_]; };
//! Input one sample to the delay-line and return one output.
virtual MY_FLOAT tick(MY_FLOAT sample);
//! Calculate and return the signal energy in the delay-line.
StkFloat energy( void ) const;
//! Input \e vectorSize samples to the delay-line and return an equal number of outputs in \e vector.
virtual MY_FLOAT *tick(MY_FLOAT *vector, unsigned int vectorSize);
//! Input one sample to the filter and return one output.
StkFloat tick( StkFloat input );
//! Take a channel of the StkFrames object as inputs to the filter and replace with corresponding outputs.
/*!
The StkFrames argument reference is returned. The \c channel
argument must be less than the number of channels in the
StkFrames argument (the first channel is specified by 0).
However, range checking is only performed if _STK_DEBUG_ is
defined during compilation, in which case an out-of-range value
will trigger an StkError exception.
*/
StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
//! Take a channel of the \c iFrames object as inputs to the filter and write outputs to the \c oFrames object.
/*!
The \c iFrames object reference is returned. Each channel
argument must be less than the number of channels in the
corresponding StkFrames argument (the first channel is specified
by 0). However, range checking is only performed if _STK_DEBUG_
is defined during compilation, in which case an out-of-range value
will trigger an StkError exception.
*/
StkFrames& tick( StkFrames& iFrames, StkFrames &oFrames, unsigned int iChannel = 0, unsigned int oChannel = 0 );
protected:
long inPoint;
long outPoint;
long length;
MY_FLOAT delay;
unsigned long inPoint_;
unsigned long outPoint_;
unsigned long delay_;
};
inline StkFloat Delay :: tick( StkFloat input )
{
inputs_[inPoint_++] = input * gain_;
// Check for end condition
if ( inPoint_ == inputs_.size() )
inPoint_ = 0;
// Read out next value
lastFrame_[0] = inputs_[outPoint_++];
if ( outPoint_ == inputs_.size() )
outPoint_ = 0;
return lastFrame_[0];
}
inline StkFrames& Delay :: tick( StkFrames& frames, unsigned int channel )
{
#if defined(_STK_DEBUG_)
if ( channel >= frames.channels() ) {
oStream_ << "Delay::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
StkFloat *samples = &frames[channel];
unsigned int hop = frames.channels();
for ( unsigned int i=0; i<frames.frames(); i++, samples += hop ) {
inputs_[inPoint_++] = *samples * gain_;
if ( inPoint_ == inputs_.size() ) inPoint_ = 0;
*samples = inputs_[outPoint_++];
if ( outPoint_ == inputs_.size() ) outPoint_ = 0;
}
lastFrame_[0] = *(samples-hop);
return frames;
}
inline StkFrames& Delay :: tick( StkFrames& iFrames, StkFrames& oFrames, unsigned int iChannel, unsigned int oChannel )
{
#if defined(_STK_DEBUG_)
if ( iChannel >= iFrames.channels() || oChannel >= oFrames.channels() ) {
oStream_ << "Delay::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
StkFloat *iSamples = &iFrames[iChannel];
StkFloat *oSamples = &oFrames[oChannel];
unsigned int iHop = iFrames.channels(), oHop = oFrames.channels();
for ( unsigned int i=0; i<iFrames.frames(); i++, iSamples += iHop, oSamples += oHop ) {
inputs_[inPoint_++] = *iSamples * gain_;
if ( inPoint_ == inputs_.size() ) inPoint_ = 0;
*oSamples = inputs_[outPoint_++];
if ( outPoint_ == inputs_.size() ) outPoint_ = 0;
}
lastFrame_[0] = *(oSamples-oHop);
return iFrames;
}
} // stk namespace
#endif

View File

@@ -1,73 +1,207 @@
#ifndef STK_DELAYA_H
#define STK_DELAYA_H
#include "Filter.h"
namespace stk {
/***************************************************/
/*! \class DelayA
\brief STK allpass interpolating delay line class.
This Delay subclass implements a fractional-
length digital delay-line using a first-order
allpass filter. A fixed maximum length
of 4095 and a delay of 0.5 is set using the
default constructor. Alternatively, the
delay and maximum length can be set during
instantiation with an overloaded constructor.
This class implements a fractional-length digital delay-line using
a first-order allpass filter. If the delay and maximum length are
not specified during instantiation, a fixed maximum length of 4095
and a delay of 0.5 is set.
An allpass filter has unity magnitude gain but
variable phase delay properties, making it useful
in achieving fractional delays without affecting
a signal's frequency magnitude response. In
order to achieve a maximally flat phase delay
response, the minimum delay possible in this
implementation is limited to a value of 0.5.
An allpass filter has unity magnitude gain but variable phase
delay properties, making it useful in achieving fractional delays
without affecting a signal's frequency magnitude response. In
order to achieve a maximally flat phase delay response, the
minimum delay possible in this implementation is limited to a
value of 0.5.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995--2014.
*/
/***************************************************/
#if !defined(__DelayA_h)
#define __DelayA_h
#include "Delay.h"
class DelayA : public Delay
class DelayA : public Filter
{
public:
//! Default constructor creates a delay-line with maximum length of 4095 samples and zero delay.
DelayA();
//! Overloaded constructor which specifies the current and maximum delay-line lengths.
DelayA(MY_FLOAT theDelay, long maxDelay);
//! Default constructor creates a delay-line with maximum length of 4095 samples and delay = 0.5.
/*!
An StkError will be thrown if the delay parameter is less than
zero, the maximum delay parameter is less than one, or the delay
parameter is greater than the maxDelay value.
*/
DelayA( StkFloat delay = 0.5, unsigned long maxDelay = 4095 );
//! Class destructor.
~DelayA();
//! Clears the internal state of the delay line.
void clear();
//! Clears all internal states of the delay line.
void clear( void );
//! Get the maximum delay-line length.
unsigned long getMaximumDelay( void ) { return inputs_.size() - 1; };
//! Set the maximum delay-line length.
/*!
This method should generally only be used during initial setup
of the delay line. If it is used between calls to the tick()
function, without a call to clear(), a signal discontinuity will
likely occur. If the current maximum length is greater than the
new length, no memory allocation change is made.
*/
void setMaximumDelay( unsigned long delay );
//! Set the delay-line length
/*!
The valid range for \e theDelay is from 0.5 to the maximum delay-line length.
The valid range for \e delay is from 0.5 to the maximum delay-line length.
*/
void setDelay(MY_FLOAT theDelay);
void setDelay( StkFloat delay );
//! Return the current delay-line length.
MY_FLOAT getDelay(void);
StkFloat getDelay( void ) const { return delay_; };
//! Return the value at \e tapDelay samples from the delay-line input.
/*!
The tap point is determined modulo the delay-line length and is
relative to the last input value (i.e., a tapDelay of zero returns
the last input value).
*/
StkFloat tapOut( unsigned long tapDelay );
//! Set the \e value at \e tapDelay samples from the delay-line input.
void tapIn( StkFloat value, unsigned long tapDelay );
//! Return the last computed output value.
StkFloat lastOut( void ) const { return lastFrame_[0]; };
//! Return the value which will be output by the next call to tick().
/*!
This method is valid only for delay settings greater than zero!
*/
MY_FLOAT nextOut(void);
StkFloat nextOut( void );
//! Input one sample to the delay-line and return one output.
MY_FLOAT tick(MY_FLOAT sample);
//! Input one sample to the filter and return one output.
StkFloat tick( StkFloat input );
//! Take a channel of the StkFrames object as inputs to the filter and replace with corresponding outputs.
/*!
The StkFrames argument reference is returned. The \c channel
argument must be less than the number of channels in the
StkFrames argument (the first channel is specified by 0).
However, range checking is only performed if _STK_DEBUG_ is
defined during compilation, in which case an out-of-range value
will trigger an StkError exception.
*/
StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
//! Take a channel of the \c iFrames object as inputs to the filter and write outputs to the \c oFrames object.
/*!
The \c iFrames object reference is returned. Each channel
argument must be less than the number of channels in the
corresponding StkFrames argument (the first channel is specified
by 0). However, range checking is only performed if _STK_DEBUG_
is defined during compilation, in which case an out-of-range value
will trigger an StkError exception.
*/
StkFrames& tick( StkFrames& iFrames, StkFrames &oFrames, unsigned int iChannel = 0, unsigned int oChannel = 0 );
protected:
MY_FLOAT alpha;
MY_FLOAT coeff;
MY_FLOAT apInput;
MY_FLOAT nextOutput;
bool doNextOut;
unsigned long inPoint_;
unsigned long outPoint_;
StkFloat delay_;
StkFloat alpha_;
StkFloat coeff_;
StkFloat apInput_;
StkFloat nextOutput_;
bool doNextOut_;
};
inline StkFloat DelayA :: nextOut( void )
{
if ( doNextOut_ ) {
// Do allpass interpolation delay.
nextOutput_ = -coeff_ * lastFrame_[0];
nextOutput_ += apInput_ + ( coeff_ * inputs_[outPoint_] );
doNextOut_ = false;
}
return nextOutput_;
}
inline StkFloat DelayA :: tick( StkFloat input )
{
inputs_[inPoint_++] = input * gain_;
// Increment input pointer modulo length.
if ( inPoint_ == inputs_.size() )
inPoint_ = 0;
lastFrame_[0] = nextOut();
doNextOut_ = true;
// Save the allpass input and increment modulo length.
apInput_ = inputs_[outPoint_++];
if ( outPoint_ == inputs_.size() )
outPoint_ = 0;
return lastFrame_[0];
}
inline StkFrames& DelayA :: tick( StkFrames& frames, unsigned int channel )
{
#if defined(_STK_DEBUG_)
if ( channel >= frames.channels() ) {
oStream_ << "DelayA::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
StkFloat *samples = &frames[channel];
unsigned int hop = frames.channels();
for ( unsigned int i=0; i<frames.frames(); i++, samples += hop ) {
inputs_[inPoint_++] = *samples * gain_;
if ( inPoint_ == inputs_.size() ) inPoint_ = 0;
*samples = nextOut();
lastFrame_[0] = *samples;
doNextOut_ = true;
apInput_ = inputs_[outPoint_++];
if ( outPoint_ == inputs_.size() ) outPoint_ = 0;
}
return frames;
}
inline StkFrames& DelayA :: tick( StkFrames& iFrames, StkFrames& oFrames, unsigned int iChannel, unsigned int oChannel )
{
#if defined(_STK_DEBUG_)
if ( iChannel >= iFrames.channels() || oChannel >= oFrames.channels() ) {
oStream_ << "DelayA::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
StkFloat *iSamples = &iFrames[iChannel];
StkFloat *oSamples = &oFrames[oChannel];
unsigned int iHop = iFrames.channels(), oHop = oFrames.channels();
for ( unsigned int i=0; i<iFrames.frames(); i++, iSamples += iHop, oSamples += oHop ) {
inputs_[inPoint_++] = *iSamples * gain_;
if ( inPoint_ == inputs_.size() ) inPoint_ = 0;
*oSamples = nextOut();
lastFrame_[0] = *oSamples;
doNextOut_ = true;
apInput_ = inputs_[outPoint_++];
if ( outPoint_ == inputs_.size() ) outPoint_ = 0;
}
return iFrames;
}
} // stk namespace
#endif

View File

@@ -1,69 +1,203 @@
#ifndef STK_DELAYL_H
#define STK_DELAYL_H
#include "Filter.h"
namespace stk {
/***************************************************/
/*! \class DelayL
\brief STK linear interpolating delay line class.
This Delay subclass implements a fractional-
length digital delay-line using first-order
linear interpolation. A fixed maximum length
of 4095 and a delay of zero is set using the
default constructor. Alternatively, the
delay and maximum length can be set during
instantiation with an overloaded constructor.
This class implements a fractional-length digital delay-line using
first-order linear interpolation. If the delay and maximum length
are not specified during instantiation, a fixed maximum length of
4095 and a delay of zero is set.
Linear interpolation is an efficient technique
for achieving fractional delay lengths, though
it does introduce high-frequency signal
attenuation to varying degrees depending on the
fractional delay setting. The use of higher
order Lagrange interpolators can typically
improve (minimize) this attenuation characteristic.
Linear interpolation is an efficient technique for achieving
fractional delay lengths, though it does introduce high-frequency
signal attenuation to varying degrees depending on the fractional
delay setting. The use of higher order Lagrange interpolators can
typically improve (minimize) this attenuation characteristic.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995--2014.
*/
/***************************************************/
#if !defined(__DELAYL_H)
#define __DELAYL_H
#include "Delay.h"
class DelayL : public Delay
class DelayL : public Filter
{
public:
//! Default constructor creates a delay-line with maximum length of 4095 samples and zero delay.
DelayL();
//! Overloaded constructor which specifies the current and maximum delay-line lengths.
DelayL(MY_FLOAT theDelay, long maxDelay);
/*!
An StkError will be thrown if the delay parameter is less than
zero, the maximum delay parameter is less than one, or the delay
parameter is greater than the maxDelay value.
*/
DelayL( StkFloat delay = 0.0, unsigned long maxDelay = 4095 );
//! Class destructor.
~DelayL();
//! Get the maximum delay-line length.
unsigned long getMaximumDelay( void ) { return inputs_.size() - 1; };
//! Set the maximum delay-line length.
/*!
This method should generally only be used during initial setup
of the delay line. If it is used between calls to the tick()
function, without a call to clear(), a signal discontinuity will
likely occur. If the current maximum length is greater than the
new length, no memory allocation change is made.
*/
void setMaximumDelay( unsigned long delay );
//! Set the delay-line length.
/*!
The valid range for \e theDelay is from 0 to the maximum delay-line length.
The valid range for \e delay is from 0 to the maximum delay-line length.
*/
void setDelay(MY_FLOAT theDelay);
void setDelay( StkFloat delay );
//! Return the current delay-line length.
MY_FLOAT getDelay(void) const;
StkFloat getDelay( void ) const { return delay_; };
//! Return the value at \e tapDelay samples from the delay-line input.
/*!
The tap point is determined modulo the delay-line length and is
relative to the last input value (i.e., a tapDelay of zero returns
the last input value).
*/
StkFloat tapOut( unsigned long tapDelay );
//! Set the \e value at \e tapDelay samples from the delay-line input.
void tapIn( StkFloat value, unsigned long tapDelay );
//! Return the last computed output value.
StkFloat lastOut( void ) const { return lastFrame_[0]; };
//! Return the value which will be output by the next call to tick().
/*!
This method is valid only for delay settings greater than zero!
*/
MY_FLOAT nextOut(void);
StkFloat nextOut( void );
//! Input one sample to the delay-line and return one output.
MY_FLOAT tick(MY_FLOAT sample);
//! Input one sample to the filter and return one output.
StkFloat tick( StkFloat input );
protected:
MY_FLOAT alpha;
MY_FLOAT omAlpha;
MY_FLOAT nextOutput;
bool doNextOut;
//! Take a channel of the StkFrames object as inputs to the filter and replace with corresponding outputs.
/*!
The StkFrames argument reference is returned. The \c channel
argument must be less than the number of channels in the
StkFrames argument (the first channel is specified by 0).
However, range checking is only performed if _STK_DEBUG_ is
defined during compilation, in which case an out-of-range value
will trigger an StkError exception.
*/
StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
//! Take a channel of the \c iFrames object as inputs to the filter and write outputs to the \c oFrames object.
/*!
The \c iFrames object reference is returned. Each channel
argument must be less than the number of channels in the
corresponding StkFrames argument (the first channel is specified
by 0). However, range checking is only performed if _STK_DEBUG_
is defined during compilation, in which case an out-of-range value
will trigger an StkError exception.
*/
StkFrames& tick( StkFrames& iFrames, StkFrames &oFrames, unsigned int iChannel = 0, unsigned int oChannel = 0 );
protected:
unsigned long inPoint_;
unsigned long outPoint_;
StkFloat delay_;
StkFloat alpha_;
StkFloat omAlpha_;
StkFloat nextOutput_;
bool doNextOut_;
};
inline StkFloat DelayL :: nextOut( void )
{
if ( doNextOut_ ) {
// First 1/2 of interpolation
nextOutput_ = inputs_[outPoint_] * omAlpha_;
// Second 1/2 of interpolation
if (outPoint_+1 < inputs_.size())
nextOutput_ += inputs_[outPoint_+1] * alpha_;
else
nextOutput_ += inputs_[0] * alpha_;
doNextOut_ = false;
}
return nextOutput_;
}
inline StkFloat DelayL :: tick( StkFloat input )
{
inputs_[inPoint_++] = input * gain_;
// Increment input pointer modulo length.
if ( inPoint_ == inputs_.size() )
inPoint_ = 0;
lastFrame_[0] = nextOut();
doNextOut_ = true;
// Increment output pointer modulo length.
if ( ++outPoint_ == inputs_.size() )
outPoint_ = 0;
return lastFrame_[0];
}
inline StkFrames& DelayL :: tick( StkFrames& frames, unsigned int channel )
{
#if defined(_STK_DEBUG_)
if ( channel >= frames.channels() ) {
oStream_ << "DelayL::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
StkFloat *samples = &frames[channel];
unsigned int hop = frames.channels();
for ( unsigned int i=0; i<frames.frames(); i++, samples += hop ) {
inputs_[inPoint_++] = *samples * gain_;
if ( inPoint_ == inputs_.size() ) inPoint_ = 0;
*samples = nextOut();
doNextOut_ = true;
if ( ++outPoint_ == inputs_.size() ) outPoint_ = 0;
}
lastFrame_[0] = *(samples-hop);
return frames;
}
inline StkFrames& DelayL :: tick( StkFrames& iFrames, StkFrames& oFrames, unsigned int iChannel, unsigned int oChannel )
{
#if defined(_STK_DEBUG_)
if ( iChannel >= iFrames.channels() || oChannel >= oFrames.channels() ) {
oStream_ << "DelayL::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
StkFloat *iSamples = &iFrames[iChannel];
StkFloat *oSamples = &oFrames[oChannel];
unsigned int iHop = iFrames.channels(), oHop = oFrames.channels();
for ( unsigned int i=0; i<iFrames.frames(); i++, iSamples += iHop, oSamples += oHop ) {
inputs_[inPoint_++] = *iSamples * gain_;
if ( inPoint_ == inputs_.size() ) inPoint_ = 0;
*oSamples = nextOut();
doNextOut_ = true;
if ( ++outPoint_ == inputs_.size() ) outPoint_ = 0;
}
lastFrame_[0] = *(oSamples-oHop);
return iFrames;
}
} // stk namespace
#endif

View File

@@ -1,3 +1,12 @@
#ifndef STK_DRUMMER_H
#define STK_DRUMMER_H
#include "Instrmnt.h"
#include "FileWvIn.h"
#include "OnePole.h"
namespace stk {
/***************************************************/
/*! \class Drummer
\brief STK drum sample player class.
@@ -11,49 +20,111 @@
of simultaneous voices) via a #define in the
Drummer.h.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995--2014.
*/
/***************************************************/
#if !defined(__DRUMMER_H)
#define __DRUMMER_H
#include "Instrmnt.h"
#include "WvIn.h"
#include "OnePole.h"
#define DRUM_NUMWAVES 11
#define DRUM_POLYPHONY 4
const int DRUM_NUMWAVES = 11;
const int DRUM_POLYPHONY = 4;
class Drummer : public Instrmnt
{
public:
//! Class constructor.
Drummer();
/*!
An StkError will be thrown if the rawwave path is incorrectly set.
*/
Drummer( void );
//! Class destructor.
~Drummer();
~Drummer( void );
//! Start a note with the given drum type and amplitude.
/*!
Use general MIDI drum instrument numbers, converted to
frequency values as if MIDI note numbers, to select a
particular instrument.
frequency values as if MIDI note numbers, to select a particular
instrument. An StkError will be thrown if the rawwave path is
incorrectly set.
*/
void noteOn(MY_FLOAT instrument, MY_FLOAT amplitude);
void noteOn( StkFloat instrument, StkFloat amplitude );
//! Stop a note with the given amplitude (speed of decay).
void noteOff(MY_FLOAT amplitude);
void noteOff( StkFloat amplitude );
//! Compute one output sample.
MY_FLOAT tick();
//! Compute and return one output sample.
StkFloat tick( unsigned int channel = 0 );
protected:
WvIn *waves[DRUM_POLYPHONY];
OnePole *filters[DRUM_POLYPHONY];
int sounding[DRUM_POLYPHONY];
int nSounding;
//! Fill a channel of the StkFrames object with computed outputs.
/*!
The \c channel argument must be less than the number of
channels in the StkFrames argument (the first channel is specified
by 0). However, range checking is only performed if _STK_DEBUG_
is defined during compilation, in which case an out-of-range value
will trigger an StkError exception.
*/
StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
protected:
FileWvIn waves_[DRUM_POLYPHONY];
OnePole filters_[DRUM_POLYPHONY];
std::vector<int> soundOrder_;
std::vector<int> soundNumber_;
int nSounding_;
};
inline StkFloat Drummer :: tick( unsigned int )
{
lastFrame_[0] = 0.0;
if ( nSounding_ == 0 ) return lastFrame_[0];
for ( int i=0; i<DRUM_POLYPHONY; i++ ) {
if ( soundOrder_[i] >= 0 ) {
if ( waves_[i].isFinished() ) {
// Re-order the list.
for ( int j=0; j<DRUM_POLYPHONY; j++ ) {
if ( soundOrder_[j] > soundOrder_[i] )
soundOrder_[j] -= 1;
}
soundOrder_[i] = -1;
nSounding_--;
}
else
lastFrame_[0] += filters_[i].tick( waves_[i].tick() );
}
}
return lastFrame_[0];
}
inline StkFrames& Drummer :: tick( StkFrames& frames, unsigned int channel )
{
unsigned int nChannels = lastFrame_.channels();
#if defined(_STK_DEBUG_)
if ( channel > frames.channels() - nChannels ) {
oStream_ << "Drummer::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
StkFloat *samples = &frames[channel];
unsigned int j, hop = frames.channels() - nChannels;
if ( nChannels == 1 ) {
for ( unsigned int i=0; i<frames.frames(); i++, samples += hop )
*samples++ = tick();
}
else {
for ( unsigned int i=0; i<frames.frames(); i++, samples += hop ) {
*samples++ = tick();
for ( j=1; j<nChannels; j++ )
*samples++ = lastFrame_[j];
}
}
return frames;
}
} // stk namespace
#endif

View File

@@ -1,53 +1,120 @@
#ifndef STK_ECHO_H
#define STK_ECHO_H
#include "Effect.h"
#include "Delay.h"
namespace stk {
/***************************************************/
/*! \class Echo
\brief STK echo effect class.
This class implements a echo effect.
This class implements an echo effect.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995--2014.
*/
/***************************************************/
#if !defined(__ECHO_H)
#define __ECHO_H
#include "Stk.h"
#include "Delay.h"
class Echo : public Stk
class Echo : public Effect
{
public:
//! Class constructor, taking the longest desired delay length.
Echo(MY_FLOAT longestDelay);
//! Class destructor.
~Echo();
//! Class constructor, taking the longest desired delay length (one second default value).
/*!
The default delay value is set to 1/2 the maximum delay length.
*/
Echo( unsigned long maximumDelay = (unsigned long) Stk::sampleRate() );
//! Reset and clear all internal state.
void clear();
//! Set the maximum delay line length in samples.
void setMaximumDelay( unsigned long delay );
//! Set the delay line length in samples.
void setDelay(MY_FLOAT delay);
void setDelay( unsigned long delay );
//! Set the mixture of input and processed levels in the output (0.0 = input only, 1.0 = processed only).
void setEffectMix(MY_FLOAT mix);
//! Return the last computed output value.
StkFloat lastOut( void ) const { return lastFrame_[0]; };
//! Return the last output value.
MY_FLOAT lastOut() const;
//! Input one sample to the effect and return one output.
StkFloat tick( StkFloat input );
//! Compute one output sample.
MY_FLOAT tick(MY_FLOAT input);
//! Take a channel of the StkFrames object as inputs to the effect and replace with corresponding outputs.
/*!
The StkFrames argument reference is returned. The \c channel
argument must be less than the number of channels in the
StkFrames argument (the first channel is specified by 0).
However, range checking is only performed if _STK_DEBUG_ is
defined during compilation, in which case an out-of-range value
will trigger an StkError exception.
*/
StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
//! Input \e vectorSize samples to the filter and return an equal number of outputs in \e vector.
MY_FLOAT *tick(MY_FLOAT *vector, unsigned int vectorSize);
//! Take a channel of the \c iFrames object as inputs to the effect and write outputs to the \c oFrames object.
/*!
The \c iFrames object reference is returned. Each channel
argument must be less than the number of channels in the
corresponding StkFrames argument (the first channel is specified
by 0). However, range checking is only performed if _STK_DEBUG_
is defined during compilation, in which case an out-of-range value
will trigger an StkError exception.
*/
StkFrames& tick( StkFrames& iFrames, StkFrames &oFrames, unsigned int iChannel = 0, unsigned int oChannel = 0 );
protected:
Delay *delayLine;
long length;
MY_FLOAT lastOutput;
MY_FLOAT effectMix;
protected:
Delay delayLine_;
unsigned long length_;
};
inline StkFloat Echo :: tick( StkFloat input )
{
lastFrame_[0] = effectMix_ * ( delayLine_.tick( input ) - input ) + input;
return lastFrame_[0];
}
inline StkFrames& Echo :: tick( StkFrames& frames, unsigned int channel )
{
#if defined(_STK_DEBUG_)
if ( channel >= frames.channels() ) {
oStream_ << "Echo::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
StkFloat *samples = &frames[channel];
unsigned int hop = frames.channels();
for ( unsigned int i=0; i<frames.frames(); i++, samples += hop ) {
*samples = effectMix_ * ( delayLine_.tick( *samples ) - *samples ) + *samples;
}
lastFrame_[0] = *(samples-hop);
return frames;
}
inline StkFrames& Echo :: tick( StkFrames& iFrames, StkFrames& oFrames, unsigned int iChannel, unsigned int oChannel )
{
#if defined(_STK_DEBUG_)
if ( iChannel >= iFrames.channels() || oChannel >= oFrames.channels() ) {
oStream_ << "Echo::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
StkFloat *iSamples = &iFrames[iChannel];
StkFloat *oSamples = &oFrames[oChannel];
unsigned int iHop = iFrames.channels(), oHop = oFrames.channels();
for ( unsigned int i=0; i<iFrames.frames(); i++, iSamples += iHop, oSamples += oHop ) {
*oSamples = effectMix_ * ( delayLine_.tick( *iSamples ) - *iSamples ) + *iSamples;
}
lastFrame_[0] = *(oSamples-oHop);
return iFrames;
}
} // stk namespace
#endif

79
include/Effect.h Normal file
View File

@@ -0,0 +1,79 @@
#ifndef STK_EFFECT_H
#define STK_EFFECT_H
#include "Stk.h"
#include <cmath>
namespace stk {
/***************************************************/
/*! \class Effect
\brief STK abstract effects parent class.
This class provides common functionality for STK effects
subclasses. It is general enough to support both monophonic and
polyphonic input/output classes.
by Perry R. Cook and Gary P. Scavone, 1995--2014.
*/
/***************************************************/
class Effect : public Stk
{
public:
//! Class constructor.
Effect( void ) { lastFrame_.resize( 1, 1, 0.0 ); };
//! Return the number of output channels for the class.
unsigned int channelsOut( void ) const { return lastFrame_.channels(); };
//! Return an StkFrames reference to the last output sample frame.
const StkFrames& lastFrame( void ) const { return lastFrame_; };
//! Reset and clear all internal state.
virtual void clear() = 0;
//! Set the mixture of input and "effected" levels in the output (0.0 = input only, 1.0 = effect only).
virtual void setEffectMix( StkFloat mix );
protected:
// Returns true if argument value is prime.
bool isPrime( unsigned int number );
StkFrames lastFrame_;
StkFloat effectMix_;
};
inline void Effect :: setEffectMix( StkFloat mix )
{
if ( mix < 0.0 ) {
oStream_ << "Effect::setEffectMix: mix parameter is less than zero ... setting to zero!";
handleError( StkError::WARNING );
effectMix_ = 0.0;
}
else if ( mix > 1.0 ) {
oStream_ << "Effect::setEffectMix: mix parameter is greater than 1.0 ... setting to one!";
handleError( StkError::WARNING );
effectMix_ = 1.0;
}
else
effectMix_ = mix;
}
inline bool Effect :: isPrime( unsigned int number )
{
if ( number == 2 ) return true;
if ( number & 1 ) {
for ( int i=3; i<(int)sqrt((double)number)+1; i+=2 )
if ( (number % i) == 0 ) return false;
return true; // prime
}
else return false; // even
}
} // stk namespace
#endif

View File

@@ -1,68 +1,130 @@
#ifndef STK_ENVELOPE_H
#define STK_ENVELOPE_H
#include "Generator.h"
namespace stk {
/***************************************************/
/*! \class Envelope
\brief STK envelope base class.
\brief STK linear line envelope class.
This class implements a simple envelope
generator which is capable of ramping to
a target value by a specified \e rate.
It also responds to simple \e keyOn and
\e keyOff messages, ramping to 1.0 on
keyOn and to 0.0 on keyOff.
This class implements a simple linear line envelope generator
which is capable of ramping to an arbitrary target value by a
specified \e rate. It also responds to simple \e keyOn and \e
keyOff messages, ramping to 1.0 on keyOn and to 0.0 on keyOff.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995--2014.
*/
/***************************************************/
#if !defined(__ENVELOPE_H)
#define __ENVELOPE_H
#include "Stk.h"
class Envelope : public Stk
class Envelope : public Generator
{
public:
//! Default constructor.
Envelope(void);
Envelope( void );
//! Class destructor.
virtual ~Envelope(void);
~Envelope( void );
//! Assignment operator.
Envelope& operator= ( const Envelope& e );
//! Set target = 1.
virtual void keyOn(void);
void keyOn( void ) { this->setTarget( 1.0 ); };
//! Set target = 0.
virtual void keyOff(void);
void keyOff( void ) { this->setTarget( 0.0 ); };
//! Set the \e rate.
void setRate(MY_FLOAT aRate);
/*!
The \e rate must be positive (though a value of 0.0 is allowed).
*/
void setRate( StkFloat rate );
//! Set the \e rate based on a time duration.
void setTime(MY_FLOAT aTime);
//! Set the \e rate based on a positive time duration (seconds).
/*!
The \e rate is calculated such that the envelope will ramp from
a value of 0.0 to 1.0 in the specified time duration.
*/
void setTime( StkFloat time );
//! Set the target value.
virtual void setTarget(MY_FLOAT aTarget);
void setTarget( StkFloat target );
//! Set current and target values to \e aValue.
virtual void setValue(MY_FLOAT aValue);
//! Set current and target values to \e value.
void setValue( StkFloat value );
//! Return the current envelope \e state (0 = at target, 1 otherwise).
virtual int getState(void) const;
//! Return one envelope output value.
virtual MY_FLOAT tick(void);
//! Return \e vectorSize envelope outputs in \e vector.
virtual MY_FLOAT *tick(MY_FLOAT *vector, unsigned int vectorSize);
int getState( void ) const { return state_; };
//! Return the last computed output value.
MY_FLOAT lastOut(void) const;
StkFloat lastOut( void ) const { return lastFrame_[0]; };
//! Compute and return one output sample.
StkFloat tick( void );
//! Fill a channel of the StkFrames object with computed outputs.
/*!
The \c channel argument must be less than the number of
channels in the StkFrames argument (the first channel is specified
by 0). However, range checking is only performed if _STK_DEBUG_
is defined during compilation, in which case an out-of-range value
will trigger an StkError exception.
*/
StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
protected:
MY_FLOAT value;
MY_FLOAT target;
MY_FLOAT rate;
int state;
void sampleRateChanged( StkFloat newRate, StkFloat oldRate );
StkFloat value_;
StkFloat target_;
StkFloat rate_;
int state_;
};
inline StkFloat Envelope :: tick( void )
{
if ( state_ ) {
if ( target_ > value_ ) {
value_ += rate_;
if ( value_ >= target_ ) {
value_ = target_;
state_ = 0;
}
}
else {
value_ -= rate_;
if ( value_ <= target_ ) {
value_ = target_;
state_ = 0;
}
}
lastFrame_[0] = value_;
}
return value_;
}
inline StkFrames& Envelope :: tick( StkFrames& frames, unsigned int channel )
{
#if defined(_STK_DEBUG_)
if ( channel >= frames.channels() ) {
oStream_ << "Envelope::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
StkFloat *samples = &frames[channel];
unsigned int hop = frames.channels();
for ( unsigned int i=0; i<frames.frames(); i++, samples += hop )
*samples = tick();
return frames;
}
} // stk namespace
#endif

View File

@@ -1,3 +1,14 @@
#ifndef STK_FM_H
#define STK_FM_H
#include "Instrmnt.h"
#include "ADSR.h"
#include "FileLoop.h"
#include "SineWave.h"
#include "TwoZero.h"
namespace stk {
/***************************************************/
/*! \class FM
\brief STK abstract FM synthesis base class.
@@ -19,85 +30,90 @@
type who should worry about this (making
money) worry away.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995--2014.
*/
/***************************************************/
#if !defined(__FM_H)
#define __FM_H
#include "Instrmnt.h"
#include "ADSR.h"
#include "WaveLoop.h"
#include "TwoZero.h"
class FM : public Instrmnt
{
public:
//! Class constructor, taking the number of wave/envelope operators to control.
FM( int operators = 4 );
/*!
An StkError will be thrown if the rawwave path is incorrectly set.
*/
FM( unsigned int operators = 4 );
//! Class destructor.
virtual ~FM();
//! Reset and clear all wave and envelope states.
void clear();
virtual ~FM( void );
//! Load the rawwave filenames in waves.
void loadWaves(const char **filenames);
void loadWaves( const char **filenames );
//! Set instrument parameters for a particular frequency.
virtual void setFrequency(MY_FLOAT frequency);
virtual void setFrequency( StkFloat frequency );
//! Set the frequency ratio for the specified wave.
void setRatio(int waveIndex, MY_FLOAT ratio);
void setRatio( unsigned int waveIndex, StkFloat ratio );
//! Set the gain for the specified wave.
void setGain(int waveIndex, MY_FLOAT gain);
void setGain( unsigned int waveIndex, StkFloat gain );
//! Set the modulation speed in Hz.
void setModulationSpeed(MY_FLOAT mSpeed);
void setModulationSpeed( StkFloat mSpeed ) { vibrato_.setFrequency( mSpeed ); };
//! Set the modulation depth.
void setModulationDepth(MY_FLOAT mDepth);
void setModulationDepth( StkFloat mDepth ) { modDepth_ = mDepth; };
//! Set the value of control1.
void setControl1(MY_FLOAT cVal);
void setControl1( StkFloat cVal ) { control1_ = cVal * 2.0; };
//! Set the value of control1.
void setControl2(MY_FLOAT cVal);
void setControl2( StkFloat cVal ) { control2_ = cVal * 2.0; };
//! Start envelopes toward "on" targets.
void keyOn();
void keyOn( void );
//! Start envelopes toward "off" targets.
void keyOff();
void keyOff( void );
//! Stop a note with the given amplitude (speed of decay).
void noteOff(MY_FLOAT amplitude);
//! Pure virtual function ... must be defined in subclasses.
virtual MY_FLOAT tick() = 0;
void noteOff( StkFloat amplitude );
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
virtual void controlChange(int number, MY_FLOAT value);
virtual void controlChange( int number, StkFloat value );
protected:
ADSR **adsr;
WaveLoop **waves;
WaveLoop *vibrato;
TwoZero *twozero;
int nOperators;
MY_FLOAT baseFrequency;
MY_FLOAT *ratios;
MY_FLOAT *gains;
MY_FLOAT modDepth;
MY_FLOAT control1;
MY_FLOAT control2;
MY_FLOAT __FM_gains[100];
MY_FLOAT __FM_susLevels[16];
MY_FLOAT __FM_attTimes[32];
//! Compute and return one output sample.
virtual StkFloat tick( unsigned int ) = 0;
//! Fill a channel of the StkFrames object with computed outputs.
/*!
The \c channel argument must be less than the number of
channels in the StkFrames argument (the first channel is specified
by 0). However, range checking is only performed if _STK_DEBUG_
is defined during compilation, in which case an out-of-range value
will trigger an StkError exception.
*/
virtual StkFrames& tick( StkFrames& frames, unsigned int channel = 0 ) = 0;
protected:
std::vector<ADSR *> adsr_;
std::vector<FileLoop *> waves_;
SineWave vibrato_;
TwoZero twozero_;
unsigned int nOperators_;
StkFloat baseFrequency_;
std::vector<StkFloat> ratios_;
std::vector<StkFloat> gains_;
StkFloat modDepth_;
StkFloat control1_;
StkFloat control2_;
StkFloat fmGains_[100];
StkFloat fmSusLevels_[16];
StkFloat fmAttTimes_[32];
};
} // stk namespace
#endif

View File

@@ -1,3 +1,10 @@
#ifndef STK_FMVOICES_H
#define STK_FMVOICES_H
#include "FM.h"
namespace stk {
/***************************************************/
/*! \class FMVoices
\brief STK singing FM synthesis instrument.
@@ -26,40 +33,103 @@
type who should worry about this (making
money) worry away.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995--2014.
*/
/***************************************************/
#if !defined(__FMVOICES_H)
#define __FMVOICES_H
#include "FM.h"
class FMVoices : public FM
{
public:
//! Class constructor.
FMVoices();
/*!
An StkError will be thrown if the rawwave path is incorrectly set.
*/
FMVoices( void );
//! Class destructor.
~FMVoices();
~FMVoices( void );
//! Set instrument parameters for a particular frequency.
virtual void setFrequency(MY_FLOAT frequency);
void setFrequency( StkFloat frequency );
//! Start a note with the given frequency and amplitude.
void noteOn(MY_FLOAT frequency, MY_FLOAT amplitude);
//! Compute one output sample.
MY_FLOAT tick();
void noteOn( StkFloat frequency, StkFloat amplitude );
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
virtual void controlChange(int number, MY_FLOAT value);
void controlChange( int number, StkFloat value );
//! Compute and return one output sample.
StkFloat tick( unsigned int channel = 0 );
//! Fill a channel of the StkFrames object with computed outputs.
/*!
The \c channel argument must be less than the number of
channels in the StkFrames argument (the first channel is specified
by 0). However, range checking is only performed if _STK_DEBUG_
is defined during compilation, in which case an out-of-range value
will trigger an StkError exception.
*/
StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
protected:
int currentVowel;
MY_FLOAT tilt[3];
MY_FLOAT mods[3];
int currentVowel_;
StkFloat tilt_[3];
StkFloat mods_[3];
};
inline StkFloat FMVoices :: tick( unsigned int )
{
StkFloat temp, temp2;
temp = gains_[3] * adsr_[3]->tick() * waves_[3]->tick();
temp2 = vibrato_.tick() * modDepth_ * 0.1;
waves_[0]->setFrequency(baseFrequency_ * (1.0 + temp2) * ratios_[0]);
waves_[1]->setFrequency(baseFrequency_ * (1.0 + temp2) * ratios_[1]);
waves_[2]->setFrequency(baseFrequency_ * (1.0 + temp2) * ratios_[2]);
waves_[3]->setFrequency(baseFrequency_ * (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();
lastFrame_[0] = temp * 0.33;
return lastFrame_[0];
}
inline StkFrames& FMVoices :: tick( StkFrames& frames, unsigned int channel )
{
unsigned int nChannels = lastFrame_.channels();
#if defined(_STK_DEBUG_)
if ( channel > frames.channels() - nChannels ) {
oStream_ << "FMVoices::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
StkFloat *samples = &frames[channel];
unsigned int j, hop = frames.channels() - nChannels;
if ( nChannels == 1 ) {
for ( unsigned int i=0; i<frames.frames(); i++, samples += hop )
*samples++ = tick();
}
else {
for ( unsigned int i=0; i<frames.frames(); i++, samples += hop ) {
*samples++ = tick();
for ( j=1; j<nChannels; j++ )
*samples++ = lastFrame_[j];
}
}
return frames;
}
} // stk namespace
#endif

164
include/FileLoop.h Normal file
View File

@@ -0,0 +1,164 @@
#ifndef STK_FILELOOP_H
#define STK_FILELOOP_H
#include "FileWvIn.h"
namespace stk {
/***************************************************/
/*! \class FileLoop
\brief STK file looping / oscillator class.
This class provides audio file looping functionality. Any audio
file that can be loaded by FileRead can be looped using this
class.
FileLoop supports multi-channel data. It is important to
distinguish the tick() method that computes a single frame (and
returns only the specified sample of a multi-channel frame) from
the overloaded one that takes an StkFrames object for
multi-channel and/or multi-frame data.
by Perry R. Cook and Gary P. Scavone, 1995--2014.
*/
/***************************************************/
class FileLoop : protected FileWvIn
{
public:
//! Default constructor.
FileLoop( unsigned long chunkThreshold = 1000000, unsigned long chunkSize = 1024 );
//! Class constructor that opens a specified file.
FileLoop( std::string fileName, bool raw = false, bool doNormalize = true,
unsigned long chunkThreshold = 1000000, unsigned long chunkSize = 1024 );
//! Class destructor.
~FileLoop( void );
//! Open the specified file and load its data.
/*!
Data from a previously opened file will be overwritten by this
function. An StkError will be thrown if the file is not found,
its format is unknown, or a read error occurs. If the file data
is to be loaded incrementally from disk and normalization is
specified, a scaling will be applied with respect to fixed-point
limits. If the data format is floating-point, no scaling is
performed.
*/
void openFile( std::string fileName, bool raw = false, bool doNormalize = true );
//! Close a file if one is open.
void closeFile( void ) { FileWvIn::closeFile(); };
//! Clear outputs and reset time (file) pointer to zero.
void reset( void ) { FileWvIn::reset(); };
//! Return the number of audio channels in the data or stream.
unsigned int channelsOut( void ) const { return data_.channels(); };
//! Normalize data to a maximum of +-1.0.
/*!
This function has no effect when data is incrementally loaded
from disk.
*/
void normalize( void ) { FileWvIn::normalize( 1.0 ); };
//! Normalize data to a maximum of \e +-peak.
/*!
This function has no effect when data is incrementally loaded
from disk.
*/
void normalize( StkFloat peak ) { FileWvIn::normalize( peak ); };
//! Return the file size in sample frames.
unsigned long getSize( void ) const { return data_.frames(); };
//! Return the input file sample rate in Hz (not the data read rate).
/*!
WAV, SND, and AIF formatted files specify a sample rate in
their headers. STK RAW files have a sample rate of 22050 Hz
by definition. MAT-files are assumed to have a rate of 44100 Hz.
*/
StkFloat getFileRate( void ) const { return data_.dataRate(); };
//! Set the data read rate in samples. The rate can be negative.
/*!
If the rate value is negative, the data is read in reverse order.
*/
void setRate( StkFloat rate );
//! Set the data interpolation rate based on a looping frequency.
/*!
This function determines the interpolation rate based on the file
size and the current Stk::sampleRate. The \e frequency value
corresponds to file cycles per second. The frequency can be
negative, in which case the loop is read in reverse order.
*/
void setFrequency( StkFloat frequency ) { this->setRate( file_.fileSize() * frequency / Stk::sampleRate() ); };
//! Increment the read pointer by \e time samples, modulo file size.
void addTime( StkFloat time );
//! Increment current read pointer by \e angle, relative to a looping frequency.
/*!
This function increments the read pointer based on the file
size and the current Stk::sampleRate. The \e anAngle value
is a multiple of file size.
*/
void addPhase( StkFloat angle );
//! Add a phase offset to the current read pointer.
/*!
This function determines a time offset based on the file
size and the current Stk::sampleRate. The \e angle value
is a multiple of file size.
*/
void addPhaseOffset( StkFloat angle );
//! Return the specified channel value of the last computed frame.
/*!
For multi-channel files, use the lastFrame() function to get
all values from the last computed frame. If no file data is
loaded, the returned value is 0.0. The \c channel argument must
be less than the number of channels in the file data (the first
channel is specified by 0). However, range checking is only
performed if _STK_DEBUG_ is defined during compilation, in which
case an out-of-range value will trigger an StkError exception.
*/
StkFloat lastOut( unsigned int channel = 0 ) { return FileWvIn::lastOut( channel ); };
//! Compute a sample frame and return the specified \c channel value.
/*!
For multi-channel files, use the lastFrame() function to get
all values from the computed frame. If no file data is loaded,
the returned value is 0.0. The \c channel argument must be less
than the number of channels in the file data (the first channel is
specified by 0). However, range checking is only performed if
_STK_DEBUG_ is defined during compilation, in which case an
out-of-range value will trigger an StkError exception.
*/
StkFloat tick( unsigned int channel = 0 );
//! Fill the StkFrames argument with computed frames and return the same reference.
/*!
The number of channels in the StkFrames argument should equal
the number of channels in the file data. However, this is only
checked if _STK_DEBUG_ is defined during compilation, in which
case an incompatibility will trigger an StkError exception. If no
file data is loaded, the function does nothing (a warning will be
issued if _STK_DEBUG_ is defined during compilation and
Stk::showWarnings() has been set to \e true).
*/
StkFrames& tick( StkFrames& frames );
protected:
StkFrames firstFrame_;
StkFloat phaseOffset_;
};
} // stk namespace
#endif

141
include/FileRead.h Normal file
View File

@@ -0,0 +1,141 @@
#ifndef STK_FILEREAD_H
#define STK_FILEREAD_H
#include "Stk.h"
namespace stk {
/***************************************************/
/*! \class FileRead
\brief STK audio file input class.
This class provides input support for various
audio file formats. Multi-channel (>2)
soundfiles are supported. The file data is
returned via an external StkFrames object
passed to the read() function. This class
does not store its own copy of the file data,
rather the data is read directly from disk.
FileRead currently supports uncompressed WAV,
AIFF/AIFC, SND (AU), MAT-file (Matlab), and
STK RAW file formats. Signed integer (8-,
16-, 24-, and 32-bit) and floating-point (32- and
64-bit) data types are supported. Compressed
data types are not supported.
STK RAW files have no header and are assumed to
contain a monophonic stream of 16-bit signed
integers in big-endian byte order at a sample
rate of 22050 Hz. MAT-file data should be saved
in an array with each data channel filling a
matrix row. The sample rate for MAT-files should
be specified in a variable named "fs". If no
such variable is found, the sample rate is
assumed to be 44100 Hz.
by Perry R. Cook and Gary P. Scavone, 1995--2014.
*/
/***************************************************/
class FileRead : public Stk
{
public:
//! Default constructor.
FileRead( void );
//! Overloaded constructor that opens a file during instantiation.
/*!
An StkError will be thrown if the file is not found or its
format is unknown or unsupported. The optional arguments allow a
headerless file type to be supported. If \c typeRaw is false (the
default), the subsequent parameters are ignored.
*/
FileRead( std::string fileName, bool typeRaw = false, unsigned int nChannels = 1,
StkFormat format = STK_SINT16, StkFloat rate = 22050.0 );
//! Class destructor.
~FileRead( void );
//! Open the specified file and determine its formatting.
/*!
An StkError will be thrown if the file is not found or its
format is unknown or unsupported. The optional arguments allow a
headerless file type to be supported. If \c typeRaw is false (the
default), the subsequent parameters are ignored.
*/
void open( std::string fileName, bool typeRaw = false, unsigned int nChannels = 1,
StkFormat format = STK_SINT16, StkFloat rate = 22050.0 );
//! If a file is open, close it.
void close( void );
//! Returns \e true if a file is currently open.
bool isOpen( void );
//! Return the file size in sample frames.
unsigned long fileSize( void ) const { return fileSize_; };
//! Return the number of audio channels in the file.
unsigned int channels( void ) const { return channels_; };
//! Return the data format of the file.
StkFormat format( void ) const { return dataType_; };
//! Return the file sample rate in Hz.
/*!
WAV, SND, and AIF formatted files specify a sample rate in
their headers. By definition, STK RAW files have a sample rate of
22050 Hz. MAT-files are assumed to have a rate of 44100 Hz.
*/
StkFloat fileRate( void ) const { return fileRate_; };
//! Read sample frames from the file into an StkFrames object.
/*!
The number of sample frames to read will be determined from the
number of frames of the StkFrames argument. If this size is
larger than the available data in the file (given the file size
and starting frame index), the extra frames will be unaffected
(the StkFrames object will not be resized). Optional parameters
are provided to specify the starting sample frame within the file
(default = 0) and whether to normalize the data with respect to
fixed-point limits (default = true). An StkError will be thrown
if a file error occurs or if the number of channels in the
StkFrames argument is not equal to that in the file.
*/
void read( StkFrames& buffer, unsigned long startFrame = 0, bool doNormalize = true );
protected:
// Get STK RAW file information.
bool getRawInfo( const char *fileName, unsigned int nChannels,
StkFormat format, StkFloat rate );
// Get WAV file header information.
bool getWavInfo( const char *fileName );
// Get SND (AU) file header information.
bool getSndInfo( const char *fileName );
// Get AIFF file header information.
bool getAifInfo( const char *fileName );
// Get MAT-file header information.
bool getMatInfo( const char *fileName );
// Helper function for MAT-file parsing.
bool findNextMatArray( SINT32 *chunkSize, SINT32 *rows, SINT32 *columns, SINT32 *nametype );
FILE *fd_;
bool byteswap_;
bool wavFile_;
unsigned long fileSize_;
unsigned long dataOffset_;
unsigned int channels_;
StkFormat dataType_;
StkFloat fileRate_;
};
} // stk namespace
#endif

116
include/FileWrite.h Normal file
View File

@@ -0,0 +1,116 @@
#ifndef STK_FILEWRITE_H
#define STK_FILEWRITE_H
#include "Stk.h"
namespace stk {
/***************************************************/
/*! \class FileWrite
\brief STK audio file output class.
This class provides output support for various
audio file formats.
FileWrite writes samples to an audio file. It supports
multi-channel data.
FileWrite currently supports uncompressed WAV, AIFF, AIFC, SND
(AU), MAT-file (Matlab), and STK RAW file formats. Signed integer
(8-, 16-, 24-, and 32-bit) and floating- point (32- and 64-bit)
data types are supported. STK RAW files use 16-bit integers by
definition. MAT-files will always be written as 64-bit floats.
If a data type specification does not match the specified file
type, the data type will automatically be modified. Compressed
data types are not supported.
by Perry R. Cook and Gary P. Scavone, 1995--2014.
*/
/***************************************************/
class FileWrite : public Stk
{
public:
typedef unsigned long FILE_TYPE;
static const FILE_TYPE FILE_RAW; /*!< STK RAW file type. */
static const FILE_TYPE FILE_WAV; /*!< WAV file type. */
static const FILE_TYPE FILE_SND; /*!< SND (AU) file type. */
static const FILE_TYPE FILE_AIF; /*!< AIFF file type. */
static const FILE_TYPE FILE_MAT; /*!< Matlab MAT-file type. */
//! Default constructor.
FileWrite( void );
//! Overloaded constructor used to specify a file name, type, and data format with this object.
/*!
An StkError is thrown for invalid argument values or if an error occurs when initializing the output file.
*/
FileWrite( std::string fileName, unsigned int nChannels = 1, FILE_TYPE type = FILE_WAV, Stk::StkFormat format = STK_SINT16 );
//! Class destructor.
virtual ~FileWrite();
//! Create a file of the specified type and name and output samples to it in the given data format.
/*!
An StkError is thrown for invalid argument values or if an error occurs when initializing the output file.
*/
void open( std::string fileName, unsigned int nChannels = 1,
FileWrite::FILE_TYPE type = FILE_WAV, Stk::StkFormat format = STK_SINT16 );
//! If a file is open, write out samples in the queue and then close it.
void close( void );
//! Returns \e true if a file is currently open.
bool isOpen( void );
//! Write sample frames from the StkFrames object to the file.
/*!
An StkError will be thrown if the number of channels in the
StkFrames argument does not agree with the number of channels
specified when opening the file.
*/
void write( StkFrames& buffer );
protected:
// Write STK RAW file header.
bool setRawFile( std::string fileName );
// Write WAV file header.
bool setWavFile( std::string fileName );
// Close WAV file, updating the header.
void closeWavFile( void );
// Write SND (AU) file header.
bool setSndFile( std::string fileName );
// Close SND file, updating the header.
void closeSndFile( void );
// Write AIFF file header.
bool setAifFile( std::string fileName );
// Close AIFF file, updating the header.
void closeAifFile( void );
// Write MAT-file header.
bool setMatFile( std::string fileName );
// Close MAT-file, updating the header.
void closeMatFile( void );
FILE *fd_;
FILE_TYPE fileType_;
StkFormat dataType_;
unsigned int channels_;
unsigned long frameCounter_;
bool byteswap_;
};
} // stk namespace
#endif

196
include/FileWvIn.h Normal file
View File

@@ -0,0 +1,196 @@
#ifndef STK_FILEWVIN_H
#define STK_FILEWVIN_H
#include "WvIn.h"
#include "FileRead.h"
namespace stk {
/***************************************************/
/*! \class FileWvIn
\brief STK audio file input class.
This class inherits from WvIn. It provides a "tick-level"
interface to the FileRead class. It also provides variable-rate
playback functionality. Audio file support is provided by the
FileRead class. Linear interpolation is used for fractional read
rates.
FileWvIn supports multi-channel data. It is important to
distinguish the tick() method that computes a single frame (and
returns only the specified sample of a multi-channel frame) from
the overloaded one that takes an StkFrames object for
multi-channel and/or multi-frame data.
FileWvIn will either load the entire content of an audio file into
local memory or incrementally read file data from disk in chunks.
This behavior is controlled by the optional constructor arguments
\e chunkThreshold and \e chunkSize. File sizes greater than \e
chunkThreshold (in sample frames) will be read incrementally in
chunks of \e chunkSize each (also in sample frames).
When the file end is reached, subsequent calls to the tick()
functions return zeros and isFinished() returns \e true.
See the FileRead class for a description of the supported audio
file formats.
by Perry R. Cook and Gary P. Scavone, 1995--2014.
*/
/***************************************************/
class FileWvIn : public WvIn
{
public:
//! Default constructor.
FileWvIn( unsigned long chunkThreshold = 1000000, unsigned long chunkSize = 1024 );
//! Overloaded constructor for file input.
/*!
An StkError will be thrown if the file is not found, its format is
unknown, or a read error occurs.
*/
FileWvIn( std::string fileName, bool raw = false, bool doNormalize = true,
unsigned long chunkThreshold = 1000000, unsigned long chunkSize = 1024 );
//! Class destructor.
~FileWvIn( void );
//! Open the specified file and load its data.
/*!
Data from a previously opened file will be overwritten by this
function. An StkError will be thrown if the file is not found,
its format is unknown, or a read error occurs. If the file data
is to be loaded incrementally from disk and normalization is
specified, a scaling will be applied with respect to fixed-point
limits. If the data format is floating-point, no scaling is
performed.
*/
virtual void openFile( std::string fileName, bool raw = false, bool doNormalize = true );
//! Close a file if one is open.
virtual void closeFile( void );
//! Clear outputs and reset time (file) pointer to zero.
virtual void reset( void );
//! Normalize data to a maximum of +-1.0.
/*!
This function has no effect when data is incrementally loaded
from disk.
*/
virtual void normalize( void );
//! Normalize data to a maximum of \e +-peak.
/*!
This function has no effect when data is incrementally loaded
from disk.
*/
virtual void normalize( StkFloat peak );
//! Return the file size in sample frames.
virtual unsigned long getSize( void ) const { return file_.fileSize(); };
//! Return the input file sample rate in Hz (not the data read rate).
/*!
WAV, SND, and AIF formatted files specify a sample rate in
their headers. STK RAW files have a sample rate of 22050 Hz
by definition. MAT-files are assumed to have a rate of 44100 Hz.
*/
virtual StkFloat getFileRate( void ) const { return data_.dataRate(); };
//! Query whether a file is open.
bool isOpen( void ) { return file_.isOpen(); };
//! Query whether reading is complete.
bool isFinished( void ) const { return finished_; };
//! Set the data read rate in samples. The rate can be negative.
/*!
If the rate value is negative, the data is read in reverse order.
*/
virtual void setRate( StkFloat rate );
//! Increment the read pointer by \e time samples.
/*!
Note that this function will not modify the interpolation flag status.
*/
virtual void addTime( StkFloat time );
//! Turn linear interpolation on/off.
/*!
Interpolation is automatically off when the read rate is
an integer value. If interpolation is turned off for a
fractional rate, the time index is truncated to an integer
value.
*/
void setInterpolate( bool doInterpolate ) { interpolate_ = doInterpolate; };
//! Return the specified channel value of the last computed frame.
/*!
If no file is loaded, the returned value is 0.0. The \c
channel argument must be less than the number of output channels,
which can be determined with the channelsOut() function (the first
channel is specified by 0). However, range checking is only
performed if _STK_DEBUG_ is defined during compilation, in which
case an out-of-range value will trigger an StkError exception. \sa
lastFrame()
*/
StkFloat lastOut( unsigned int channel = 0 );
//! Compute a sample frame and return the specified \c channel value.
/*!
For multi-channel files, use the lastFrame() function to get
all values from the computed frame. If no file data is loaded,
the returned value is 0.0. The \c channel argument must be less
than the number of channels in the file data (the first channel is
specified by 0). However, range checking is only performed if
_STK_DEBUG_ is defined during compilation, in which case an
out-of-range value will trigger an StkError exception.
*/
virtual StkFloat tick( unsigned int channel = 0 );
//! Fill the StkFrames argument with computed frames and return the same reference.
/*!
The number of channels in the StkFrames argument must equal
the number of channels in the file data. However, this is only
checked if _STK_DEBUG_ is defined during compilation, in which
case an incompatibility will trigger an StkError exception. If no
file data is loaded, the function does nothing (a warning will be
issued if _STK_DEBUG_ is defined during compilation).
*/
virtual StkFrames& tick( StkFrames& frames );
protected:
void sampleRateChanged( StkFloat newRate, StkFloat oldRate );
FileRead file_;
bool finished_;
bool interpolate_;
bool normalizing_;
bool chunking_;
StkFloat time_;
StkFloat rate_;
unsigned long chunkThreshold_;
unsigned long chunkSize_;
long chunkPointer_;
};
inline StkFloat FileWvIn :: lastOut( unsigned int channel )
{
#if defined(_STK_DEBUG_)
if ( channel >= data_.channels() ) {
oStream_ << "FileWvIn::lastOut(): channel argument and soundfile data are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
if ( finished_ ) return 0.0;
return lastFrame_[channel];
}
} // stk namespace
#endif

102
include/FileWvOut.h Normal file
View File

@@ -0,0 +1,102 @@
#ifndef STK_FILEWVOUT_H
#define STK_FILEWVOUT_H
#include "WvOut.h"
#include "FileWrite.h"
namespace stk {
/***************************************************/
/*! \class FileWvOut
\brief STK audio file output class.
This class inherits from WvOut. It provides a "tick-level"
interface to the FileWrite class.
FileWvOut writes samples to an audio file and supports
multi-channel data. It is important to distinguish the tick()
method that outputs a single sample to all channels in a sample
frame from the overloaded one that takes a reference to an
StkFrames object for multi-channel and/or multi-frame data.
See the FileWrite class for a description of the supported audio
file formats.
Currently, FileWvOut is non-interpolating and the output rate is
always Stk::sampleRate().
by Perry R. Cook and Gary P. Scavone, 1995--2014.
*/
/***************************************************/
class FileWvOut : public WvOut
{
public:
//! Default constructor with optional output buffer size argument.
/*!
The output buffer size defines the number of frames that are
accumulated between writes to disk.
*/
FileWvOut( unsigned int bufferFrames = 1024 );
//! Overloaded constructor used to specify a file name, type, and data format with this object.
/*!
An StkError is thrown for invalid argument values or if an error occurs when initializing the output file.
*/
FileWvOut( std::string fileName,
unsigned int nChannels = 1,
FileWrite::FILE_TYPE type = FileWrite::FILE_WAV,
Stk::StkFormat format = STK_SINT16,
unsigned int bufferFrames = 1024 );
//! Class destructor.
virtual ~FileWvOut();
//! Open a new file with the specified parameters.
/*!
If a file was previously open, it will be closed. An StkError
will be thrown if any of the specified arguments are invalid or a
file error occurs during opening.
*/
void openFile( std::string fileName,
unsigned int nChannels,
FileWrite::FILE_TYPE type,
Stk::StkFormat format );
//! Close a file if one is open.
/*!
Any data remaining in the internal buffer will be written to
the file before closing.
*/
void closeFile( void );
//! Output a single sample to all channels in a sample frame.
/*!
An StkError is thrown if an output error occurs.
*/
void tick( const StkFloat sample );
//! Output the StkFrames data.
/*!
An StkError will be thrown if an output error occurs. An
StkError will also be thrown if _STK_DEBUG_ is defined during
compilation and there is an incompatability between the number of
channels in the FileWvOut object and that in the StkFrames object.
*/
void tick( const StkFrames& frames );
protected:
void incrementFrame( void );
FileWrite file_;
unsigned int bufferFrames_;
unsigned int bufferIndex_;
unsigned int iData_;
};
} // stk namespace
#endif

View File

@@ -1,112 +1,124 @@
/***************************************************/
/*! \class Filter
\brief STK filter class.
This class implements a generic structure which
can be used to create a wide range of filters.
It can function independently or be subclassed
to provide more specific controls based on a
particular filter type.
In particular, this class implements the standard
difference equation:
a[0]*y[n] = b[0]*x[n] + ... + b[nb]*x[n-nb] -
a[1]*y[n-1] - ... - a[na]*y[n-na]
If a[0] is not equal to 1, the filter coeffcients
are normalized by a[0].
The \e gain parameter is applied at the filter
input and does not affect the coefficient values.
The default gain value is 1.0. This structure
results in one extra multiply per computed sample,
but allows easy control of the overall filter gain.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
*/
/***************************************************/
#if !defined(__FILTER_H)
#define __FILTER_H
#ifndef STK_FILTER_H
#define STK_FILTER_H
#include "Stk.h"
#include <vector>
#include <cmath>
namespace stk {
/***************************************************/
/*! \class Filter
\brief STK abstract filter class.
This class provides limited common functionality for STK digital
filter subclasses. It is general enough to support both
monophonic and polyphonic input/output classes.
by Perry R. Cook and Gary P. Scavone, 1995--2014.
*/
/***************************************************/
class Filter : public Stk
{
public:
//! Default constructor creates a zero-order pass-through "filter".
Filter(void);
//! Class constructor.
Filter( void ) { gain_ = 1.0; channelsIn_ = 1; lastFrame_.resize( 1, 1, 0.0 ); };
//! Overloaded constructor which takes filter coefficients.
/*!
An StkError can be thrown if either \e nb or \e na is less than
one, or if the a[0] coefficient is equal to zero.
*/
Filter(int nb, MY_FLOAT *bCoefficients, int na, MY_FLOAT *aCoefficients);
//! Return the number of input channels for the class.
unsigned int channelsIn( void ) const { return channelsIn_; };
//! Class destructor.
virtual ~Filter(void);
//! Return the number of output channels for the class.
unsigned int channelsOut( void ) const { return lastFrame_.channels(); };
//! Clears all internal states of the filter.
void clear(void);
//! Set filter coefficients.
/*!
An StkError can be thrown if either \e nb or \e na is less than
one, or if the a[0] coefficient is equal to zero. If a[0] is not
equal to 1, the filter coeffcients are normalized by a[0].
*/
void setCoefficients(int nb, MY_FLOAT *bCoefficients, int na, MY_FLOAT *aCoefficients);
//! Set numerator coefficients.
/*!
An StkError can be thrown if \e nb is less than one. Any
previously set denominator coefficients are left unaffected.
Note that the default constructor sets the single denominator
coefficient a[0] to 1.0.
*/
void setNumerator(int nb, MY_FLOAT *bCoefficients);
//! Set denominator coefficients.
/*!
An StkError can be thrown if \e na is less than one or if the
a[0] coefficient is equal to zero. Previously set numerator
coefficients are unaffected unless a[0] is not equal to 1, in
which case all coeffcients are normalized by a[0]. Note that the
default constructor sets the single numerator coefficient b[0]
to 1.0.
*/
void setDenominator(int na, MY_FLOAT *aCoefficients);
virtual void clear( void );
//! Set the filter gain.
/*!
The gain is applied at the filter input and does not affect the
coefficient values. The default gain value is 1.0.
*/
virtual void setGain(MY_FLOAT theGain);
void setGain( StkFloat gain ) { gain_ = gain; };
//! Return the current filter gain.
virtual MY_FLOAT getGain(void) const;
StkFloat getGain( void ) const { return gain_; };
//! Return the last computed output value.
virtual MY_FLOAT lastOut(void) const;
//! Return the filter phase delay at the specified frequency.
/*!
Note that the phase delay calculation accounts for the filter
gain. The frequency value should be greater than 0.0 and less
than or equal to one-half the sample rate.
*/
StkFloat phaseDelay( StkFloat frequency );
//! Input one sample to the filter and return one output.
virtual MY_FLOAT tick(MY_FLOAT sample);
//! Return an StkFrames reference to the last output sample frame.
const StkFrames& lastFrame( void ) const { return lastFrame_; };
//! Input \e vectorSize samples to the filter and return an equal number of outputs in \e vector.
virtual MY_FLOAT *tick(MY_FLOAT *vector, unsigned int vectorSize);
//! Take a channel of the StkFrames object as inputs to the filter and replace with corresponding outputs.
/*!
The StkFrames argument reference is returned. The \c channel
argument must be less than the number of channels in the
StkFrames argument (the first channel is specified by 0).
However, range checking is only performed if _STK_DEBUG_ is
defined during compilation, in which case an out-of-range value
will trigger an StkError exception.
*/
virtual StkFrames& tick( StkFrames& frames, unsigned int channel = 0 ) = 0;
protected:
MY_FLOAT gain;
int nB;
int nA;
MY_FLOAT *b;
MY_FLOAT *a;
MY_FLOAT *outputs;
MY_FLOAT *inputs;
StkFloat gain_;
unsigned int channelsIn_;
StkFrames lastFrame_;
std::vector<StkFloat> b_;
std::vector<StkFloat> a_;
StkFrames outputs_;
StkFrames inputs_;
};
inline void Filter :: clear( void )
{
unsigned int i;
for ( i=0; i<inputs_.size(); i++ )
inputs_[i] = 0.0;
for ( i=0; i<outputs_.size(); i++ )
outputs_[i] = 0.0;
for ( i=0; i<lastFrame_.size(); i++ )
lastFrame_[i] = 0.0;
}
inline StkFloat Filter :: phaseDelay( StkFloat frequency )
{
if ( frequency <= 0.0 || frequency > 0.5 * Stk::sampleRate() ) {
oStream_ << "Filter::phaseDelay: argument (" << frequency << ") is out of range!";
handleError( StkError::WARNING ); return 0.0;
}
StkFloat omegaT = 2 * PI * frequency / Stk::sampleRate();
StkFloat real = 0.0, imag = 0.0;
for ( unsigned int i=0; i<b_.size(); i++ ) {
real += b_[i] * std::cos( i * omegaT );
imag -= b_[i] * std::sin( i * omegaT );
}
real *= gain_;
imag *= gain_;
StkFloat phase = atan2( imag, real );
real = 0.0, imag = 0.0;
for ( unsigned int i=0; i<a_.size(); i++ ) {
real += a_[i] * std::cos( i * omegaT );
imag -= a_[i] * std::sin( i * omegaT );
}
phase -= std::atan2( imag, real );
phase = std::fmod( -phase, 2 * PI );
return phase / omegaT;
}
} // stk namespace
#endif

155
include/Fir.h Normal file
View File

@@ -0,0 +1,155 @@
#ifndef STK_FIR_H
#define STK_FIR_H
#include "Filter.h"
namespace stk {
/***************************************************/
/*! \class Fir
\brief STK general finite impulse response filter class.
This class provides a generic digital filter structure that can be
used to implement FIR filters. For filters with feedback terms,
the Iir class should be used.
In particular, this class implements the standard difference
equation:
y[n] = b[0]*x[n] + ... + b[nb]*x[n-nb]
The \e gain parameter is applied at the filter input and does not
affect the coefficient values. The default gain value is 1.0.
This structure results in one extra multiply per computed sample,
but allows easy control of the overall filter gain.
by Perry R. Cook and Gary P. Scavone, 1995--2014.
*/
/***************************************************/
class Fir : public Filter
{
public:
//! Default constructor creates a zero-order pass-through "filter".
Fir( void );
//! Overloaded constructor which takes filter coefficients.
/*!
An StkError can be thrown if the coefficient vector size is
zero.
*/
Fir( std::vector<StkFloat> &coefficients );
//! Class destructor.
~Fir( void );
//! Set filter coefficients.
/*!
An StkError can be thrown if the coefficient vector size is
zero. The internal state of the filter is not cleared unless the
\e clearState flag is \c true.
*/
void setCoefficients( std::vector<StkFloat> &coefficients, bool clearState = false );
//! Return the last computed output value.
StkFloat lastOut( void ) const { return lastFrame_[0]; };
//! Input one sample to the filter and return one output.
StkFloat tick( StkFloat input );
//! Take a channel of the StkFrames object as inputs to the filter and replace with corresponding outputs.
/*!
The StkFrames argument reference is returned. The \c channel
argument must be less than the number of channels in the
StkFrames argument (the first channel is specified by 0).
However, range checking is only performed if _STK_DEBUG_ is
defined during compilation, in which case an out-of-range value
will trigger an StkError exception.
*/
StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
//! Take a channel of the \c iFrames object as inputs to the filter and write outputs to the \c oFrames object.
/*!
The \c iFrames object reference is returned. Each channel
argument must be less than the number of channels in the
corresponding StkFrames argument (the first channel is specified
by 0). However, range checking is only performed if _STK_DEBUG_
is defined during compilation, in which case an out-of-range value
will trigger an StkError exception.
*/
StkFrames& tick( StkFrames& iFrames, StkFrames &oFrames, unsigned int iChannel = 0, unsigned int oChannel = 0 );
protected:
};
inline StkFloat Fir :: tick( StkFloat input )
{
lastFrame_[0] = 0.0;
inputs_[0] = gain_ * input;
for ( unsigned int i=(unsigned int)(b_.size())-1; i>0; i-- ) {
lastFrame_[0] += b_[i] * inputs_[i];
inputs_[i] = inputs_[i-1];
}
lastFrame_[0] += b_[0] * inputs_[0];
return lastFrame_[0];
}
inline StkFrames& Fir :: tick( StkFrames& frames, unsigned int channel )
{
#if defined(_STK_DEBUG_)
if ( channel >= frames.channels() ) {
oStream_ << "Fir::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
StkFloat *samples = &frames[channel];
unsigned int i, hop = frames.channels();
for ( unsigned int j=0; j<frames.frames(); j++, samples += hop ) {
inputs_[0] = gain_ * *samples;
*samples = 0.0;
for ( i=(unsigned int)b_.size()-1; i>0; i-- ) {
*samples += b_[i] * inputs_[i];
inputs_[i] = inputs_[i-1];
}
*samples += b_[0] * inputs_[0];
}
lastFrame_[0] = *(samples-hop);
return frames;
}
inline StkFrames& Fir :: tick( StkFrames& iFrames, StkFrames& oFrames, unsigned int iChannel, unsigned int oChannel )
{
#if defined(_STK_DEBUG_)
if ( iChannel >= iFrames.channels() || oChannel >= oFrames.channels() ) {
oStream_ << "Fir::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
StkFloat *iSamples = &iFrames[iChannel];
StkFloat *oSamples = &oFrames[oChannel];
unsigned int i, iHop = iFrames.channels(), oHop = oFrames.channels();
for ( unsigned int j=0; j<iFrames.frames(); j++, iSamples += iHop, oSamples += oHop ) {
inputs_[0] = gain_ * *iSamples;
*oSamples = 0.0;
for ( i=(unsigned int)b_.size()-1; i>0; i-- ) {
*oSamples += b_[i] * inputs_[i];
inputs_[i] = inputs_[i-1];
}
*oSamples += b_[0] * inputs_[0];
}
lastFrame_[0] = *(oSamples-oHop);
return iFrames;
}
} // stk namespace
#endif

View File

@@ -1,3 +1,17 @@
#ifndef STK_FLUTE_H
#define STK_FLUTE_H
#include "Instrmnt.h"
#include "JetTable.h"
#include "DelayL.h"
#include "OnePole.h"
#include "PoleZero.h"
#include "Noise.h"
#include "ADSR.h"
#include "SineWave.h"
namespace stk {
/***************************************************/
/*! \class Flute
\brief STK flute physical model class.
@@ -18,83 +32,135 @@
- Vibrato Gain = 1
- Breath Pressure = 128
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995--2014.
*/
/***************************************************/
#if !defined(__FLUTE_H)
#define __FLUTE_H
#include "Instrmnt.h"
#include "JetTabl.h"
#include "DelayL.h"
#include "OnePole.h"
#include "PoleZero.h"
#include "Noise.h"
#include "ADSR.h"
#include "WaveLoop.h"
class Flute : public Instrmnt
{
public:
//! Class constructor, taking the lowest desired playing frequency.
Flute(MY_FLOAT lowestFrequency);
/*!
An StkError will be thrown if the rawwave path is incorrectly set.
*/
Flute( StkFloat lowestFrequency );
//! Class destructor.
~Flute();
~Flute( void );
//! Reset and clear all internal state.
void clear();
void clear( void );
//! Set instrument parameters for a particular frequency.
void setFrequency(MY_FLOAT frequency);
void setFrequency( StkFloat frequency );
//! Set the reflection coefficient for the jet delay (-1.0 - 1.0).
void setJetReflection(MY_FLOAT coefficient);
void setJetReflection( StkFloat coefficient ) { jetReflection_ = coefficient; };
//! Set the reflection coefficient for the air column delay (-1.0 - 1.0).
void setEndReflection(MY_FLOAT coefficient);
void setEndReflection( StkFloat coefficient ) { endReflection_ = coefficient; };
//! Set the length of the jet delay in terms of a ratio of jet delay to air column delay lengths.
void setJetDelay(MY_FLOAT aRatio);
void setJetDelay( StkFloat aRatio );
//! Apply breath velocity to instrument with given amplitude and rate of increase.
void startBlowing(MY_FLOAT amplitude, MY_FLOAT rate);
void startBlowing( StkFloat amplitude, StkFloat rate );
//! Decrease breath velocity with given rate of decrease.
void stopBlowing(MY_FLOAT rate);
void stopBlowing( StkFloat rate );
//! Start a note with the given frequency and amplitude.
void noteOn(MY_FLOAT frequency, MY_FLOAT amplitude);
void noteOn( StkFloat frequency, StkFloat amplitude );
//! Stop a note with the given amplitude (speed of decay).
void noteOff(MY_FLOAT amplitude);
//! Compute one output sample.
MY_FLOAT tick();
void noteOff( StkFloat amplitude );
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
void controlChange(int number, MY_FLOAT value);
void controlChange( int number, StkFloat value );
protected:
DelayL *jetDelay;
DelayL *boreDelay;
JetTabl *jetTable;
OnePole *filter;
PoleZero *dcBlock;
Noise *noise;
ADSR *adsr;
WaveLoop *vibrato;
long length;
MY_FLOAT lastFrequency;
MY_FLOAT maxPressure;
MY_FLOAT jetReflection;
MY_FLOAT endReflection;
MY_FLOAT noiseGain;
MY_FLOAT vibratoGain;
MY_FLOAT outputGain;
MY_FLOAT jetRatio;
//! Compute and return one output sample.
StkFloat tick( unsigned int channel = 0 );
//! Fill a channel of the StkFrames object with computed outputs.
/*!
The \c channel argument must be less than the number of
channels in the StkFrames argument (the first channel is specified
by 0). However, range checking is only performed if _STK_DEBUG_
is defined during compilation, in which case an out-of-range value
will trigger an StkError exception.
*/
StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
protected:
DelayL jetDelay_;
DelayL boreDelay_;
JetTable jetTable_;
OnePole filter_;
PoleZero dcBlock_;
Noise noise_;
ADSR adsr_;
SineWave vibrato_;
StkFloat lastFrequency_;
StkFloat maxPressure_;
StkFloat jetReflection_;
StkFloat endReflection_;
StkFloat noiseGain_;
StkFloat vibratoGain_;
StkFloat outputGain_;
StkFloat jetRatio_;
};
inline StkFloat Flute :: tick( unsigned int )
{
StkFloat pressureDiff;
StkFloat breathPressure;
// Calculate the breath pressure (envelope + noise + vibrato)
breathPressure = maxPressure_ * adsr_.tick();
breathPressure += breathPressure * ( noiseGain_ * noise_.tick() + vibratoGain_ * vibrato_.tick() );
StkFloat temp = -filter_.tick( boreDelay_.lastOut() );
temp = dcBlock_.tick( temp ); // Block DC on reflection.
pressureDiff = breathPressure - (jetReflection_ * temp);
pressureDiff = jetDelay_.tick( pressureDiff );
pressureDiff = jetTable_.tick( pressureDiff ) + (endReflection_ * temp);
lastFrame_[0] = (StkFloat) 0.3 * boreDelay_.tick( pressureDiff );
lastFrame_[0] *= outputGain_;
return lastFrame_[0];
}
inline StkFrames& Flute :: tick( StkFrames& frames, unsigned int channel )
{
unsigned int nChannels = lastFrame_.channels();
#if defined(_STK_DEBUG_)
if ( channel > frames.channels() - nChannels ) {
oStream_ << "Flute::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
StkFloat *samples = &frames[channel];
unsigned int j, hop = frames.channels() - nChannels;
if ( nChannels == 1 ) {
for ( unsigned int i=0; i<frames.frames(); i++, samples += hop )
*samples++ = tick();
}
else {
for ( unsigned int i=0; i<frames.frames(); i++, samples += hop ) {
*samples++ = tick();
for ( j=1; j<nChannels; j++ )
*samples++ = lastFrame_[j];
}
}
return frames;
}
} // stk namespace
#endif

View File

@@ -1,51 +1,56 @@
#ifndef STK_FORMSWEP_H
#define STK_FORMSWEP_H
#include "Filter.h"
namespace stk {
/***************************************************/
/*! \class FormSwep
\brief STK sweepable formant filter class.
This public BiQuad filter subclass implements
a formant (resonance) which can be "swept"
over time from one frequency setting to another.
It provides methods for controlling the sweep
rate and target frequency.
This class implements a formant (resonance) which can be "swept"
over time from one frequency setting to another. It provides
methods for controlling the sweep rate and target frequency.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995--2014.
*/
/***************************************************/
#if !defined(__FORMSWEP_H)
#define __FORMSWEP_H
#include "BiQuad.h"
class FormSwep : public BiQuad
class FormSwep : public Filter
{
public:
//! Default constructor creates a second-order pass-through filter.
FormSwep();
FormSwep( void );
//! Class destructor.
~FormSwep();
//! A function to enable/disable the automatic updating of class data when the STK sample rate changes.
void ignoreSampleRateChange( bool ignore = true ) { ignoreSampleRateChange_ = ignore; };
//! Sets the filter coefficients for a resonance at \e frequency (in Hz).
/*!
This method determines the filter coefficients corresponding to
two complex-conjugate poles with the given \e frequency (in Hz)
and \e radius from the z-plane origin. The filter zeros are
placed at z = 1, z = -1, and the coefficients are then normalized to
produce a constant unity gain (independent of the filter \e gain
parameter). The resulting filter frequency response has a
placed at z = 1, z = -1, and the coefficients are then normalized
to produce a constant unity gain (independent of the filter \e
gain parameter). The resulting filter frequency response has a
resonance at the given \e frequency. The closer the poles are to
the unit-circle (\e radius close to one), the narrower the
resulting resonance width.
resulting resonance width. An unstable filter will result for \e
radius >= 1.0. The \e frequency value should be between zero and
half the sample rate.
*/
void setResonance(MY_FLOAT aFrequency, MY_FLOAT aRadius);
void setResonance( StkFloat frequency, StkFloat radius );
//! Set both the current and target resonance parameters.
void setStates(MY_FLOAT aFrequency, MY_FLOAT aRadius, MY_FLOAT aGain = 1.0);
void setStates( StkFloat frequency, StkFloat radius, StkFloat gain = 1.0 );
//! Set target resonance parameters.
void setTargets(MY_FLOAT aFrequency, MY_FLOAT aRadius, MY_FLOAT aGain = 1.0);
void setTargets( StkFloat frequency, StkFloat radius, StkFloat gain = 1.0 );
//! Set the sweep rate (between 0.0 - 1.0).
/*!
@@ -56,7 +61,7 @@ class FormSwep : public BiQuad
target values. A sweep rate of 0.0 will produce no
change in resonance parameters.
*/
void setSweepRate(MY_FLOAT aRate);
void setSweepRate( StkFloat rate );
//! Set the sweep rate in terms of a time value in seconds.
/*!
@@ -64,30 +69,122 @@ class FormSwep : public BiQuad
given time for the formant parameters to reach
their target values.
*/
void setSweepTime(MY_FLOAT aTime);
void setSweepTime( StkFloat time );
//! Input one sample to the filter and return one output.
MY_FLOAT tick(MY_FLOAT sample);
//! Return the last computed output value.
StkFloat lastOut( void ) const { return lastFrame_[0]; };
//! Input \e vectorSize samples to the filter and return an equal number of outputs in \e vector.
MY_FLOAT *tick(MY_FLOAT *vector, unsigned int vectorSize);
//! Input one sample to the filter and return a reference to one output.
StkFloat tick( StkFloat input );
protected:
bool dirty;
MY_FLOAT frequency;
MY_FLOAT radius;
MY_FLOAT startFrequency;
MY_FLOAT startRadius;
MY_FLOAT startGain;
MY_FLOAT targetFrequency;
MY_FLOAT targetRadius;
MY_FLOAT targetGain;
MY_FLOAT deltaFrequency;
MY_FLOAT deltaRadius;
MY_FLOAT deltaGain;
MY_FLOAT sweepState;
MY_FLOAT sweepRate;
//! Take a channel of the StkFrames object as inputs to the filter and replace with corresponding outputs.
/*!
The StkFrames argument reference is returned. The \c channel
argument must be less than the number of channels in the
StkFrames argument (the first channel is specified by 0).
However, range checking is only performed if _STK_DEBUG_ is
defined during compilation, in which case an out-of-range value
will trigger an StkError exception.
*/
StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
//! Take a channel of the \c iFrames object as inputs to the filter and write outputs to the \c oFrames object.
/*!
The \c iFrames object reference is returned. Each channel
argument must be less than the number of channels in the
corresponding StkFrames argument (the first channel is specified
by 0). However, range checking is only performed if _STK_DEBUG_
is defined during compilation, in which case an out-of-range value
will trigger an StkError exception.
*/
StkFrames& tick( StkFrames& iFrames, StkFrames &oFrames, unsigned int iChannel = 0, unsigned int oChannel = 0 );
protected:
virtual void sampleRateChanged( StkFloat newRate, StkFloat oldRate );
bool dirty_;
StkFloat frequency_;
StkFloat radius_;
StkFloat startFrequency_;
StkFloat startRadius_;
StkFloat startGain_;
StkFloat targetFrequency_;
StkFloat targetRadius_;
StkFloat targetGain_;
StkFloat deltaFrequency_;
StkFloat deltaRadius_;
StkFloat deltaGain_;
StkFloat sweepState_;
StkFloat sweepRate_;
};
inline StkFloat FormSwep :: tick( StkFloat input )
{
if ( dirty_ ) {
sweepState_ += sweepRate_;
if ( sweepState_ >= 1.0 ) {
sweepState_ = 1.0;
dirty_ = false;
radius_ = targetRadius_;
frequency_ = targetFrequency_;
gain_ = targetGain_;
}
else {
radius_ = startRadius_ + (deltaRadius_ * sweepState_);
frequency_ = startFrequency_ + (deltaFrequency_ * sweepState_);
gain_ = startGain_ + (deltaGain_ * sweepState_);
}
this->setResonance( frequency_, radius_ );
}
inputs_[0] = gain_ * input;
lastFrame_[0] = b_[0] * inputs_[0] + b_[1] * inputs_[1] + b_[2] * inputs_[2];
lastFrame_[0] -= a_[2] * outputs_[2] + a_[1] * outputs_[1];
inputs_[2] = inputs_[1];
inputs_[1] = inputs_[0];
outputs_[2] = outputs_[1];
outputs_[1] = lastFrame_[0];
return lastFrame_[0];
}
inline StkFrames& FormSwep :: tick( StkFrames& frames, unsigned int channel )
{
#if defined(_STK_DEBUG_)
if ( channel >= frames.channels() ) {
oStream_ << "FormSwep::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
StkFloat *samples = &frames[channel];
unsigned int hop = frames.channels();
for ( unsigned int i=0; i<frames.frames(); i++, samples += hop )
*samples = tick( *samples );
return frames;
}
inline StkFrames& FormSwep :: tick( StkFrames& iFrames, StkFrames& oFrames, unsigned int iChannel, unsigned int oChannel )
{
#if defined(_STK_DEBUG_)
if ( iChannel >= iFrames.channels() || oChannel >= oFrames.channels() ) {
oStream_ << "FormSwep::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
StkFloat *iSamples = &iFrames[iChannel];
StkFloat *oSamples = &oFrames[oChannel];
unsigned int iHop = iFrames.channels(), oHop = oFrames.channels();
for ( unsigned int i=0; i<iFrames.frames(); i++, iSamples += iHop, oSamples += oHop )
*oSamples = tick( *iSamples );
return iFrames;
}
} // stk namespace
#endif

251
include/FreeVerb.h Normal file
View File

@@ -0,0 +1,251 @@
#ifndef STK_FREEVERB_H
#define STK_FREEVERB_H
#include "Effect.h"
#include "Delay.h"
#include "OnePole.h"
namespace stk {
/***********************************************************************/
/*! \class FreeVerb
\brief Jezar at Dreampoint's FreeVerb, implemented in STK.
Freeverb is a free and open-source Schroeder reverberator
originally implemented in C++. The parameters of the reverberation
model are exceptionally well tuned. FreeVerb uses 8
lowpass-feedback-comb-filters in parallel, followed by 4 Schroeder
allpass filters in series. The input signal can be either mono or
stereo, and the output signal is stereo. The delay lengths are
optimized for a sample rate of 44100 Hz.
Ported to STK by Gregory Burlet, 2012.
*/
/***********************************************************************/
class FreeVerb : public Effect
{
public:
//! FreeVerb Constructor
/*!
Initializes the effect with default parameters. Note that these defaults
are slightly different than those in the original implementation of
FreeVerb [Effect Mix: 0.75; Room Size: 0.75; Damping: 0.25; Width: 1.0;
Mode: freeze mode off].
*/
FreeVerb();
//! Destructor
~FreeVerb();
//! Set the effect mix [0 = mostly dry, 1 = mostly wet].
void setEffectMix( StkFloat mix );
//! Set the room size (comb filter feedback gain) parameter [0,1].
void setRoomSize( StkFloat value );
//! Get the room size (comb filter feedback gain) parameter.
StkFloat getRoomSize( void );
//! Set the damping parameter [0=low damping, 1=higher damping].
void setDamping( StkFloat value );
//! Get the damping parameter.
StkFloat getDamping( void );
//! Set the width (left-right mixing) parameter [0,1].
void setWidth( StkFloat value );
//! Get the width (left-right mixing) parameter.
StkFloat getWidth( void );
//! Set the mode [frozen = 1, unfrozen = 0].
void setMode( bool isFrozen );
//! Get the current freeze mode [frozen = 1, unfrozen = 0].
StkFloat getMode( void );
//! Clears delay lines, etc.
void clear( void );
//! Return the specified channel value of the last computed stereo frame.
/*!
Use the lastFrame() function to get both values of the last
computed stereo frame. The \c channel argument must be 0 or 1
(the first channel is specified by 0). However, range checking is
only performed if _STK_DEBUG_ is defined during compilation, in
which case an out-of-range value will trigger an StkError
exception.
*/
StkFloat lastOut( unsigned int channel = 0 );
//! Input one or two samples to the effect and return the specified \c channel value of the computed stereo frame.
/*!
Use the lastFrame() function to get both values of the computed
stereo output frame. The \c channel argument must be 0 or 1 (the
first channel is specified by 0). However, range checking is only
performed if _STK_DEBUG_ is defined during compilation, in which
case an out-of-range value will trigger an StkError exception.
*/
StkFloat tick( StkFloat inputL, StkFloat inputR = 0.0, unsigned int channel = 0 );
//! Take two channels of the StkFrames object as inputs to the effect and replace with stereo outputs.
/*!
The StkFrames argument reference is returned. The stereo
inputs are taken from (and written back to) the StkFrames argument
starting at the specified \c channel. Therefore, the \c channel
argument must be less than ( channels() - 1 ) of the StkFrames
argument (the first channel is specified by 0). However, range
checking is only performed if _STK_DEBUG_ is defined during
compilation, in which case an out-of-range value will trigger an
StkError exception.
*/
StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
//! Take one or two channels of the \c iFrames object as inputs to the effect and write stereo outputs to the \c oFrames object.
/*!
The \c iFrames object reference is returned. The \c iChannel
argument must be less than the number of channels in the \c
iFrames argument (the first channel is specified by 0). If more
than one channel of data exists in \c iFrames starting from \c
iChannel, stereo data is input to the effect. The \c oChannel
argument must be less than ( channels() - 1 ) of the \c oFrames
argument. However, range checking is only performed if
_STK_DEBUG_ is defined during compilation, in which case an
out-of-range value will trigger an StkError exception.
*/
StkFrames& tick( StkFrames& iFrames, StkFrames &oFrames, unsigned int iChannel = 0, unsigned int oChannel = 0 );
protected:
//! Update interdependent parameters.
void update( void );
// Clamp very small floats to zero, version from
// http://music.columbia.edu/pipermail/linux-audio-user/2004-July/013489.html .
// However, this is for 32-bit floats only.
//static inline StkFloat undenormalize( volatile StkFloat s ) {
// s += 9.8607615E-32f;
// return s - 9.8607615E-32f;
//}
static const int nCombs = 8;
static const int nAllpasses = 4;
static const int stereoSpread = 23;
static const StkFloat fixedGain;
static const StkFloat scaleWet;
static const StkFloat scaleDry;
static const StkFloat scaleDamp;
static const StkFloat scaleRoom;
static const StkFloat offsetRoom;
// Delay line lengths for 44100Hz sampling rate.
static int cDelayLengths[nCombs];
static int aDelayLengths[nAllpasses];
StkFloat g_; // allpass coefficient
StkFloat gain_;
StkFloat roomSizeMem_, roomSize_;
StkFloat dampMem_, damp_;
StkFloat wet1_, wet2_;
StkFloat dry_;
StkFloat width_;
bool frozenMode_;
// LBFC: Lowpass Feedback Comb Filters
Delay combDelayL_[nCombs];
Delay combDelayR_[nCombs];
OnePole combLPL_[nCombs];
OnePole combLPR_[nCombs];
// AP: Allpass Filters
Delay allPassDelayL_[nAllpasses];
Delay allPassDelayR_[nAllpasses];
};
inline StkFloat FreeVerb :: lastOut( unsigned int channel )
{
#if defined(_STK_DEBUG_)
if ( channel > 1 ) {
oStream_ << "FreeVerb::lastOut(): channel argument must be less than 2!";
handleError( StkError::FUNCTION_ARGUMENT );
}
#endif
return lastFrame_[channel];
}
inline StkFloat FreeVerb::tick( StkFloat inputL, StkFloat inputR, unsigned int channel )
{
#if defined(_STK_DEBUG_)
if ( channel > 1 ) {
oStream_ << "FreeVerb::tick(): channel argument must be less than 2!";
handleError(StkError::FUNCTION_ARGUMENT);
}
#endif
StkFloat fInput = (inputL + inputR) * gain_;
StkFloat outL = 0.0;
StkFloat outR = 0.0;
// Parallel LBCF filters
for ( int i = 0; i < nCombs; i++ ) {
// Left channel
//StkFloat yn = fInput + (roomSize_ * FreeVerb::undenormalize(combLPL_[i].tick(FreeVerb::undenormalize(combDelayL_[i].nextOut()))));
StkFloat yn = fInput + (roomSize_ * combLPL_[i].tick( combDelayL_[i].nextOut() ) );
combDelayL_[i].tick(yn);
outL += yn;
// Right channel
//yn = fInput + (roomSize_ * FreeVerb::undenormalize(combLPR_[i].tick(FreeVerb::undenormalize(combDelayR_[i].nextOut()))));
yn = fInput + (roomSize_ * combLPR_[i].tick( combDelayR_[i].nextOut() ) );
combDelayR_[i].tick(yn);
outR += yn;
}
// Series allpass filters
for ( int i = 0; i < nAllpasses; i++ ) {
// Left channel
//StkFloat vn_m = FreeVerb::undenormalize(allPassDelayL_[i].nextOut());
StkFloat vn_m = allPassDelayL_[i].nextOut();
StkFloat vn = outL + (g_ * vn_m);
allPassDelayL_[i].tick(vn);
// calculate output
outL = -vn + (1.0 + g_)*vn_m;
// Right channel
//vn_m = FreeVerb::undenormalize(allPassDelayR_[i].nextOut());
vn_m = allPassDelayR_[i].nextOut();
vn = outR + (g_ * vn_m);
allPassDelayR_[i].tick(vn);
// calculate output
outR = -vn + (1.0 + g_)*vn_m;
}
// Mix output
lastFrame_[0] = outL*wet1_ + outR*wet2_ + inputL*dry_;
lastFrame_[1] = outR*wet1_ + outL*wet2_ + inputR*dry_;
/*
// Hard limiter ... there's not much else we can do at this point
if ( lastFrame_[0] >= 1.0 ) {
lastFrame_[0] = 0.9999;
}
if ( lastFrame_[0] <= -1.0 ) {
lastFrame_[0] = -0.9999;
}
if ( lastFrame_[1] >= 1.0 ) {
lastFrame_[1] = 0.9999;
}
if ( lastFrame_[1] <= -1.0 ) {
lastFrame_[1] = -0.9999;
}
*/
return lastFrame_[channel];
}
}
#endif

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