From 2cbce2d8bd78479672a02dda6743076d22dcf0e4 Mon Sep 17 00:00:00 2001
From: Gary Scavone
Date: Tue, 24 Mar 2009 23:02:14 -0400
Subject: [PATCH] Version 4.2.1
---
INSTALL | 6 +-
README | 4 +-
configure.ac | 6 +-
doc/README-Linux.txt | 2 +-
doc/README-MacOSX.txt | 4 +-
doc/README-NeXT.txt | 2 +-
doc/README-SGI.txt | 2 +-
doc/README-Win.txt | 2 +-
doc/ReleaseNotes.txt | 34 +-
doc/doxygen/Doxyfile | 43 +-
doc/doxygen/compile.txt | 52 +-
doc/doxygen/control.txt | 2 +-
doc/doxygen/crealtime.txt | 4 +-
doc/doxygen/download.txt | 37 +-
doc/doxygen/filtering.txt | 8 +-
doc/doxygen/footer.html | 2 +-
doc/doxygen/fundamentals.txt | 16 +-
doc/doxygen/hello.txt | 68 +-
doc/doxygen/index.txt | 19 +-
doc/doxygen/information.txt | 39 +-
doc/doxygen/instruments.txt | 10 +-
doc/doxygen/multichannel.txt | 19 +-
doc/doxygen/realtime.txt | 29 +-
doc/doxygen/skini.txt | 50 +-
doc/{Hierarchy.txt => hierarchy.txt} | 92 +-
include/ADSR.h | 22 +-
include/Asymp.h | 20 +-
include/BandedWG.h | 17 +-
include/BeeThree.h | 17 +-
include/BiQuad.h | 19 +-
include/Blit.h | 84 ++
include/BlitSaw.h | 73 ++
include/BlitSquare.h | 89 ++
include/BlowBotl.h | 26 +-
include/BlowHole.h | 26 +-
include/BowTable.h | 22 +-
include/Bowed.h | 26 +-
include/Brass.h | 26 +-
include/Chorus.h | 22 +-
include/Clarinet.h | 24 +-
include/Delay.h | 22 +-
include/DelayA.h | 47 +-
include/DelayL.h | 18 +-
include/Drummer.h | 27 +-
include/Echo.h | 18 +-
include/Effect.h | 22 +-
include/Envelope.h | 26 +-
include/FM.h | 25 +-
include/FMVoices.h | 20 +-
include/FileRead.h | 124 +++
include/FileWrite.h | 112 +++
include/FileWvIn.h | 143 +++
include/FileWvOut.h | 87 ++
include/Filter.h | 35 +-
include/Flute.h | 26 +-
include/FormSwep.h | 22 +-
include/Function.h | 22 +-
include/Generator.h | 30 +-
include/Granulate.h | 145 +++
include/HevyMetl.h | 17 +-
include/InetWvIn.h | 103 ++
include/InetWvOut.h | 77 ++
include/Instrmnt.h | 27 +-
include/JCRev.h | 20 +-
include/JetTable.h | 19 +-
include/Mandolin.h | 32 +-
include/Mesh2D.h | 19 +-
include/Messager.h | 6 +-
include/Modal.h | 27 +-
include/ModalBar.h | 2 +-
include/Modulate.h | 24 +-
include/Moog.h | 20 +-
include/Mutex.h | 2 +-
include/NRev.h | 18 +-
include/Noise.h | 19 +-
include/OnePole.h | 15 +-
include/OneZero.h | 13 +-
include/PRCRev.h | 18 +-
include/PercFlut.h | 17 +-
include/Phonemes.h | 2 +-
include/PitShift.h | 18 +-
include/PluckTwo.h | 44 +-
include/Plucked.h | 20 +-
include/PoleZero.h | 21 +-
include/ReedTable.h | 22 +-
include/Resonate.h | 22 +-
include/Rhodey.h | 17 +-
include/RtAudio.h | 60 +-
include/RtDuplex.h | 2 +-
include/RtMidi.h | 24 +-
include/RtWvIn.h | 97 +-
include/RtWvOut.h | 89 +-
include/Sampler.h | 25 +-
include/Saxofony.h | 24 +-
include/Shakers.h | 16 +-
include/Simple.h | 22 +-
include/SineWave.h | 80 ++
include/SingWave.h | 23 +-
include/Sitar.h | 18 +-
include/Skini.h | 2 +-
include/Socket.h | 101 +-
include/StifKarp.h | 48 +-
include/Stk.h | 123 ++-
include/SubNoise.h | 26 +-
include/Table.h | 63 --
include/TcpClient.h | 61 ++
include/TcpServer.h | 61 ++
include/TcpWvIn.h | 131 ---
include/TcpWvOut.h | 109 --
include/Thread.h | 2 +-
include/TubeBell.h | 17 +-
include/TwoPole.h | 13 +-
include/TwoZero.h | 13 +-
include/UdpSocket.h | 72 ++
include/VoicForm.h | 20 +-
include/Voicer.h | 2 +-
include/WaveLoop.h | 88 +-
include/Whistle.h | 23 +-
include/Wurley.h | 17 +-
include/WvIn.h | 229 +----
include/WvOut.h | 146 +--
projects/demo/Makefile.in | 8 +-
projects/demo/Md2Skini.cpp | 63 +-
projects/demo/demo.cpp | 18 +-
projects/demo/demo.dsp | 48 +
projects/demo/tcl/Demo.tcl | 2 +-
projects/demo/tcl/Modal.tcl | 2 +-
projects/demo/utilities.cpp | 47 +-
projects/demo/utilities.h | 2 +-
projects/effects/Makefile.in | 6 +-
projects/effects/README-effects.txt | 21 +-
projects/effects/{Effects => StkEffects} | 0
.../effects/{Effects.bat => StkEffects.bat} | 0
projects/effects/effects.dsp | 32 +
projects/examples/Makefile.in | 53 +-
projects/examples/bethree.dsp | 24 +
projects/examples/controlbee.dsp | 20 +
projects/examples/crtblit.cpp | 81 ++
projects/examples/crtsine.cpp | 23 +-
projects/examples/crtsine.dsp | 24 +-
projects/examples/examples.dsw | 72 +-
projects/examples/foursine.cpp | 46 +-
projects/examples/foursine.dsp | 32 +
projects/examples/grains.cpp | 105 ++
projects/examples/{tcpOut.dsp => grains.dsp} | 114 ++-
projects/examples/inetIn.cpp | 81 ++
projects/examples/{tcpIn.dsp => inetIn.dsp} | 78 +-
projects/examples/inetOut.cpp | 78 ++
projects/examples/inetOut.dsp | 162 +++
projects/examples/libMakefile.in | 15 +-
projects/examples/play.cpp | 8 +-
projects/examples/play.dsp | 8 +
projects/examples/playsmf.cpp | 1 -
projects/examples/playsmf.dsp | 126 +++
projects/examples/record.cpp | 14 +-
projects/examples/record.dsp | 8 +
projects/examples/rtsine.cpp | 14 +-
projects/examples/rtsine.dsp | 24 +
projects/examples/sine.cpp | 57 +-
projects/examples/sine.dsp | 24 +
projects/examples/sineosc.cpp | 26 +-
projects/examples/sineosc.dsp | 24 +
projects/examples/tcpIn.cpp | 89 --
projects/examples/tcpOut.cpp | 86 --
projects/examples/threebees.dsp | 16 +
projects/ragamatic/Drone.cpp | 26 +-
projects/ragamatic/Drone.h | 18 +-
projects/ragamatic/Makefile.in | 4 +-
projects/ragamatic/Tabla.cpp | 184 ++--
projects/ragamatic/Tabla.h | 39 +-
projects/ragamatic/VoicDrum.cpp | 180 ++--
projects/ragamatic/VoicDrum.h | 39 +-
projects/ragamatic/ragamat.cpp | 8 +-
projects/ragamatic/ragamat.dsp | 24 +
rawwaves/sine.c | 22 +
rawwaves/sinewave.raw | Bin 512 -> 2048 bytes
src/ADSR.cpp | 14 +-
src/Asymp.cpp | 13 +-
src/BandedWG.cpp | 15 +-
src/BeeThree.cpp | 14 +-
src/BiQuad.cpp | 12 +-
src/Blit.cpp | 105 ++
src/BlitSaw.cpp | 125 +++
src/BlitSquare.cpp | 122 +++
src/BlowBotl.cpp | 23 +-
src/BlowHole.cpp | 21 +-
src/BowTable.cpp | 13 +-
src/Bowed.cpp | 23 +-
src/Brass.cpp | 25 +-
src/Chorus.cpp | 31 +-
src/Clarinet.cpp | 23 +-
src/Delay.cpp | 10 +-
src/DelayA.cpp | 46 +-
src/DelayL.cpp | 15 +-
src/Drummer.cpp | 139 ++-
src/Echo.cpp | 14 +-
src/Effect.cpp | 25 +-
src/Envelope.cpp | 36 +-
src/FM.cpp | 10 +-
src/FMVoices.cpp | 16 +-
src/FileRead.cpp | 721 ++++++++++++++
src/FileWrite.cpp | 701 +++++++++++++
src/FileWvIn.cpp | 211 ++++
src/FileWvOut.cpp | 152 +++
src/Filter.cpp | 39 +-
src/Flute.cpp | 30 +-
src/FormSwep.cpp | 17 +-
src/Function.cpp | 25 +-
src/Generator.cpp | 27 +-
src/Granulate.cpp | 275 ++++++
src/HevyMetl.cpp | 19 +-
src/InetWvIn.cpp | 275 ++++++
src/InetWvOut.cpp | 230 +++++
src/Instrmnt.cpp | 21 +-
src/JCRev.cpp | 14 +-
src/JetTable.cpp | 14 +-
src/Makefile.in | 10 +-
src/Mandolin.cpp | 38 +-
src/Mesh2D.cpp | 14 +-
src/Messager.cpp | 11 +-
src/MidiFileIn.cpp | 11 +-
src/Modal.cpp | 23 +-
src/ModalBar.cpp | 16 +-
src/Modulate.cpp | 23 +-
src/Moog.cpp | 16 +-
src/Mutex.cpp | 2 +-
src/NRev.cpp | 15 +-
src/Noise.cpp | 14 +-
src/OnePole.cpp | 11 +-
src/OneZero.cpp | 11 +-
src/PRCRev.cpp | 14 +-
src/PercFlut.cpp | 16 +-
src/Phonemes.cpp | 2 +-
src/PitShift.cpp | 17 +-
src/PluckTwo.cpp | 2 +-
src/Plucked.cpp | 14 +-
src/PoleZero.cpp | 11 +-
src/ReedTable.cpp | 13 +-
src/Resonate.cpp | 14 +-
src/Rhodey.cpp | 20 +-
src/RtAudio.cpp | 698 ++++++++++---
src/RtDuplex.cpp | 2 +-
src/RtMidi.cpp | 146 ++-
src/RtWvIn.cpp | 116 +--
src/RtWvOut.cpp | 221 ++---
src/Sampler.cpp | 2 +-
src/Saxofony.cpp | 23 +-
src/Shakers.cpp | 14 +-
src/Simple.cpp | 14 +-
src/SineWave.cpp | 103 ++
src/SingWave.cpp | 36 +-
src/Sitar.cpp | 14 +-
src/Skini.cpp | 7 +-
src/Socket.cpp | 198 +---
src/StifKarp.cpp | 16 +-
src/Stk.cpp | 187 +++-
src/SubNoise.cpp | 42 +-
src/Table.cpp | 100 --
src/TcpClient.cpp | 100 ++
src/TcpServer.cpp | 95 ++
src/TcpWvIn.cpp | 336 -------
src/TcpWvOut.cpp | 280 ------
src/Thread.cpp | 2 +-
src/TubeBell.cpp | 18 +-
src/TwoPole.cpp | 11 +-
src/TwoZero.cpp | 11 +-
src/UdpSocket.cpp | 104 ++
src/Vector3D.cpp | 2 +-
src/VoicForm.cpp | 44 +-
src/Voicer.cpp | 4 +-
src/WaveLoop.cpp | 209 ++--
src/Whistle.cpp | 43 +-
src/Wurley.cpp | 17 +-
src/WvIn.cpp | 927 +-----------------
src/WvOut.cpp | 844 +---------------
275 files changed, 8949 insertions(+), 6906 deletions(-)
rename doc/{Hierarchy.txt => hierarchy.txt} (63%)
create mode 100644 include/Blit.h
create mode 100644 include/BlitSaw.h
create mode 100644 include/BlitSquare.h
create mode 100644 include/FileRead.h
create mode 100644 include/FileWrite.h
create mode 100644 include/FileWvIn.h
create mode 100644 include/FileWvOut.h
create mode 100644 include/Granulate.h
create mode 100644 include/InetWvIn.h
create mode 100644 include/InetWvOut.h
create mode 100644 include/SineWave.h
delete mode 100644 include/Table.h
create mode 100644 include/TcpClient.h
create mode 100644 include/TcpServer.h
delete mode 100644 include/TcpWvIn.h
delete mode 100644 include/TcpWvOut.h
create mode 100644 include/UdpSocket.h
rename projects/effects/{Effects => StkEffects} (100%)
rename projects/effects/{Effects.bat => StkEffects.bat} (100%)
create mode 100644 projects/examples/crtblit.cpp
create mode 100644 projects/examples/grains.cpp
rename projects/examples/{tcpOut.dsp => grains.dsp} (58%)
mode change 100644 => 100755
create mode 100644 projects/examples/inetIn.cpp
rename projects/examples/{tcpIn.dsp => inetIn.dsp} (64%)
mode change 100644 => 100755
create mode 100644 projects/examples/inetOut.cpp
create mode 100755 projects/examples/inetOut.dsp
create mode 100644 projects/examples/playsmf.dsp
delete mode 100644 projects/examples/tcpIn.cpp
delete mode 100644 projects/examples/tcpOut.cpp
create mode 100644 rawwaves/sine.c
create mode 100644 src/Blit.cpp
create mode 100644 src/BlitSaw.cpp
create mode 100644 src/BlitSquare.cpp
create mode 100644 src/FileRead.cpp
create mode 100644 src/FileWrite.cpp
create mode 100644 src/FileWvIn.cpp
create mode 100644 src/FileWvOut.cpp
create mode 100644 src/Granulate.cpp
create mode 100644 src/InetWvIn.cpp
create mode 100644 src/InetWvOut.cpp
create mode 100644 src/SineWave.cpp
delete mode 100644 src/Table.cpp
create mode 100644 src/TcpClient.cpp
create mode 100644 src/TcpServer.cpp
delete mode 100644 src/TcpWvIn.cpp
delete mode 100644 src/TcpWvOut.cpp
create mode 100644 src/UdpSocket.cpp
diff --git a/INSTALL b/INSTALL
index 09e49aa..00d0ea1 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,6 +1,6 @@
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-2005.
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.
@@ -24,8 +24,8 @@ Several options can be passed to configure, including:
It is now possible to specify more than one Linux audio API. Note however that the ALSA library is required in order to compile the RtMidi class, even if the "--with-oss" option is provided (only the OSS audio API will be used, not the OSS MIDI API). Typing "./configure --help" will display all the available options. In addition, it is possible to specify the RAWWAVES and INCLUDE paths to configure as (ex. to set to /home/gary/rawwaves and /home/gary/include):
- ./configure RAWWAVE_PATH="/home/gary/rawwaves/"
- ./configure INCLUDE_PATH="/home/gary/include/"
+ ./configure RAWWAVE_PATH='$(HOME)/rawwaves/'
+ ./configure INCLUDE_PATH='$(HOME)/include/'
The ending "/" is required for the RAWWAVES path. The default behavior will set a relative path that works for the project files included with the distribution (assuming they are not moved). You can also change the RAWWAVE_PATH dynamically via the static Stk::setRawwavePath() function.
diff --git a/README b/README
index 75f3a64..8a9fe9c 100644
--- a/README
+++ b/README
@@ -1,6 +1,6 @@
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-2005.
This distribution of the Synthesis ToolKit in C++ (STK) contains the following:
@@ -35,7 +35,7 @@ WHAT'S NEW (AND NOT SO NEW):
Despite being available in one form or another since 1996, we still consider STK to be alpha software. We attempt to maintain backward compatability but changes are sometimes made in an effort to improve the overall design or performance of the software. Please read the Release Notes to see what has changed since the last release.
-A new StkFrames class has been created to facilitate the handling and passing of multichannel, vectorized audio data. All STK classes have been updated to include tick() functions which accept StkFrames arguments.
+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.
diff --git a/configure.ac b/configure.ac
index 99f1f7b..f3c9e4e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,7 +1,7 @@
# Process this file with autoconf to produce a configure script.
-AC_INIT(STK, 4.2.0, gary@music.mcgill.ca, stk)
+AC_INIT(STK, 4.2.1, gary@music.mcgill.ca, stk)
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(src/Makefile projects/demo/Makefile projects/effects/Makefile projects/ragamatic/Makefile projects/examples/Makefile projects/examples/libMakefile)
# Checks for programs.
AC_PROG_CC
@@ -53,7 +53,7 @@ AC_ARG_ENABLE(debug,
# Check compiler and use -Wall if gnu.
if test $GXX = "yes" ; then
- AC_SUBST( warn, ["-Wall -g -Woverloaded-virtual -D__GXX__"] )
+ AC_SUBST( warn, ["-Wall -g -D__GXX__"] )
fi
if test $realtime = yes; then
diff --git a/doc/README-Linux.txt b/doc/README-Linux.txt
index 8f64655..99fddaf 100644
--- a/doc/README-Linux.txt
+++ b/doc/README-Linux.txt
@@ -1,6 +1,6 @@
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-2005.
Please read the file README and INSTALL for more general STK information.
diff --git a/doc/README-MacOSX.txt b/doc/README-MacOSX.txt
index 70431e3..1830b6d 100644
--- a/doc/README-MacOSX.txt
+++ b/doc/README-MacOSX.txt
@@ -1,12 +1,12 @@
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-2005.
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 install the OS X developer kit in order to compile STK. STK was successfully tested on OS X versions 10.2 and 10.3.
+It is necessary to install the OS X developer kit in order to compile STK. STK was successfully tested on OS X versions 10.4.
The internal Macintosh audio hardware typically supports a sample rate of 44100 Hz only. The default STK sample rate is now 44100 Hz and all current example programs use this rate. However, it is possible to manually override this value in some programs from the command-line. The default sample rate is set in Stk.h. In addition, the RT_BUFFER_SIZE, specified in Stk.h, could be increased (to a higher power of two) for more robust performance.
diff --git a/doc/README-NeXT.txt b/doc/README-NeXT.txt
index 78f8d24..e9d59b1 100644
--- a/doc/README-NeXT.txt
+++ b/doc/README-NeXT.txt
@@ -1,6 +1,6 @@
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-2005.
Please read the file README and INSTALL for more general STK information.
diff --git a/doc/README-SGI.txt b/doc/README-SGI.txt
index 003a932..febe80f 100644
--- a/doc/README-SGI.txt
+++ b/doc/README-SGI.txt
@@ -1,6 +1,6 @@
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-2005.
Please read the file README and INSTALL for more general STK information.
diff --git a/doc/README-Win.txt b/doc/README-Win.txt
index db38b3c..5d78d14 100644
--- a/doc/README-Win.txt
+++ b/doc/README-Win.txt
@@ -1,6 +1,6 @@
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-2005.
Please read the file README for more general STK information.
diff --git a/doc/ReleaseNotes.txt b/doc/ReleaseNotes.txt
index 41590de..ed4439d 100644
--- a/doc/ReleaseNotes.txt
+++ b/doc/ReleaseNotes.txt
@@ -1,6 +1,38 @@
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-2005.
+
+Future To Do:
+- OSC server/client classes
+- move various error checks, especially in tick() functions, into __DEBUG__ blocks?
+- add WAVEFORMATEXTENSIBLE support to RtAudio
+- add WAVEFORMATEXTENSIBLE support to WvIn/WvOut?
+- better documentation
+
+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
diff --git a/doc/doxygen/Doxyfile b/doc/doxygen/Doxyfile
index f4b1c07..795a16e 100644
--- a/doc/doxygen/Doxyfile
+++ b/doc/doxygen/Doxyfile
@@ -1,11 +1,12 @@
-# Doxyfile 1.3.6
+# Doxyfile 1.4.4
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
PROJECT_NAME = STK
-PROJECT_NUMBER = 4.2.0
+PROJECT_NUMBER = 4.2.1
OUTPUT_DIRECTORY = .
+CREATE_SUBDIRS = NO
OUTPUT_LANGUAGE = English
USE_WINDOWS_ENCODING = NO
BRIEF_MEMBER_DESC = YES
@@ -15,12 +16,14 @@ ALWAYS_DETAILED_SEC = NO
INLINE_INHERITED_MEMB = NO
FULL_PATH_NAMES = NO
STRIP_FROM_PATH =
+STRIP_FROM_INC_PATH =
SHORT_NAMES = NO
JAVADOC_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
DETAILS_AT_TOP = YES
-INHERIT_DOCS = YES
+INHERIT_DOCS = NO
DISTRIBUTE_GROUP_DOC = NO
+SEPARATE_MEMBER_PAGES = NO
TAB_SIZE = 9
ALIASES =
OPTIMIZE_OUTPUT_FOR_C = NO
@@ -31,12 +34,13 @@ SUBGROUPING = YES
#---------------------------------------------------------------------------
EXTRACT_ALL = NO
EXTRACT_PRIVATE = NO
-EXTRACT_STATIC = YES
-EXTRACT_LOCAL_CLASSES = YES
+EXTRACT_STATIC = NO
+EXTRACT_LOCAL_CLASSES = NO
+EXTRACT_LOCAL_METHODS = NO
HIDE_UNDOC_MEMBERS = YES
HIDE_UNDOC_CLASSES = YES
-HIDE_FRIEND_COMPOUNDS = NO
-HIDE_IN_BODY_DOCS = NO
+HIDE_FRIEND_COMPOUNDS = YES
+HIDE_IN_BODY_DOCS = YES
INTERNAL_DOCS = NO
CASE_SENSE_NAMES = YES
HIDE_SCOPE_NAMES = NO
@@ -52,6 +56,8 @@ GENERATE_DEPRECATEDLIST= YES
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
+SHOW_DIRECTORIES = YES
+FILE_VERSION_FILTER =
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
@@ -59,6 +65,7 @@ QUIET = NO
WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
WARN_IF_DOC_ERROR = YES
+WARN_NO_PARAMDOC = NO
WARN_FORMAT = "$file:$line: $text"
WARN_LOGFILE =
#---------------------------------------------------------------------------
@@ -69,7 +76,7 @@ INPUT = . \
FILE_PATTERNS = *.txt \
*.msg \
*.h
-RECURSIVE = YES
+RECURSIVE = NO
EXCLUDE = ../../src/asio
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS =
@@ -78,20 +85,22 @@ EXAMPLE_PATTERNS =
EXAMPLE_RECURSIVE = NO
IMAGE_PATH =
INPUT_FILTER =
+FILTER_PATTERNS =
FILTER_SOURCE_FILES = NO
#---------------------------------------------------------------------------
# configuration options related to source browsing
#---------------------------------------------------------------------------
-SOURCE_BROWSER = YES
-INLINE_SOURCES = YES
+SOURCE_BROWSER = NO
+INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = YES
-REFERENCED_BY_RELATION = YES
-REFERENCES_RELATION = YES
+REFERENCED_BY_RELATION = NO
+REFERENCES_RELATION = NO
+USE_HTAGS = NO
VERBATIM_HEADERS = YES
#---------------------------------------------------------------------------
# configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
-ALPHABETICAL_INDEX = NO
+ALPHABETICAL_INDEX = YES
COLS_IN_ALPHA_INDEX = 5
IGNORE_PREFIX =
#---------------------------------------------------------------------------
@@ -167,7 +176,7 @@ PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
-ENABLE_PREPROCESSING = YES
+ENABLE_PREPROCESSING = NO
MACRO_EXPANSION = NO
EXPAND_ONLY_PREDEF = NO
SEARCH_INCLUDES = YES
@@ -192,18 +201,22 @@ HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = NO
CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
+GROUP_GRAPHS = YES
UML_LOOK = NO
TEMPLATE_RELATIONS = NO
INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
CALL_GRAPH = NO
GRAPHICAL_HIERARCHY = YES
+DIRECTORY_GRAPH = YES
DOT_IMAGE_FORMAT = png
-DOT_PATH =
+DOT_PATH = /sw/bin
DOTFILE_DIRS =
MAX_DOT_GRAPH_WIDTH = 1024
MAX_DOT_GRAPH_HEIGHT = 1024
MAX_DOT_GRAPH_DEPTH = 0
+DOT_TRANSPARENT = NO
+DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = YES
DOT_CLEANUP = YES
#---------------------------------------------------------------------------
diff --git a/doc/doxygen/compile.txt b/doc/doxygen/compile.txt
index 8eccfa1..ff153aa 100644
--- a/doc/doxygen/compile.txt
+++ b/doc/doxygen/compile.txt
@@ -5,9 +5,21 @@ The Synthesis ToolKit can be used in a variety of ways, depending on your partic
\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) dependent. STK classes which require specific platform/OS support include RtAudio, RtWvOut, RtWvIn, RtDuplex, RtMidi, TcpWvIn, TcpWvOut, Socket, Thread, and Mutex. These classes currently can only be compiled on Linux, Irix, Macintosh OS X, and Windows systems.
+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) dependent. STK classes which 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, Irix, 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 __LITTLE_ENDIAN__ 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
+__LITTLE_ENDIAN__ preprocessor definition should be provided.
\section unix Unix Systems:
@@ -28,6 +40,12 @@ STK compiles with realtime support on the following flavors of the Unix operatin
| __LINUX_ALSA__, __LINUX_ALSASEQ__, __LITTLE_ENDIAN__ |
asound, pthread |
+
+ | Linux |
+ Jack (audio only, use ALSA for MIDI support) |
+ __LINUX_JACK__, __LINUX_ALSASEQ__, __LITTLE_ENDIAN__ |
+ asound, pthread |
+
| Linux |
OSS (audio only, use ALSA for MIDI support) |
@@ -51,9 +69,18 @@ STK compiles with realtime support on the following flavors of the Unix operatin
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 sineosc.cpp example from the previous tutorial chapter, it would be necessary to set up a directory that includes the files sineosc.cpp, the rawwave file sinewave.raw in a subdirectory called rawwaves, and the header and source files for the classes Stk, WvIn, WaveLoop, and WvOut. The program could then be compiled on a little-endian system, such as a PC running Linux, using the GNU g++ compiler as follows:
+One approach in using STK is to simply copy the class files needed for
+a particular program into a project directory. Taking the
+sineosc.cpp example from the previous tutorial chapter, it
+would be necessary to set up a directory that includes the files
+sineosc.cpp, the rawwave file sinewave.raw in a
+subdirectory called rawwaves, and the header and source files
+for the classes Stk, FileRead, FileWrite, WvIn, FileWvIn, WaveLoop,
+WvOut, 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 WvIn.cpp WaveLoop.cpp WvOut.cpp sineosc.cpp
+g++ -Wall -D__LITTLE_ENDIAN__ -o sineosc Stk.cpp FileRead.cpp FileWrite.cpp WvIn.cpp FileWvIn.cpp WaveLoop.cpp WvOut.cpp FileWvOut.cpp sineosc.cpp
\endcode
Note that the sineosc.cpp 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.
@@ -75,7 +102,7 @@ With the header files in a standard search path, it is possible to modify the src and include 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 sineosc.cpp, and make sure the sinewave.raw file is in the subdirectory rawwaves.
+The approach when using Visual C++ is to build a project which
+includes the necessary ToolKit files from the distribution
+src and include directories. For the example
+program from the previous tutorial chapter, create a VC++ console
+application project, add the Stk, FileRead, FileWrite, WvIn, FileWvIn,
+WaveLoop, WvOut, and FileWvOut class files, as well as
+sineosc.cpp, and make sure the sinewave.raw file is
+in the subdirectory rawwaves.
For programs using any of the STK realtime classes mentioned above, it is necessary to link with the DirectSound (dsound.lib), winmm.lib, and Wsock32.lib libraries, select the multithreaded library, and provide the __LITTLE_ENDIAN__, __WINDOWS_DS__, and __WINDOWS_MM__ preprocessor definitions.
For Steinberg ASIO support, use the __WINDOWS_ASIO__ preprocessor definition (and the __WINDOWS_MM__ definition for RtMidi support), include all the files in the src/asio/ directory (i.e., asio.h,cpp, asiodrivers.h,cpp, ...), and link with the winmm.lib, and Wsock32.lib libraries.
-[Next tutorial] [Main tutorial page]
+[Main tutorial page] [Next tutorial]
*/
diff --git a/doc/doxygen/control.txt b/doc/doxygen/control.txt
index 5b963f3..5afa72f 100644
--- a/doc/doxygen/control.txt
+++ b/doc/doxygen/control.txt
@@ -39,5 +39,5 @@ Only a few basic SKINI message type case statements are included in this example
This example could also be easily extended to accept "realtime" control input messages via pipe, socket or MIDI connections. The Messager class provides Messager::startStdInput(), Messager::startSocketInput(), and Messager::startMidiInput() functions for this purpose.
-[Next tutorial] [Main tutorial page]
+[Main tutorial page] [Next tutorial]
*/
diff --git a/doc/doxygen/crealtime.txt b/doc/doxygen/crealtime.txt
index af70513..02d4ec4 100644
--- a/doc/doxygen/crealtime.txt
+++ b/doc/doxygen/crealtime.txt
@@ -16,11 +16,11 @@ The \c main() function blocks at the std::cin.get() call until the user hits the
\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.
+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.
The RtAudio class provides both blocking and callback routines for all supported audio APIs. It should be noted that it is easy to embed blocking calls within a thread to create "callback-like" functionality. In fact, this is what RtAudio does for those audio APIs which are naturally based on blocking routines (Linux ALSA and OSS, SGI Irix, and Windows DirectSound). It is much more difficult to make an inherently callback-based system work like a blocking scheme. RtAudio attempts to do this with the Linux JACK, Macintosh OS-X CoreAudio, and Windows ASIO APIs, but the result is not fully robust (audio over/underruns are more likely to occur).
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 which 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.
-[Next tutorial] [Main tutorial page]
+[Main tutorial page] [Next tutorial]
*/
diff --git a/doc/doxygen/download.txt b/doc/doxygen/download.txt
index 751de48..9ba6a6d 100644
--- a/doc/doxygen/download.txt
+++ b/doc/doxygen/download.txt
@@ -1,15 +1,42 @@
-/*! \page download Download and Release Notes
+/*! \page download Download, Release Notes, and Bug Fixes
+
+\section down Download Version 4.2.1 (14 October 2005):
-Version 4.2.0, 4 October 2004
\section notes Release Notes:
+\subsection v4dot2dot1 Version 4.2.1
+
+
+- Greatly expanded StkFrames functionality (including interpolation and indexing by channel/frame).
+- New Blit, BlitSaw, and BlitSquare bandlimited waveform classes (thanks to Robin Davies!).
+- New Granulate granular synthesis class.
+- 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 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.
+- Fixes to RtAudio, especially for Windows DirectSound and ASIO (thanks to Robin Davies).
+
+
\subsection v4dot2dot0 Version 4.2.0
diff --git a/doc/doxygen/filtering.txt b/doc/doxygen/filtering.txt
index 3c24ec8..29a93b7 100644
--- a/doc/doxygen/filtering.txt
+++ b/doc/doxygen/filtering.txt
@@ -7,7 +7,7 @@ In this section, we demonstrate the use of a few of the STK filter classes. The
int main()
{
- StkFrames output( 20 ); // initialize StkFrames to 20 elements (defaults: 1 channel, interleaved)
+ StkFrames output( 20, 1 ); // initialize StkFrames to 20 frames and 1 channel (default: interleaved)
output[0] = 1.0;
std::vector numerator( 5, 0.1 ); // create and initialize numerator coefficients
@@ -46,7 +46,7 @@ The STK BiQuad and TwoPole classes provide functionality for creating resonance
int main()
{
- StkFrames output( 20 ); // initialize StkFrames to 20 elements (defaults: 1 channel, interleaved)
+ StkFrames output( 20, 1 ); // initialize StkFrames to 20 frames and 1 channel (default: interleaved)
Noise noise;
BiQuad biquad;
@@ -69,7 +69,7 @@ By passing a boolian value of \c true as the third argument to the BiQuad::setRe
int main()
{
- StkFrames output( 20 ); // initialize StkFrames to 20 elements (defaults: 1 channel, interleaved)
+ StkFrames output( 20, 1 ); // initialize StkFrames to 20 frames and 1 channel (default: interleaved)
Noise noise;
BiQuad biquad;
@@ -84,5 +84,5 @@ int main()
}
\endcode
-[Next tutorial] [Main tutorial page]
+[Main tutorial page] [Next tutorial]
*/
diff --git a/doc/doxygen/footer.html b/doc/doxygen/footer.html
index 132c535..3eb686f 100644
--- a/doc/doxygen/footer.html
+++ b/doc/doxygen/footer.html
@@ -2,7 +2,7 @@
| The Synthesis ToolKit in C++ (STK) |
- | ©1995-2004 Perry R. Cook and Gary P. Scavone. All Rights Reserved. |
+ | ©1995-2005 Perry R. Cook and Gary P. Scavone. All Rights Reserved. |
-
\htmlonly
+
\endhtmlonly
-The Synthesis ToolKit in C++ (STK) is a set of open source audio signal processing and algorithmic synthesis classes written in the C++ programming language. STK was designed to facilitate rapid development of music synthesis and audio processing software, with an emphasis on cross-platform functionality, realtime control, ease of use, and educational example code. The Synthesis ToolKit is extremely portable (it's mostly platform-independent C and C++ code), and it's completely user-extensible (all source included, no unusual libraries, and no hidden drivers). We like to think that this increases the chances that our programs will still work in another 5-10 years. In fact, the ToolKit has been working continuously for nearly 10 years now. STK currently runs with "realtime" support (audio and MIDI) on 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 about 10 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.
- \ref information
- \ref classes
diff --git a/doc/doxygen/information.txt b/doc/doxygen/information.txt
index cda37ed..0fccfd2 100644
--- a/doc/doxygen/information.txt
+++ b/doc/doxygen/information.txt
@@ -2,17 +2,17 @@
References
-- ICMC99 Paper
+- ICMC2005 Paper
+
+A paper by Gary and Perry detailing recent updates to the Synthesis ToolKit in C++.
+
+
- ICMC99 Paper
A not-so-recent paper by Perry and Gary about the Synthesis ToolKit in C++.
-
- SIGGRAPH96 Paper
+- Book Chapter: Audio Anecdotes
-A very-not-so-recent paper by Perry about the Synthesis ToolKit in C++.
-
-
- Perry's STK Web Page
-
-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.
@@ -31,9 +31,30 @@ For those instances where a simple GUI with sliders and buttons is helpful, we u
A brief history of the Synthesis ToolKit in C++.
-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 Princeton Sound Kitchen, Perry Cook's home page at Princeton, Gary Scavone's home page at Stanford's Center for Computer Research in Music and Acoustics (CCRMA), and the Synthesis ToolKit home page. 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 PeRColate. Help on real-time sound and MIDI has been provided over the years by Tim Stilson, Bill Putnam, and Gabriel Maldonado.
+The Toolkit has been distributed continuously since 1996 via the Princeton Sound Kitchen,
+Perry Cook's home page
+at Princeton, Gary
+Scavone's home page at McGill University, and the Synthesis ToolKit
+home page. 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 PeRColate. Help on
+real-time sound and MIDI has been provided over the years by Tim
+Stilson, Bill Putnam, and Gabriel Maldonado.
Legal and Ethical Notes
diff --git a/doc/doxygen/instruments.txt b/doc/doxygen/instruments.txt
index 6a75a8e..6ccc7f5 100644
--- a/doc/doxygen/instruments.txt
+++ b/doc/doxygen/instruments.txt
@@ -4,12 +4,16 @@ The ToolKit comes with a wide variety of synthesis algorithms, all of which inhe
\include bethree.cpp
-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).
+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., 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.
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.
-[Next tutorial] [Main tutorial page]
+[Main tutorial page] [Next tutorial]
*/
diff --git a/doc/doxygen/multichannel.txt b/doc/doxygen/multichannel.txt
index e6dc567..15b6fa2 100644
--- a/doc/doxygen/multichannel.txt
+++ b/doc/doxygen/multichannel.txt
@@ -2,13 +2,26 @@
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 sample frame. 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 tick() function. In order to distinguish single-sample and sample frame calculations, the WvIn and WvOut classes implement both tick() and tickFrame() functions. The tickFrame() functions take or return a pointer to an array of audio data representing one or more sample frames. For single-channel streams, the tick() and tickFrame() functions produce equivalent results. When tick() 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
+tick() function. In order to distinguish single-sample and
+sample frame calculations, the WvIn and WvOut classes implement both
+tick() and tickFrame() functions. The
+tickFrame() functions take or return a reference to an StkFrames object
+representing one or more sample frames. For single-channel
+streams, the tick() and tickFrame() functions
+produce equivalent results. When tick() 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).
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 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.
\include foursine.cpp
-[Next tutorial] [Main tutorial page]
+[Main tutorial page] [Next tutorial]
*/
diff --git a/doc/doxygen/realtime.txt b/doc/doxygen/realtime.txt
index fe51f0b..bb3f1b8 100644
--- a/doc/doxygen/realtime.txt
+++ b/doc/doxygen/realtime.txt
@@ -1,28 +1,43 @@
/*! \page realtime Realtime Audio (blocking)
-In this section, we modify the sineosc.cpp program in order to send the output to the default audio playback device on your computer system.
+In this section, we modify the sineosc.cpp program in order
+to send the output to the default audio playback device on your
+computer system. We also make use of the SineWave class as a
+sine-wave oscillator. 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 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. RtWvOut provides a "single-sample" interface to the RtAudio class. Note that RtWvOut (as well as the RtWvIn and RtDuplex classes described below) make use of RtAudio's blocking input/output functionality. On systems which implement an inherently callback-based audio API, this blocking functionality will be less robust. An example of audio output using a callback scheme will be discussed in a subsequent tutorial section.
+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. RtWvOut provides a "single-sample"
+interface to the RtAudio class. Note that RtWvOut (as well as the
+RtWvIn and RtDuplex classes described below) make use of RtAudio's
+blocking input/output functionality. On systems that implement an
+inherently callback-based audio API (Linux Jack, Windows ASIO, OS-X
+CoreAudio), this blocking functionality will be less robust. An
+example of audio output using a callback scheme will be discussed in a
+subsequent tutorial section.
-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 record.cpp example program in the examples project for more information.
+Though not used here, an RtWvIn class exists as well that can be used to read realtime audio data from an input device. See the record.cpp example program in the examples project for more information.
It may be 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 effects project or the io.cpp example program in the examples 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 API as follows (assuming all necessary files exist in the project directory):
+When using any realtime STK class (RtAudio, RtWvOut, RtWvIn, RtDuplex, RtMidi, InetWvIn, InetWvOut, Socket, UdpSocket, TcpServer, TcpClient, 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 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 \
+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
-g++ -Wall -D__MACOSX_CORE__ -o rtsine Stk.cpp WvIn.cpp WaveLoop.cpp WvOut.cpp RtWvOut.cpp RtAudio.cpp \
+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
-[Next tutorial] [Main tutorial page]
+[Main tutorial page] [Next tutorial]
*/
diff --git a/doc/doxygen/skini.txt b/doc/doxygen/skini.txt
index 44b7fa1..9509295 100644
--- a/doc/doxygen/skini.txt
+++ b/doc/doxygen/skini.txt
@@ -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 Files Used To Implement SKINI
-Skini.cpp is a C++ 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 floatValues; /*!< The message values read as floats (values are type-specific). */
+ std::vector 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 long ints, 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 ints (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,13 +167,13 @@ 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;
@@ -207,8 +219,6 @@ Here's a simple example of code which uses the SKINI object to read a SKINI file
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.
-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.
-
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.
diff --git a/doc/Hierarchy.txt b/doc/hierarchy.txt
similarity index 63%
rename from doc/Hierarchy.txt
rename to doc/hierarchy.txt
index 6a1f52a..8520e0b 100644
--- a/doc/Hierarchy.txt
+++ b/doc/hierarchy.txt
@@ -1,20 +1,24 @@
STK: A ToolKit of Audio Synthesis Classes and Instruments in C++
-By Perry R. Cook and Gary P. Scavone, 1995-2004.
+By Perry R. Cook and Gary P. Scavone, 1995-2005.
STK Classes - See the HTML documentation in the html directory for complete information.
- .- Generator - (Modulate, Noise, SingWave, Envelope)
+ .- Generator - (Modulate, Noise, SingWave, Envelope, SineWave, Blit, BlitSaw, BlitSquare, Granulate)
| | |
| SubNoise ADSR
| Asymp
|
- |- Function - (Table, BowTable, JetTable, ReedTable)
+ |- Function - (BowTable, JetTable, ReedTable)
|
- |- WvIn - (WaveLoop, RtWvIn, TcpWvIn)
+ |- FileRead, FileWrite
|
- |- WvOut - (RtWvOut, TcpWvOut)
+ |- WvIn - (FileWvIn, RtWvIn, InetWvIn)
+ | |
+ | WaveLoop
+ |
+ |- WvOut - (FileWvOut, RtWvOut, TcpWvOut)
|
|- Filter - (OnePole, OneZero, Delay, TwoPole, TwoZero, PoleZero, Biquad)
| | |
@@ -22,7 +26,13 @@ STK Classes - See the HTML documentation in the html directory for complete info
| DelayA
|
|- RtAudio, RtMidi, RtDuplex, Socket, Thread, Mutex
-Stk -|
+ | |
+Stk -| UdpSocket
+ | TcpServer
+ | TcpClient
+ |
+ |- StkFrames
+ |
|- Effect - (Echo, Chorus, PitShift, PRCRev, JCRev, NRev)
|
|- Voicer, Message, Skini, MidiFileIn, Phonemes, Sphere, Vector3D
@@ -58,42 +68,50 @@ Stk -|
Master Class: Stk.cpp Sample rate, byte-swapping, error handling functionality
-Sources: Generator.cpp Abstract Base Class for Various Source Signal Classes
- Function.cpp Abstract Base Class for Various Input/Output Mapping Classes
- Envelope.cpp Linearly Goes to Target by Rate
- ADSR.cpp ADSR Flavor of Envelope
- Asymp.cpp Exponentially Approaches Target
- 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)
+Sources: Generator.cpp Abstract base class for various source signal classes
+ Function.cpp Abstract base class for various input/output mapping classes
+ Envelope.cpp Linearly goes to target by rate
+ ADSR.cpp ADSR flavor of Envelope
+ Asymp.cpp Exponentially approaches target
+ Noise.cpp Random number generator
+ SubNoise.cpp Random numbers each N samples
+ 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.cpp Abstract base class for audio data input classes
+ FileWvIn.cpp Audio file input interface class with interpolation
+ WaveLoop.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: 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)
+Sinks: FileWrite.cpp Audio file output class (no internal data storage) for RAW, WAV, SND (AU), AIFF, MAT-file files
+ WvOut.cpp 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)
-Duplex: RtDuplex.cpp Synchronous Realtime Audio Input/Output Class
+Duplex: RtDuplex.cpp Synchronous realtime audio input/output class (blocking)
-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)
+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
+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
+Derived: Modulate.cpp Periodic and random vibrato: WvIn, SubNoise, OnePole
SingWave.cpp Looping wave table with randomness: Modulate, WaveLoop, Envelope
diff --git a/include/ADSR.h b/include/ADSR.h
index f9e0e4b..04df416 100644
--- a/include/ADSR.h
+++ b/include/ADSR.h
@@ -11,7 +11,7 @@
envelope value reaches 0.0 in the
ADSR::RELEASE state.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -60,7 +60,7 @@ class ADSR : public Envelope
//! Set the release rate based on a time duration.
void setReleaseTime(StkFloat time);
- //! Set sustain level and attach, decay, and release time durations.
+ //! Set sustain level and attack, decay, and release time durations.
void setAllTimes(StkFloat aTime, StkFloat dTime, StkFloat sLevel, StkFloat rTime);
//! Set the target value.
@@ -72,22 +72,10 @@ class ADSR : public Envelope
//! Set to state = ADSR::SUSTAIN with current and target values of \e aValue.
void setValue(StkFloat value);
- //! Return one envelope output value.
- StkFloat tick(void);
-
- //! Compute \e vectorSize outputs and return them in \e vector.
- StkFloat *tick( StkFloat *vector, unsigned int vectorSize );
-
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
protected:
+
+ StkFloat computeSample( void );
+
StkFloat attackRate_;
StkFloat decayRate_;
StkFloat sustainLevel_;
diff --git a/include/Asymp.h b/include/Asymp.h
index fd708e0..e1a5c1d 100644
--- a/include/Asymp.h
+++ b/include/Asymp.h
@@ -19,7 +19,7 @@
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 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -61,22 +61,10 @@ class Asymp : public Envelope
//! Set the target value.
void setTarget(StkFloat target);
- //! Return one envelope output value.
- StkFloat tick(void);
-
- //! Compute \e vectorSize outputs and return them in \e vector.
- StkFloat *tick( StkFloat *vector, unsigned int vectorSize );
-
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
protected:
+
+ StkFloat computeSample( void );
+
StkFloat factor_;
StkFloat constant_;
};
diff --git a/include/BandedWG.h b/include/BandedWG.h
index 1c613e1..675290e 100644
--- a/include/BandedWG.h
+++ b/include/BandedWG.h
@@ -76,26 +76,13 @@ class BandedWG : public Instrmnt
//! Stop a note with the given amplitude (speed of decay).
void noteOff(StkFloat amplitude);
- //! Compute one output sample.
- StkFloat tick();
-
- //! Computer \e vectorSize outputs and return them in \e vector.
- StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
-
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
void controlChange(int number, StkFloat value);
protected:
+ StkFloat computeSample( void );
+
bool doPluck_;
bool trackVelocity_;
int nModes_;
diff --git a/include/BeeThree.h b/include/BeeThree.h
index c71148f..0880c24 100644
--- a/include/BeeThree.h
+++ b/include/BeeThree.h
@@ -28,7 +28,7 @@
type who should worry about this (making
money) worry away.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -52,20 +52,9 @@ class BeeThree : public FM
//! Start a note with the given frequency and amplitude.
void noteOn(StkFloat frequency, StkFloat amplitude);
- //! Compute one output sample.
- StkFloat tick();
+ protected:
- //! Computer \e vectorSize outputs and return them in \e vector.
- StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
-
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
+ StkFloat computeSample( void );
};
#endif
diff --git a/include/BiQuad.h b/include/BiQuad.h
index 4d5803c..7a58548 100644
--- a/include/BiQuad.h
+++ b/include/BiQuad.h
@@ -8,7 +8,7 @@
frequency response while maintaining a constant
filter gain.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -93,17 +93,20 @@ public:
//! Input one sample to the filter and return one output.
virtual StkFloat tick(StkFloat sample);
- //! Input \e vectorSize samples to the filter and return an equal number of outputs in \e vector.
- virtual StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
-
//! Take a channel of the StkFrames object as inputs to the filter and replace with corresponding outputs.
/*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
+ The \c channel argument should be zero or greater (the first
+ channel is specified by 0). An StkError will be thrown if the \c
+ channel argument is equal to or greater than the number of
channels in the StkFrames object.
*/
- virtual StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
+ virtual StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
+
+ protected:
+
+ // This function must be implemented in all subclasses. It is used
+ // to get around a C++ problem with overloaded virtual functions.
+ virtual StkFloat computeSample( StkFloat input );
};
#endif
diff --git a/include/Blit.h b/include/Blit.h
new file mode 100644
index 0000000..897c623
--- /dev/null
+++ b/include/Blit.h
@@ -0,0 +1,84 @@
+/***************************************************/
+/*! \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.
+*/
+/***************************************************/
+
+#ifndef STK_BLIT_H
+#define STK_BLIT_H
+
+#include "Generator.h"
+
+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 );
+
+ protected:
+
+ void updateHarmonics( void );
+ StkFloat computeSample( void );
+
+ unsigned int nHarmonics_;
+ unsigned int m_;
+ StkFloat rate_;
+ StkFloat phase_;
+ StkFloat p_;
+
+};
+
+#endif
diff --git a/include/BlitSaw.h b/include/BlitSaw.h
new file mode 100644
index 0000000..5d643f3
--- /dev/null
+++ b/include/BlitSaw.h
@@ -0,0 +1,73 @@
+/***************************************************/
+/*! \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.
+*/
+/***************************************************/
+
+#ifndef STK_BLITSAW_H
+#define STK_BLITSAW_H
+
+#include "Generator.h"
+
+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 );
+
+ protected:
+
+ void updateHarmonics( void );
+ StkFloat computeSample( void );
+
+ unsigned int nHarmonics_;
+ unsigned int m_;
+ StkFloat rate_;
+ StkFloat phase_;
+ StkFloat p_;
+ StkFloat C2_;
+ StkFloat a_;
+ StkFloat state_;
+
+};
+
+#endif
diff --git a/include/BlitSquare.h b/include/BlitSquare.h
new file mode 100644
index 0000000..8c758ff
--- /dev/null
+++ b/include/BlitSquare.h
@@ -0,0 +1,89 @@
+/***************************************************/
+/*! \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 but that is
+ subtracted off the output signal.
+
+ 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).
+
+ Based on initial code of Robin Davies, 2005.
+ Modified algorithm code by Gary Scavone, 2005.
+*/
+/***************************************************/
+
+#ifndef STK_BLITSQUARE_H
+#define STK_BLITSQUARE_H
+
+#include "Generator.h"
+
+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 );
+
+ protected:
+
+ void updateHarmonics( void );
+ StkFloat computeSample( void );
+
+ unsigned int nHarmonics_;
+ unsigned int m_;
+ StkFloat rate_;
+ StkFloat phase_;
+ StkFloat p_;
+ StkFloat offset_;
+};
+
+#endif
diff --git a/include/BlowBotl.h b/include/BlowBotl.h
index 16d8ab2..7bf7f1b 100644
--- a/include/BlowBotl.h
+++ b/include/BlowBotl.h
@@ -12,7 +12,7 @@
- Vibrato Gain = 1
- Volume = 128
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -25,7 +25,7 @@
#include "PoleZero.h"
#include "Noise.h"
#include "ADSR.h"
-#include "WaveLoop.h"
+#include "SineWave.h"
class BlowBotl : public Instrmnt
{
@@ -57,31 +57,19 @@ class BlowBotl : public Instrmnt
//! Stop a note with the given amplitude (speed of decay).
void noteOff(StkFloat amplitude);
- //! Compute one output sample.
- StkFloat tick();
-
- //! Computer \e vectorSize outputs and return them in \e vector.
- StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
-
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
void controlChange(int number, StkFloat value);
- protected:
+ protected:
+
+ StkFloat computeSample( void );
+
JetTable jetTable_;
BiQuad resonator_;
PoleZero dcBlock_;
Noise noise_;
ADSR adsr_;
- WaveLoop *vibrato_;
+ SineWave vibrato_;
StkFloat maxPressure_;
StkFloat noiseGain_;
StkFloat vibratoGain_;
diff --git a/include/BlowHole.h b/include/BlowHole.h
index 83e36dd..9dd06b4 100644
--- a/include/BlowHole.h
+++ b/include/BlowHole.h
@@ -29,7 +29,7 @@
- Register State = 1
- Breath Pressure = 128
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -43,7 +43,7 @@
#include "PoleZero.h"
#include "Envelope.h"
#include "Noise.h"
-#include "WaveLoop.h"
+#include "SineWave.h"
class BlowHole : public Instrmnt
{
@@ -81,25 +81,13 @@ class BlowHole : public Instrmnt
//! Stop a note with the given amplitude (speed of decay).
void noteOff(StkFloat amplitude);
- //! Compute one output sample.
- StkFloat tick();
-
- //! Computer \e vectorSize outputs and return them in \e vector.
- StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
-
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
void controlChange(int number, StkFloat value);
- protected:
+ protected:
+
+ StkFloat computeSample( void );
+
DelayL delays_[3];
ReedTable reedTable_;
OneZero filter_;
@@ -107,7 +95,7 @@ class BlowHole : public Instrmnt
PoleZero vent_;
Envelope envelope_;
Noise noise_;
- WaveLoop *vibrato_;
+ SineWave vibrato_;
unsigned long length_;
StkFloat scatter_;
StkFloat thCoeff_;
diff --git a/include/BowTable.h b/include/BowTable.h
index 7c61708..093b9aa 100644
--- a/include/BowTable.h
+++ b/include/BowTable.h
@@ -5,7 +5,7 @@
This class implements a simple bowed string
non-linear function, as described by Smith (1986).
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -39,26 +39,10 @@ public:
*/
void setSlope(StkFloat slope);
- //! Return the function value for \e input.
- /*!
- The function input represents differential
- string-to-bow velocity.
- */
- StkFloat tick( StkFloat input);
+protected:
- //! Take \e vectorSize inputs from \e vector and replace them with corresponding outputs.
- StkFloat *tick( StkFloat *vector, unsigned int vectorSize );
+ StkFloat computeSample( StkFloat input );
- //! Take a channel of the StkFrames object as inputs to the function and replace with corresponding outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
-protected:
StkFloat offset_;
StkFloat slope_;
diff --git a/include/Bowed.h b/include/Bowed.h
index 2392b14..56be381 100644
--- a/include/Bowed.h
+++ b/include/Bowed.h
@@ -17,7 +17,7 @@
- Vibrato Gain = 1
- Volume = 128
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -29,7 +29,7 @@
#include "BowTable.h"
#include "OnePole.h"
#include "BiQuad.h"
-#include "WaveLoop.h"
+#include "SineWave.h"
#include "ADSR.h"
class Bowed : public Instrmnt
@@ -62,31 +62,19 @@ class Bowed : public Instrmnt
//! Stop a note with the given amplitude (speed of decay).
void noteOff(StkFloat amplitude);
- //! Compute one output sample.
- StkFloat tick();
-
- //! Computer \e vectorSize outputs and return them in \e vector.
- StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
-
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
void controlChange(int number, StkFloat value);
- protected:
+ protected:
+
+ StkFloat computeSample( void );
+
DelayL neckDelay_;
DelayL bridgeDelay_;
BowTable bowTable_;
OnePole stringFilter_;
BiQuad bodyFilter_;
- WaveLoop *vibrato_;
+ SineWave vibrato_;
ADSR adsr_;
StkFloat maxVelocity_;
StkFloat baseDelay_;
diff --git a/include/Brass.h b/include/Brass.h
index 7d03039..2242bb3 100644
--- a/include/Brass.h
+++ b/include/Brass.h
@@ -16,7 +16,7 @@
- Vibrato Gain = 1
- Volume = 128
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -28,7 +28,7 @@
#include "BiQuad.h"
#include "PoleZero.h"
#include "ADSR.h"
-#include "WaveLoop.h"
+#include "SineWave.h"
class Brass: public Instrmnt
{
@@ -63,30 +63,18 @@ class Brass: public Instrmnt
//! Stop a note with the given amplitude (speed of decay).
void noteOff(StkFloat amplitude);
- //! Compute one output sample.
- StkFloat tick();
-
- //! Computer \e vectorSize outputs and return them in \e vector.
- StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
-
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
void controlChange(int number, StkFloat value);
- protected:
+ protected:
+
+ StkFloat computeSample( void );
+
DelayA delayLine_;
BiQuad lipFilter_;
PoleZero dcBlock_;
ADSR adsr_;
- WaveLoop *vibrato_;
+ SineWave vibrato_;
unsigned long length_;
StkFloat lipTarget_;
StkFloat slideTarget_;
diff --git a/include/Chorus.h b/include/Chorus.h
index a4daaea..241e1e9 100644
--- a/include/Chorus.h
+++ b/include/Chorus.h
@@ -4,7 +4,7 @@
This class implements a chorus effect.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -13,7 +13,7 @@
#include "Effect.h"
#include "DelayL.h"
-#include "WaveLoop.h"
+#include "SineWave.h"
class Chorus : public Effect
{
@@ -36,24 +36,12 @@ class Chorus : public Effect
//! Set modulation frequency.
void setModFrequency(StkFloat frequency);
- //! Compute one output sample.
- StkFloat tick(StkFloat input);
+ protected:
- //! Take \e vectorSize inputs, compute the same number of outputs and return them in \e vector.
- StkFloat *tick( StkFloat *vector, unsigned int vectorSize );
+ StkFloat computeSample( StkFloat input );
- //! Take a channel of the StkFrames object as inputs to the effect and replace with corresponding outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
- protected:
DelayL delayLine_[2];
- WaveLoop *mods_[2];
+ SineWave mods_[2];
StkFloat baseLength_;
StkFloat modDepth_;
diff --git a/include/Clarinet.h b/include/Clarinet.h
index 9aaac2c..d5b09ac 100644
--- a/include/Clarinet.h
+++ b/include/Clarinet.h
@@ -18,7 +18,7 @@
- Vibrato Gain = 1
- Breath Pressure = 128
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -31,7 +31,7 @@
#include "OneZero.h"
#include "Envelope.h"
#include "Noise.h"
-#include "WaveLoop.h"
+#include "SineWave.h"
class Clarinet : public Instrmnt
{
@@ -63,31 +63,19 @@ class Clarinet : public Instrmnt
//! Stop a note with the given amplitude (speed of decay).
void noteOff(StkFloat amplitude);
- //! Compute one output sample.
- StkFloat tick();
-
- //! Computer \e vectorSize outputs and return them in \e vector.
- StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
-
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
void controlChange(int number, StkFloat value);
protected:
+
+ StkFloat computeSample( void );
+
DelayL delayLine_;
ReedTable reedTable_;
OneZero filter_;
Envelope envelope_;
Noise noise_;
- WaveLoop *vibrato_;
+ SineWave vibrato_;
long length_;
StkFloat outputGain_;
StkFloat noiseGain_;
diff --git a/include/Delay.h b/include/Delay.h
index 7ef8cbc..83dc8f1 100644
--- a/include/Delay.h
+++ b/include/Delay.h
@@ -14,7 +14,7 @@
used in fixed delay-length applications, such
as for reverberation.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -83,22 +83,24 @@ public:
*/
virtual StkFloat nextOut(void);
- //! Input one sample to the delayline and return one output.
+ //! Input one sample to the filter and return one output.
virtual StkFloat tick(StkFloat sample);
- //! Input \e vectorSize samples to the delayline and return an equal number of outputs in \e vector.
- virtual StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
-
- //! Take a channel of the StkFrames object as inputs to the delayline and replace with corresponding outputs.
+ //! Take a channel of the StkFrames object as inputs to the filter and replace with corresponding outputs.
/*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
+ The \c channel argument should be zero or greater (the first
+ channel is specified by 0). An StkError will be thrown if the \c
+ channel argument is equal to or greater than the number of
channels in the StkFrames object.
*/
- virtual StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
+ virtual StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
protected:
+
+ // This function must be implemented in all subclasses. It is used
+ // to get around a C++ problem with overloaded virtual functions.
+ virtual StkFloat computeSample( StkFloat input );
+
unsigned long inPoint_;
unsigned long outPoint_;
StkFloat delay_;
diff --git a/include/DelayA.h b/include/DelayA.h
index 9ef6a0b..540f950 100644
--- a/include/DelayA.h
+++ b/include/DelayA.h
@@ -2,23 +2,20 @@
/*! \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 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.
- 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 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -55,7 +52,7 @@ public:
void setDelay(StkFloat delay);
//! Return the current delay-line length.
- StkFloat getDelay(void);
+ StkFloat getDelay(void) const;
//! Return the value which will be output by the next call to tick().
/*!
@@ -63,22 +60,10 @@ public:
*/
StkFloat nextOut(void);
- //! Input one sample to the delayline and return one output.
- StkFloat tick(StkFloat sample);
-
- //! Input \e vectorSize samples to the delayline and return an equal number of outputs in \e vector.
- virtual StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
-
- //! Take a channel of the StkFrames object as inputs to the delayline and replace with corresponding outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- virtual StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
protected:
+
+ StkFloat computeSample( StkFloat input );
+
StkFloat alpha_;
StkFloat coeff_;
StkFloat apInput_;
diff --git a/include/DelayL.h b/include/DelayL.h
index 722a7da..f0e0b87 100644
--- a/include/DelayL.h
+++ b/include/DelayL.h
@@ -18,7 +18,7 @@
order Lagrange interpolators can typically
improve (minimize) this attenuation characteristic.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -60,22 +60,10 @@ public:
*/
StkFloat nextOut(void);
- //! Input one sample to the delay-line and return one output.
- StkFloat tick(StkFloat sample);
+ protected:
- //! Input \e vectorSize samples to the delay-line and return an equal number of outputs in \e vector.
- virtual StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
+ StkFloat computeSample( StkFloat input );
- //! Take a channel of the StkFrames object as inputs to the delayline and replace with corresponding outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- virtual StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
- protected:
StkFloat alpha_;
StkFloat omAlpha_;
StkFloat nextOutput_;
diff --git a/include/Drummer.h b/include/Drummer.h
index b081ae8..e362ef7 100644
--- a/include/Drummer.h
+++ b/include/Drummer.h
@@ -11,7 +11,7 @@
of simultaneous voices) via a #define in the
Drummer.h.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -19,7 +19,7 @@
#define STK_DRUMMER_H
#include "Instrmnt.h"
-#include "WvIn.h"
+#include "FileWvIn.h"
#include "OnePole.h"
const int DRUM_NUMWAVES = 11;
@@ -49,25 +49,14 @@ class Drummer : public Instrmnt
//! Stop a note with the given amplitude (speed of decay).
void noteOff(StkFloat amplitude);
- //! Compute one output sample.
- StkFloat tick();
+ protected:
- //! Computer \e vectorSize outputs and return them in \e vector.
- StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
+ StkFloat computeSample( void );
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
- protected:
- WvIn *waves_[DRUM_POLYPHONY];
- OnePole *filters_[DRUM_POLYPHONY];
- int sounding_[DRUM_POLYPHONY];
+ FileWvIn waves_[DRUM_POLYPHONY];
+ OnePole filters_[DRUM_POLYPHONY];
+ std::vector soundOrder_;
+ std::vector soundNumber_;
int nSounding_;
};
diff --git a/include/Echo.h b/include/Echo.h
index 57d7f11..f8f3d76 100644
--- a/include/Echo.h
+++ b/include/Echo.h
@@ -4,7 +4,7 @@
This class implements an echo effect.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -35,22 +35,10 @@ class Echo : public Effect
//! Set the delay line length in samples.
void setDelay( unsigned long delay );
- //! Compute one output sample.
- StkFloat tick(StkFloat input);
+ protected:
- //! Take \e vectorSize inputs, compute the same number of outputs and return them in \e vector.
- StkFloat *tick( StkFloat *vector, unsigned int vectorSize );
+ StkFloat computeSample( StkFloat input );
- //! Take a channel of the StkFrames object as inputs to the effect and replace with corresponding outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
- protected:
Delay delayLine_;
unsigned long length_;
diff --git a/include/Effect.h b/include/Effect.h
index 60d40e9..8903d8e 100644
--- a/include/Effect.h
+++ b/include/Effect.h
@@ -5,7 +5,7 @@
This class provides common functionality for
STK effects subclasses.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -38,23 +38,25 @@ class Effect : public Stk
//! Return the last right output value.
StkFloat lastOutRight() const;
- //! Abstract tick function ... must be implemented in subclasses.
- virtual StkFloat tick( StkFloat input ) = 0;
-
- //! Take \e vectorSize inputs, compute the same number of outputs and return them in \e vector.
- virtual StkFloat *tick( StkFloat *vector, unsigned int vectorSize );
+ //! Take one sample input and compute one sample of output.
+ StkFloat tick( StkFloat input );
//! Take a channel of the StkFrames object as inputs to the effect and replace with corresponding outputs.
/*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
+ The \c channel argument should be zero or greater (the first
+ channel is specified by 0). An StkError will be thrown if the \c
+ channel argument is equal to or greater than the number of
channels in the StkFrames object.
*/
- virtual StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
+ StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
protected:
+ // This abstract function must be implemented in all subclasses.
+ // It is used to get around a C++ problem with overloaded virtual
+ // functions.
+ virtual StkFloat computeSample( StkFloat input ) = 0;
+
// Returns true if argument value is prime.
bool isPrime( int number );
diff --git a/include/Envelope.h b/include/Envelope.h
index dc5b2c7..7b8a688 100644
--- a/include/Envelope.h
+++ b/include/Envelope.h
@@ -9,7 +9,7 @@
\e keyOff messages, ramping to 1.0 on
keyOn and to 0.0 on keyOff.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -25,9 +25,15 @@ class Envelope : public Generator
//! Default constructor.
Envelope(void);
+ //! Copy constructor.
+ Envelope( const Envelope& e );
+
//! Class destructor.
virtual ~Envelope(void);
+ //! Assignment operator.
+ Envelope& operator= ( const Envelope& e );
+
//! Set target = 1.
virtual void keyOn(void);
@@ -49,22 +55,10 @@ class Envelope : public Generator
//! Return the current envelope \e state (0 = at target, 1 otherwise).
virtual int getState(void) const;
- //! Return one envelope output value.
- virtual StkFloat tick(void);
-
- //! Compute \e vectorSize outputs and return them in \e vector.
- virtual StkFloat *tick( StkFloat *vector, unsigned int vectorSize );
-
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- virtual StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
protected:
+
+ virtual StkFloat computeSample( void );
+
StkFloat value_;
StkFloat target_;
StkFloat rate_;
diff --git a/include/FM.h b/include/FM.h
index d09d2fa..f0c17a2 100644
--- a/include/FM.h
+++ b/include/FM.h
@@ -19,7 +19,7 @@
type who should worry about this (making
money) worry away.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -29,6 +29,7 @@
#include "Instrmnt.h"
#include "ADSR.h"
#include "WaveLoop.h"
+#include "SineWave.h"
#include "TwoZero.h"
class FM : public Instrmnt
@@ -79,28 +80,16 @@ class FM : public Instrmnt
//! Stop a note with the given amplitude (speed of decay).
void noteOff(StkFloat amplitude);
- //! Pure virtual function ... must be defined in subclasses.
- virtual StkFloat tick() = 0;
-
- //! Computer \e vectorSize outputs and return them in \e vector.
- virtual StkFloat *tick(StkFloat *vector, unsigned int vectorSize) = 0;
-
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- virtual StkFrames& tick( StkFrames& frames, unsigned int channel = 1 ) = 0;
-
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
virtual void controlChange(int number, StkFloat value);
- protected:
+ protected:
+
+ virtual StkFloat computeSample( void ) = 0;
+
std::vector adsr_;
std::vector waves_;
- WaveLoop *vibrato_;
+ SineWave vibrato_;
TwoZero twozero_;
unsigned int nOperators_;
StkFloat baseFrequency_;
diff --git a/include/FMVoices.h b/include/FMVoices.h
index e771e3d..02d782d 100644
--- a/include/FMVoices.h
+++ b/include/FMVoices.h
@@ -26,7 +26,7 @@
type who should worry about this (making
money) worry away.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -53,25 +53,13 @@ class FMVoices : public FM
//! Start a note with the given frequency and amplitude.
void noteOn(StkFloat frequency, StkFloat amplitude);
- //! Compute one output sample.
- StkFloat tick();
-
- //! Computer \e vectorSize outputs and return them in \e vector.
- StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
-
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
virtual void controlChange(int number, StkFloat value);
protected:
+
+ StkFloat computeSample( void );
+
int currentVowel_;
StkFloat tilt_[3];
StkFloat mods_[3];
diff --git a/include/FileRead.h b/include/FileRead.h
new file mode 100644
index 0000000..04fa5a2
--- /dev/null
+++ b/include/FileRead.h
@@ -0,0 +1,124 @@
+/***************************************************/
+/*! \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-, 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 is assumed to be 44100 Hz.
+
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
+*/
+/***************************************************/
+
+#ifndef STK_FILEREAD_H
+#define STK_FILEREAD_H
+
+#include "Stk.h"
+
+class FileRead : public Stk
+{
+public:
+ //! Default constructor.
+ FileRead();
+
+ //! 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.
+ */
+ FileRead( std::string fileName, bool typeRaw = false );
+
+ //! Class destructor.
+ ~FileRead();
+
+ //! 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. An optional parameter is
+ provided to specify whether the input file is of type STK RAW
+ (default = false).
+ */
+ void open( std::string fileName, bool typeRaw = false );
+
+ //! 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 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 );
+
+ // 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 );
+
+ FILE *fd_;
+ bool byteswap_;
+ bool wavFile_;
+ unsigned long fileSize_;
+ unsigned long dataOffset_;
+ unsigned int channels_;
+ StkFormat dataType_;
+ StkFloat fileRate_;
+};
+
+#endif
diff --git a/include/FileWrite.h b/include/FileWrite.h
new file mode 100644
index 0000000..2401ea1
--- /dev/null
+++ b/include/FileWrite.h
@@ -0,0 +1,112 @@
+/***************************************************/
+/*! \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-, 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 - 2005.
+*/
+/***************************************************/
+
+#ifndef STK_FILEWRITE_H
+#define STK_FILEWRITE_H
+
+#include "Stk.h"
+
+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();
+
+ //! 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( const char *fileName );
+
+ // Write WAV file header.
+ bool setWavFile( const char *fileName );
+
+ // Close WAV file, updating the header.
+ void closeWavFile( void );
+
+ // Write SND (AU) file header.
+ bool setSndFile( const char *fileName );
+
+ // Close SND file, updating the header.
+ void closeSndFile( void );
+
+ // Write AIFF file header.
+ bool setAifFile( const char *fileName );
+
+ // Close AIFF file, updating the header.
+ void closeAifFile( void );
+
+ // Write MAT-file header.
+ bool setMatFile( const char *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_;
+
+};
+
+#endif
diff --git a/include/FileWvIn.h b/include/FileWvIn.h
new file mode 100644
index 0000000..ab5a661
--- /dev/null
+++ b/include/FileWvIn.h
@@ -0,0 +1,143 @@
+/***************************************************/
+/*! \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() methods, which return samples produced by averaging
+ across sample frames, from the tickFrame() methods, which return
+ references to multi-channel sample frames.
+
+ 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 zero-valued data 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 - 2005.
+*/
+/***************************************************/
+
+#ifndef STK_FILEWVIN_H
+#define STK_FILEWVIN_H
+
+#include "WvIn.h"
+#include "FileRead.h"
+
+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.
+ virtual ~FileWvIn();
+
+ //! 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 );
+
+ //! Clear outputs and reset time (file) pointer to zero.
+ void reset( void );
+
+ //! Normalize data to a maximum of +-1.0.
+ /*!
+ This function has no effect when data is incrementally loaded
+ from disk.
+ */
+ void normalize( void );
+
+ //! Normalize data to a maximum of \e +-peak.
+ /*!
+ This function has no effect when data is incrementally loaded
+ from disk.
+ */
+ void normalize( StkFloat 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(); };
+
+ //! 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.
+ */
+ 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; };
+
+ StkFloat lastOut( void ) const;
+
+protected:
+
+ virtual void computeFrame( void );
+
+ FileRead file_;
+ bool finished_;
+ bool interpolate_;
+ bool normalizing_;
+ bool chunking_;
+ StkFloat time_;
+ StkFloat rate_;
+ unsigned long chunkThreshold_;
+ unsigned long chunkSize_;
+ long chunkPointer_;
+
+};
+
+#endif
diff --git a/include/FileWvOut.h b/include/FileWvOut.h
new file mode 100644
index 0000000..1f82fb0
--- /dev/null
+++ b/include/FileWvOut.h
@@ -0,0 +1,87 @@
+/***************************************************/
+/*! \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()
+ methods, which output single samples to all channels in a sample
+ frame, from the tickFrame() methods, which take a pointer or
+ reference to multi-channel sample 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 - 2005.
+*/
+/***************************************************/
+
+#ifndef STK_FILEWVOUT_H
+#define STK_FILEWVOUT_H
+
+#include "WvOut.h"
+#include "FileWrite.h"
+
+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 );
+
+ protected:
+
+ void computeSample( const StkFloat sample );
+
+ void computeFrames( const StkFrames& frames );
+
+ void incrementFrame( void );
+
+ FileWrite file_;
+ unsigned int bufferFrames_;
+ unsigned int bufferIndex_;
+ unsigned int iData_;
+
+};
+
+#endif
diff --git a/include/Filter.h b/include/Filter.h
index 365acec..f10dc1e 100644
--- a/include/Filter.h
+++ b/include/Filter.h
@@ -2,7 +2,7 @@
/*! \class Filter
\brief STK filter class.
- This class implements a generic structure which
+ This class implements a generic structure that
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
@@ -23,7 +23,7 @@
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 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -32,7 +32,6 @@
#include "Stk.h"
#include
-#include
class Filter : public Stk
{
@@ -58,19 +57,20 @@ public:
An StkError can be thrown if either of the coefficient vector
sizes is zero, 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]. The internal state of the filter is cleared.
+ a[0]. The internal state of the filter is not cleared unless the
+ \e clearState flag is \c true.
*/
- void setCoefficients( std::vector &bCoefficients, std::vector &aCoefficients );
+ void setCoefficients( std::vector &bCoefficients, std::vector &aCoefficients, bool clearState = false );
//! Set numerator coefficients.
/*!
An StkError can be thrown if coefficient vector is empty. Any
previously set denominator coefficients are left unaffected. Note
that the default constructor sets the single denominator
- coefficient a[0] to 1.0. The internal state of the filter is
- cleared.
+ coefficient a[0] to 1.0. The internal state of the filter is not
+ cleared unless the \e clearState flag is \c true.
*/
- void setNumerator( std::vector &bCoefficients );
+ void setNumerator( std::vector &bCoefficients, bool clearState = false );
//! Set denominator coefficients.
/*!
@@ -79,9 +79,10 @@ public:
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. The internal state of the filter is cleared.
+ b[0] to 1.0. The internal state of the filter is not cleared
+ unless the \e clearState flag is \c true.
*/
- void setDenominator( std::vector &aCoefficients );
+ void setDenominator( std::vector &aCoefficients, bool clearState = false );
//! Set the filter gain.
/*!
@@ -97,21 +98,19 @@ public:
virtual StkFloat lastOut(void) const;
//! Input one sample to the filter and return one output.
- virtual StkFloat tick(StkFloat sample);
-
- //! Input \e vectorSize samples to the filter and return an equal number of outputs in \e vector.
- virtual StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
+ virtual StkFloat tick( StkFloat input );
//! Take a channel of the StkFrames object as inputs to the filter and replace with corresponding outputs.
/*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
+ The \c channel argument should be zero or greater (the first
+ channel is specified by 0). An StkError will be thrown if the \c
+ channel argument is equal to or greater than the number of
channels in the StkFrames object.
*/
- virtual StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
+ virtual StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
protected:
+
StkFloat gain_;
std::vector b_;
std::vector a_;
diff --git a/include/Flute.h b/include/Flute.h
index abe3bf1..97df13b 100644
--- a/include/Flute.h
+++ b/include/Flute.h
@@ -18,7 +18,7 @@
- Vibrato Gain = 1
- Breath Pressure = 128
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -32,7 +32,7 @@
#include "PoleZero.h"
#include "Noise.h"
#include "ADSR.h"
-#include "WaveLoop.h"
+#include "SineWave.h"
class Flute : public Instrmnt
{
@@ -73,25 +73,13 @@ class Flute : public Instrmnt
//! Stop a note with the given amplitude (speed of decay).
void noteOff(StkFloat amplitude);
- //! Compute one output sample.
- StkFloat tick();
-
- //! Computer \e vectorSize outputs and return them in \e vector.
- StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
-
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
void controlChange(int number, StkFloat value);
- protected:
+ protected:
+
+ StkFloat computeSample( void );
+
DelayL jetDelay_;
DelayL boreDelay_;
JetTable jetTable_;
@@ -99,7 +87,7 @@ class Flute : public Instrmnt
PoleZero dcBlock_;
Noise noise_;
ADSR adsr_;
- WaveLoop *vibrato_;
+ SineWave vibrato_;
unsigned long length_;
StkFloat lastFrequency_;
StkFloat maxPressure_;
diff --git a/include/FormSwep.h b/include/FormSwep.h
index 332a8f7..2e74428 100644
--- a/include/FormSwep.h
+++ b/include/FormSwep.h
@@ -8,7 +8,7 @@
It provides methods for controlling the sweep
rate and target frequency.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -56,7 +56,7 @@ class FormSwep : public BiQuad
target values. A sweep rate of 0.0 will produce no
change in resonance parameters.
*/
- void setSweepRate(StkFloat rate);
+ void setSweepRate(StkFloat rate);
//! Set the sweep rate in terms of a time value in seconds.
/*!
@@ -64,24 +64,12 @@ class FormSwep : public BiQuad
given time for the formant parameters to reach
their target values.
*/
- void setSweepTime(StkFloat time);
+ void setSweepTime(StkFloat time);
- //! Input one sample to the filter and return one output.
- StkFloat tick(StkFloat sample);
+ protected:
- //! Input \e vectorSize samples to the filter and return an equal number of outputs in \e vector.
- StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
+ StkFloat computeSample( StkFloat input );
- //! Take a channel of the StkFrames object as inputs to the filter and replace with corresponding outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
- protected:
bool dirty_;
StkFloat frequency_;
StkFloat radius_;
diff --git a/include/Function.h b/include/Function.h
index c58f822..13e6bc7 100644
--- a/include/Function.h
+++ b/include/Function.h
@@ -6,7 +6,7 @@
implement tables or other types of input to output function
mappings.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -27,23 +27,25 @@ class Function : public Stk
//! Return the last output value.
virtual StkFloat lastOut() const { return lastOutput_; };
- //! Abstract tick function ... must be implemented in subclasses.
- virtual StkFloat tick( StkFloat input ) = 0;
-
- //! Take \e vectorSize inputs from \e vector and replace them with corresponding outputs.
- virtual StkFloat *tick( StkFloat *vector, unsigned int vectorSize );
+ //! Take one sample input and compute one sample of output.
+ StkFloat tick( StkFloat input );
//! Take a channel of the StkFrames object as inputs to the function and replace with corresponding outputs.
/*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
+ The \c channel argument should be zero or greater (the first
+ channel is specified by 0). An StkError will be thrown if the \c
+ channel argument is equal to or greater than the number of
channels in the StkFrames object.
*/
- virtual StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
+ virtual StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
protected:
+ // This abstract function must be implemented in all subclasses.
+ // It is used to get around a C++ problem with overloaded virtual
+ // functions.
+ virtual StkFloat computeSample( StkFloat input ) = 0;
+
StkFloat lastOutput_;
};
diff --git a/include/Generator.h b/include/Generator.h
index 212f355..6f82b86 100644
--- a/include/Generator.h
+++ b/include/Generator.h
@@ -3,9 +3,9 @@
\brief STK abstract unit generator parent class.
This class provides common functionality for
- STK unit generator source subclasses.
+ STK unit generator sample-source subclasses.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -18,31 +18,33 @@ class Generator : public Stk
{
public:
//! Class constructor.
- Generator();
+ Generator( void );
//! Class destructor.
- virtual ~Generator();
+ virtual ~Generator( void );
//! Return the last output value.
- virtual StkFloat lastOut() const { return lastOutput_; };
+ virtual StkFloat lastOut( void ) const { return lastOutput_; };
- //! Abstract tick function ... must be implemented in subclasses.
- virtual StkFloat tick( void ) = 0;
-
- //! Compute \e vectorSize outputs and return them in \e vector.
- virtual StkFloat *tick( StkFloat *vector, unsigned int vectorSize );
+ //! Compute one sample and output.
+ StkFloat tick( void );
//! Fill a channel of the StkFrames object with computed outputs.
/*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
+ The \c channel argument should be zero or greater (the first
+ channel is specified by 0). An StkError will be thrown if the \c
+ channel argument is equal to or greater than the number of
channels in the StkFrames object.
*/
- virtual StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
+ StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
protected:
+ // This abstract function must be implemented in all subclasses.
+ // It is used to get around a C++ problem with overloaded virtual
+ // functions.
+ virtual StkFloat computeSample( void ) = 0;
+
StkFloat lastOutput_;
};
diff --git a/include/Granulate.h b/include/Granulate.h
new file mode 100644
index 0000000..8629df0
--- /dev/null
+++ b/include/Granulate.h
@@ -0,0 +1,145 @@
+/***************************************************/
+/*! \class Granulate
+ \brief STK granular synthesis class.
+
+ This class implements a real-time granular synthesis algorithm
+ that operates on an input soundfile. Currently, only monophonic
+ files are supported. Various functions are provided to allow
+ control over voice and grain parameters.
+
+ The functionality of this class is based on the program MacPod by
+ Chris Rolfe and Damian Keller, though there are likely to be a
+ number of differences in the actual implementation.
+
+ by Gary Scavone, 2005.
+*/
+/***************************************************/
+
+#ifndef STK_GRANULATE_H
+#define STK_GRANULATE_H
+
+#include
+#include "Generator.h"
+#include "Envelope.h"
+#include "Noise.h"
+
+class Granulate: public Generator
+{
+ public:
+ //! Default constructor.
+ Granulate( void );
+
+ //! Constructor taking input audio file and number of voices arguments.
+ Granulate( unsigned int nVoices, std::string fileName, bool typeRaw = false );
+
+ //! Class destructor.
+ ~Granulate();
+
+ //! Load a monophonic soundfile to be "granulated".
+ /*!
+ An StkError will be thrown if the file is not found, its format
+ is unknown or unsupported, or the file has more than one channel.
+ */
+ void openFile( std::string fileName, bool typeRaw = false );
+
+ //! Reset the file pointer and all existing grains to the file start.
+ /*!
+ Multiple grains are offset from one another in time by grain
+ duration / nVoices.
+ */
+ void reset();
+
+ //! Set the number of simultaneous grain "voices" to use.
+ /*!
+ Multiple grains are offset from one another in time by grain
+ duration / nVoices. For this reason, it is best to set the grain
+ parameters before calling this function (during initialization).
+ */
+ void setVoices( unsigned int nVoices = 1 );
+
+ //! Set the stretch factor used for grain playback (1 - 1000).
+ /*!
+ Granular synthesis allows for time-stetching without affecting
+ the original pitch of a sound. A stretch factor of 4 will produce
+ a resulting sound of length 4 times the orignal sound. The
+ default parameter of 1 produces no stretching.
+ */
+ void setStretch( unsigned int stretchFactor = 1 );
+
+ //! Set global grain parameters used to determine individual grain settings.
+ /*!
+ Each grain is defined as having a length of \e duration
+ milliseconds which must be greater than zero. For values of \e
+ rampPercent (0 - 100) greater than zero, a linear envelope will be
+ applied to each grain. If \e rampPercent = 100, the resultant
+ grain "window" is triangular while \e rampPercent = 50 produces a
+ trapezoidal window. In addition, each grain can have a time delay
+ of length \e delay and a grain pointer increment of length \e
+ offset, which can be negative, before the next ramp onset (in
+ milliseconds). The actual values calculated for each grain will
+ be randomized by a factor set using the setRandomFactor()
+ function.
+ */
+ void setGrainParameters( unsigned int duration = 30, unsigned int rampPercent = 50,
+ int offset = 0, unsigned int delay = 0 );
+
+ //! This factor is used when setting individual grain parameters (0.0 - 1.0).
+ /*!
+ This random factor is applied when all grain state durations
+ are calculated. If set to 0.0, no randomness occurs. When
+ randomness = 1.0, a grain segment of length \e duration will be
+ randomly augmented by up to +- \e duration seconds (i.e., a 30
+ millisecond length will be augmented by an extra length of up to
+ +30 or -30 milliseconds).
+ */
+ void setRandomFactor( StkFloat randomness = 0.1 );
+
+ enum GrainState {
+ GRAIN_STOPPED,
+ GRAIN_FADEIN,
+ GRAIN_SUSTAIN,
+ GRAIN_FADEOUT
+ };
+
+ protected:
+
+ struct Grain {
+ StkFloat eScaler;
+ StkFloat eRate;
+ unsigned long attackCount;
+ unsigned long sustainCount;
+ unsigned long decayCount;
+ unsigned long delayCount;
+ unsigned long counter;
+ unsigned long pointer;
+ unsigned long startPointer;
+ unsigned int repeats;
+ GrainState state;
+
+ // Default constructor.
+ Grain()
+ :eScaler(0.0), eRate(0.0), attackCount(0), sustainCount(0), decayCount(0),
+ delayCount(0), counter(0), pointer(0), startPointer(0), repeats(0), state(GRAIN_STOPPED) {}
+ };
+
+ StkFloat computeSample( void );
+ void calculateGrain( Granulate::Grain& grain );
+
+ StkFrames data_;
+ std::vector grains_;
+ Noise noise;
+ long gPointer_;
+
+ // Global grain parameters.
+ unsigned int gDuration_;
+ unsigned int gRampPercent_;
+ unsigned int gDelay_;
+ unsigned int gStretch_;
+ unsigned int stretchCounter_;
+ int gOffset_;
+ StkFloat gRandomFactor_;
+ StkFloat gain_;
+
+};
+
+#endif
diff --git a/include/HevyMetl.h b/include/HevyMetl.h
index 1495cd5..80030a7 100644
--- a/include/HevyMetl.h
+++ b/include/HevyMetl.h
@@ -24,7 +24,7 @@
type who should worry about this (making
money) worry away.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -48,20 +48,9 @@ class HevyMetl : public FM
//! Start a note with the given frequency and amplitude.
void noteOn(StkFloat frequency, StkFloat amplitude);
- //! Compute one output sample.
- StkFloat tick();
+ protected:
- //! Computer \e vectorSize outputs and return them in \e vector.
- StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
-
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
+ StkFloat computeSample( void );
};
#endif
diff --git a/include/InetWvIn.h b/include/InetWvIn.h
new file mode 100644
index 0000000..5ff944b
--- /dev/null
+++ b/include/InetWvIn.h
@@ -0,0 +1,103 @@
+/***************************************************/
+/*! \class InetWvIn
+ \brief STK internet streaming input class.
+
+ This Wvin subclass reads streamed audio data over a network via a
+ TCP or UDP socket connection. The data is assumed in big-endian,
+ or network, byte order. Only a single socket connection is
+ supported.
+
+ InetWvIn supports multi-channel data. It is important to
+ distinguish the tick() methods, which return samples produced by
+ averaging across sample frames, from the tickFrame() methods,
+ which return references or pointers to multi-channel sample
+ frames.
+
+ This class implements a socket server. When using the TCP
+ protocol, the server "listens" for a single remote connection
+ within the InetWvIn::start() function. For the UDP protocol, no
+ attempt is made to verify packet delivery or order. The default
+ data type for the incoming stream is signed 16-bit integers,
+ though any of the defined StkFormats are permissible.
+
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
+*/
+/***************************************************/
+
+#ifndef STK_INETWVIN_H
+#define STK_INETWVIN_H
+
+#include "WvIn.h"
+#include "TcpServer.h"
+#include "UdpSocket.h"
+#include "Thread.h"
+#include "Mutex.h"
+
+typedef struct {
+ bool finished;
+ void *object;
+} ThreadInfo;
+
+class InetWvIn : public WvIn
+{
+public:
+ //! Default constructor.
+ /*!
+ An StkError will be thrown if an error occurs while initializing the input thread.
+ */
+ InetWvIn( unsigned long bufferFrames = 1024, unsigned int nBuffers = 8 );
+
+ //! Class destructor.
+ ~InetWvIn();
+
+ //! Wait for a (new) socket connection with specified protocol, port, data channels and format.
+ /*!
+ For the UDP protocol, this function will create a socket
+ instance and return. For the TCP protocol, this function will
+ block until a connection is established. An StkError will be
+ thrown if a socket error occurs or an invalid function argument is
+ provided.
+ */
+ void listen( int port = 2006, unsigned int nChannels = 1,
+ Stk::StkFormat format = STK_SINT16,
+ Socket::ProtocolType protocol = Socket::PROTO_TCP );
+
+ //! Returns true is an input connection exists or input data remains in the queue.
+ /*!
+ This method will not return false after an input connection has been closed until
+ all buffered input data has been read out.
+ */
+ bool isConnected( void );
+
+ // Called by the thread routine to receive data via the socket connection
+ // and fill the socket buffer. This is not intended for general use but
+ // had to be made public for access from the thread.
+ void receive( void );
+
+protected:
+
+ // Read buffered socket data into the data buffer ... will block if none available.
+ int readData( void );
+
+ void computeFrame( void );
+
+ Socket *soket_;
+ Thread thread_;
+ Mutex mutex_;
+ char *buffer_;
+ unsigned long bufferFrames_;
+ unsigned long bufferBytes_;
+ unsigned long bytesFilled_;
+ unsigned int nBuffers_;
+ unsigned long writePoint_;
+ unsigned long readPoint_;
+ long bufferCounter_;
+ int dataBytes_;
+ bool connected_;
+ int fd_;
+ ThreadInfo threadInfo_;
+ Stk::StkFormat dataType_;
+
+};
+
+#endif
diff --git a/include/InetWvOut.h b/include/InetWvOut.h
new file mode 100644
index 0000000..964c8cb
--- /dev/null
+++ b/include/InetWvOut.h
@@ -0,0 +1,77 @@
+/***************************************************/
+/*! \class InetWvOut
+ \brief STK internet streaming output class.
+
+ This WvOut subclass can stream data over a network via a TCP or
+ UDP socket connection. The data is converted to big-endian byte
+ order, if necessary, before being transmitted.
+
+ InetWvOut supports multi-channel data. It is important to
+ distinguish the tick() methods, which output single samples to all
+ channels in a sample frame, from the tickFrame() method, which
+ takes a reference to multi-channel sample frame data.
+
+ This class connects to a socket server, the port and IP address of
+ which must be specified as constructor arguments. The default
+ data type is signed 16-bit integers but any of the defined
+ StkFormats are permissible.
+
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
+*/
+/***************************************************/
+
+#ifndef STK_INETWVOUT_H
+#define STK_INETWVOUT_H
+
+#include "WvOut.h"
+#include "Socket.h"
+
+class InetWvOut : public WvOut
+{
+ public:
+ //! Default constructor ... the socket is not instantiated.
+ InetWvOut( unsigned long packetFrames = 1024 );
+
+ //! Overloaded constructor which opens a network connection during instantiation.
+ /*!
+ An StkError is thrown if a socket error occurs or an invalid argument is specified.
+ */
+ InetWvOut( int port, Socket::ProtocolType protocol = Socket::PROTO_TCP,
+ std::string hostname = "localhost", unsigned int nChannels = 1, Stk::StkFormat format = STK_SINT16,
+ unsigned long packetFrames = 1024 );
+
+ //! Class destructor.
+ ~InetWvOut();
+
+ //! Connect to the specified host and port and prepare to stream \e nChannels of data in the given data format.
+ /*!
+ An StkError is thrown if a socket error occurs or an invalid argument is specified.
+ */
+ void connect( int port, Socket::ProtocolType protocol = Socket::PROTO_TCP,
+ std::string hostname = "localhost", unsigned int nChannels = 1, Stk::StkFormat format = STK_SINT16 );
+
+ //! If a connection is open, write out remaining samples in the queue and then disconnect.
+ void disconnect(void);
+
+ protected:
+
+ void computeSample( const StkFloat sample );
+
+ void computeFrames( const StkFrames& frames );
+
+ void incrementFrame( void );
+
+ // Write a buffer of length frames via the socket connection.
+ void writeData( unsigned long frames );
+
+ char *buffer_;
+ Socket *soket_;
+ unsigned long bufferFrames_;
+ unsigned long bufferBytes_;
+ unsigned long bufferIndex_;
+ unsigned long iData_;
+ unsigned int dataBytes_;
+ Stk::StkFormat dataType_;
+};
+
+#endif
diff --git a/include/Instrmnt.h b/include/Instrmnt.h
index e710e33..e3a66e9 100644
--- a/include/Instrmnt.h
+++ b/include/Instrmnt.h
@@ -5,7 +5,7 @@
This class provides a common interface for
all STK instruments.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -41,26 +41,29 @@ class Instrmnt : public Stk
//! Return the last right output value.
StkFloat lastOutRight() const;
- //! Compute one output sample.
- virtual StkFloat tick() = 0;
-
- //! Computer \e vectorSize outputs and return them in \e vector.
- virtual StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
+ //! Compute one sample and output.
+ StkFloat tick( void );
//! Fill a channel of the StkFrames object with computed outputs.
/*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
+ The \c channel argument should be zero or greater (the first
+ channel is specified by 0). An StkError will be thrown if the \c
+ channel argument is equal to or greater than the number of
channels in the StkFrames object.
*/
- virtual StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
+ StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
virtual void controlChange(int number, StkFloat value);
- protected:
- StkFloat lastOutput_;
+ protected:
+
+ // This abstract function must be implemented in all subclasses.
+ // It is used to get around a C++ problem with overloaded virtual
+ // functions.
+ virtual StkFloat computeSample( void ) = 0;
+
+ StkFloat lastOutput_;
};
diff --git a/include/JCRev.h b/include/JCRev.h
index 312002c..397d21e 100644
--- a/include/JCRev.h
+++ b/include/JCRev.h
@@ -10,7 +10,7 @@
filters, and two decorrelation delay lines in
parallel at the output.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -35,22 +35,10 @@ class JCRev : public Effect
//! Set the reverberation T60 decay time.
void setT60( StkFloat T60 );
- //! Compute one output sample.
- StkFloat tick(StkFloat input);
-
- //! Take \e vectorSize inputs, compute the same number of outputs and return them in \e vector.
- StkFloat *tick( StkFloat *vector, unsigned int vectorSize );
-
- //! Take a channel of the StkFrames object as inputs to the effect and replace with corresponding outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
protected:
+
+ StkFloat computeSample( StkFloat input );
+
Delay allpassDelays_[3];
Delay combDelays_[4];
Delay outLeftDelay_;
diff --git a/include/JetTable.h b/include/JetTable.h
index 15c9515..c527c98 100644
--- a/include/JetTable.h
+++ b/include/JetTable.h
@@ -9,7 +9,7 @@
Consult Fletcher and Rossing, Karjalainen,
Cook, and others for more information.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -27,22 +27,9 @@ public:
//! Class destructor.
~JetTable();
- //! Return the function value for \e input.
- StkFloat tick(StkFloat input);
+protected:
- //! Take \e vectorSize inputs from \e vector and replace them with corresponding outputs.
- StkFloat *tick( StkFloat *vector, unsigned int vectorSize );
-
- //! Take a channel of the StkFrames object as inputs to the function and replace with corresponding outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
-protected:
+ StkFloat computeSample( StkFloat input );
};
diff --git a/include/Mandolin.h b/include/Mandolin.h
index f628612..ce62301 100644
--- a/include/Mandolin.h
+++ b/include/Mandolin.h
@@ -23,7 +23,7 @@
- String Detuning = 1
- Microphone Position = 128
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -31,7 +31,7 @@
#define STK_MANDOLIN_H
#include "PluckTwo.h"
-#include "WvIn.h"
+#include "FileWvIn.h"
class Mandolin : public PluckTwo
{
@@ -54,29 +54,17 @@ class Mandolin : public PluckTwo
//! Set the body size (a value of 1.0 produces the "default" size).
void setBodySize(StkFloat size);
- //! Compute one output sample.
- StkFloat tick();
-
- //! Computer \e vectorSize outputs and return them in \e vector.
- StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
-
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
void controlChange(int number, StkFloat value);
- protected:
- WvIn *soundfile_[12];
- int mic_;
- long dampTime_;
- bool waveDone_;
+ protected:
+
+ StkFloat computeSample( void );
+
+ FileWvIn *soundfile_[12];
+ int mic_;
+ long dampTime_;
+ bool waveDone_;
};
#endif
diff --git a/include/Mesh2D.h b/include/Mesh2D.h
index 43ac3b1..e580367 100644
--- a/include/Mesh2D.h
+++ b/include/Mesh2D.h
@@ -66,29 +66,16 @@ class Mesh2D : public Instrmnt
//! Calculate and return the signal energy stored in the mesh.
StkFloat energy();
- //! Compute one output sample, without adding energy to the mesh.
- StkFloat tick();
-
//! Input a sample to the mesh and compute one output sample.
- StkFloat tick(StkFloat input);
-
- //! Computer \e vectorSize outputs and return them in \e vector.
- StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
-
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
+ StkFloat inputTick( StkFloat input );
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
void controlChange(int number, StkFloat value);
protected:
+ StkFloat computeSample( void );
+
StkFloat tick0();
StkFloat tick1();
void clearMesh();
diff --git a/include/Messager.h b/include/Messager.h
index 8d37b5b..cf3b087 100644
--- a/include/Messager.h
+++ b/include/Messager.h
@@ -28,7 +28,7 @@
This class is primarily for use in STK example programs but it is
generic enough to work in many other contexts.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -45,7 +45,7 @@ const int DEFAULT_QUEUE_LIMIT = 200;
#include "Mutex.h"
#include "Thread.h"
-#include "Socket.h"
+#include "TcpServer.h"
#include "RtMidi.h"
extern "C" THREAD_RETURN THREAD_TYPE stdinHandler(void * ptr);
@@ -69,7 +69,7 @@ class Messager : public Stk
#if defined(__STK_REALTIME__)
Mutex mutex;
RtMidiIn *midi;
- Socket *socket;
+ TcpServer *socket;
std::vector fd;
fd_set mask;
#endif
diff --git a/include/Modal.h b/include/Modal.h
index 413ed58..fdc7b2a 100644
--- a/include/Modal.h
+++ b/include/Modal.h
@@ -7,7 +7,7 @@
(non-sweeping BiQuad filters), where N is set
during instantiation.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -17,6 +17,7 @@
#include "Instrmnt.h"
#include "Envelope.h"
#include "WaveLoop.h"
+#include "SineWave.h"
#include "BiQuad.h"
#include "OnePole.h"
@@ -62,30 +63,18 @@ public:
//! Stop a note with the given amplitude (speed of decay).
void noteOff(StkFloat amplitude);
- //! Compute one output sample.
- virtual StkFloat tick();
-
- //! Computer \e vectorSize outputs and return them in \e vector.
- virtual StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
-
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- virtual StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
virtual void controlChange(int number, StkFloat value) = 0;
-protected:
+protected:
+
+ StkFloat computeSample( void );
+
Envelope envelope_;
- WvIn *wave_;
+ FileWvIn *wave_;
BiQuad **filters_;
OnePole onepole_;
- WaveLoop *vibrato_;
+ SineWave vibrato_;
unsigned int nModes_;
std::vector ratios_;
diff --git a/include/ModalBar.h b/include/ModalBar.h
index 56677fa..bea5ed8 100644
--- a/include/ModalBar.h
+++ b/include/ModalBar.h
@@ -24,7 +24,7 @@
- Two Fixed = 7
- Clump = 8
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
diff --git a/include/Modulate.h b/include/Modulate.h
index 092c0a0..d47d301 100644
--- a/include/Modulate.h
+++ b/include/Modulate.h
@@ -6,7 +6,7 @@
modulations to give a nice, natural human
modulation function.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -14,7 +14,7 @@
#define STK_MODULATE_H
#include "Generator.h"
-#include "WaveLoop.h"
+#include "SineWave.h"
#include "SubNoise.h"
#include "OnePole.h"
@@ -42,23 +42,11 @@ class Modulate : public Generator
//! Set the random modulation gain.
void setRandomGain(StkFloat gain);
- //! Compute one output sample.
- StkFloat tick();
-
- //! Compute \e vectorSize outputs and return them in \e vector.
- StkFloat *tick( StkFloat *vector, unsigned int vectorSize );
-
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
protected:
- WaveLoop *vibrato_;
+
+ StkFloat computeSample( void );
+
+ SineWave vibrato_;
SubNoise noise_;
OnePole filter_;
StkFloat vibratoGain_;
diff --git a/include/Moog.h b/include/Moog.h
index e7bcbf2..e72ce3d 100644
--- a/include/Moog.h
+++ b/include/Moog.h
@@ -14,7 +14,7 @@
- Vibrato Gain = 1
- Gain = 128
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -48,25 +48,13 @@ class Moog : public Sampler
//! Set the modulation (vibrato) depth.
void setModulationDepth(StkFloat mDepth);
- //! Compute one output sample.
- StkFloat tick();
-
- //! Computer \e vectorSize outputs and return them in \e vector.
- StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
-
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
void controlChange(int number, StkFloat value);
protected:
+
+ StkFloat computeSample( void );
+
FormSwep filters_[2];
StkFloat modDepth_;
StkFloat filterQ_;
diff --git a/include/Mutex.h b/include/Mutex.h
index e072718..6757f44 100644
--- a/include/Mutex.h
+++ b/include/Mutex.h
@@ -7,7 +7,7 @@
systems, the pthread library is used. Under
Windows, critical sections are used.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
diff --git a/include/NRev.h b/include/NRev.h
index 731688b..b594b71 100644
--- a/include/NRev.h
+++ b/include/NRev.h
@@ -12,7 +12,7 @@
filters in parallel with corresponding right
and left outputs.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -37,22 +37,10 @@ class NRev : public Effect
//! Set the reverberation T60 decay time.
void setT60( StkFloat T60 );
- //! Compute one output sample.
- StkFloat tick(StkFloat input);
+ protected:
- //! Take \e vectorSize inputs, compute the same number of outputs and return them in \e vector.
- StkFloat *tick( StkFloat *vector, unsigned int vectorSize );
+ StkFloat computeSample( StkFloat input );
- //! Take a channel of the StkFrames object as inputs to the effect and replace with corresponding outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
- protected:
Delay allpassDelays_[8];
Delay combDelays_[6];
StkFloat allpassCoefficient_;
diff --git a/include/Noise.h b/include/Noise.h
index 881b49d..f87eb93 100644
--- a/include/Noise.h
+++ b/include/Noise.h
@@ -6,7 +6,7 @@
C rand() function. The quality of the rand()
function varies from one OS to another.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -39,23 +39,10 @@ public:
*/
void setSeed( unsigned int seed = 0 );
- //! Return a random number between -1.0 and 1.0 using rand().
- virtual StkFloat tick();
-
- //! Compute \e vectorSize outputs and return them in \e vector.
- virtual StkFloat *tick( StkFloat *vector, unsigned int vectorSize );
-
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- virtual StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
protected:
+ virtual StkFloat computeSample( void );
+
};
#endif
diff --git a/include/OnePole.h b/include/OnePole.h
index 2252ca4..7ed5dca 100644
--- a/include/OnePole.h
+++ b/include/OnePole.h
@@ -8,7 +8,7 @@
the real axis of the z-plane while maintaining
a constant peak filter gain.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -25,7 +25,7 @@ public:
OnePole();
//! Overloaded constructor which sets the pole position during instantiation.
- OnePole(StkFloat thePole);
+ OnePole( StkFloat thePole );
//! Class destructor.
~OnePole();
@@ -65,17 +65,14 @@ public:
//! Input one sample to the filter and return one output.
StkFloat tick(StkFloat sample);
- //! Input \e vectorSize samples to the filter and return an equal number of outputs in \e vector.
- StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
-
//! Take a channel of the StkFrames object as inputs to the filter and replace with corresponding outputs.
/*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
+ The \c channel argument should be zero or greater (the first
+ channel is specified by 0). An StkError will be thrown if the \c
+ channel argument is equal to or greater than the number of
channels in the StkFrames object.
*/
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
+ StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
};
diff --git a/include/OneZero.h b/include/OneZero.h
index 92d69b0..d34eb30 100644
--- a/include/OneZero.h
+++ b/include/OneZero.h
@@ -8,7 +8,7 @@
along the real axis of the z-plane while
maintaining a constant filter gain.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -65,17 +65,14 @@ class OneZero : protected Filter
//! Input one sample to the filter and return one output.
StkFloat tick(StkFloat sample);
- //! Input \e vectorSize samples to the filter and return an equal number of outputs in \e vector.
- StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
-
//! Take a channel of the StkFrames object as inputs to the filter and replace with corresponding outputs.
/*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
+ The \c channel argument should be zero or greater (the first
+ channel is specified by 0). An StkError will be thrown if the \c
+ channel argument is equal to or greater than the number of
channels in the StkFrames object.
*/
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
+ StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
};
diff --git a/include/PRCRev.h b/include/PRCRev.h
index 568e353..8760496 100644
--- a/include/PRCRev.h
+++ b/include/PRCRev.h
@@ -10,7 +10,7 @@
two series allpass units and two parallel comb
filters.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -35,22 +35,10 @@ public:
//! Set the reverberation T60 decay time.
void setT60( StkFloat T60 );
- //! Compute one output sample.
- StkFloat tick(StkFloat input);
+protected:
- //! Take \e vectorSize inputs, compute the same number of outputs and return them in \e vector.
- StkFloat *tick( StkFloat *vector, unsigned int vectorSize );
+ StkFloat computeSample( StkFloat input );
- //! Take a channel of the StkFrames object as inputs to the effect and replace with corresponding outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
-protected:
Delay allpassDelays_[2];
Delay combDelays_[2];
StkFloat allpassCoefficient_;
diff --git a/include/PercFlut.h b/include/PercFlut.h
index 7eb0ccb..c573757 100644
--- a/include/PercFlut.h
+++ b/include/PercFlut.h
@@ -22,7 +22,7 @@
type who should worry about this (making
money) worry away.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -49,20 +49,9 @@ class PercFlut : public FM
//! Start a note with the given frequency and amplitude.
void noteOn(StkFloat frequency, StkFloat amplitude);
- //! Compute one output sample.
- StkFloat tick();
+ protected:
- //! Computer \e vectorSize outputs and return them in \e vector.
- StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
-
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
+ StkFloat computeSample( void );
};
#endif
diff --git a/include/Phonemes.h b/include/Phonemes.h
index 0dd0463..f5dc2de 100644
--- a/include/Phonemes.h
+++ b/include/Phonemes.h
@@ -6,7 +6,7 @@
set of 32 static phoneme formant parameters
and provide access to those values.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
diff --git a/include/PitShift.h b/include/PitShift.h
index 78bd410..45dd830 100644
--- a/include/PitShift.h
+++ b/include/PitShift.h
@@ -5,7 +5,7 @@
This class implements a simple pitch shifter
using delay lines.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -30,22 +30,10 @@ class PitShift : public Effect
//! Set the pitch shift factor (1.0 produces no shift).
void setShift(StkFloat shift);
- //! Compute one output sample.
- StkFloat tick(StkFloat input);
+ protected:
- //! Take \e vectorSize inputs, compute the same number of outputs and return them in \e vector.
- StkFloat *tick( StkFloat *vector, unsigned int vectorSize );
+ StkFloat computeSample( StkFloat input );
- //! Take a channel of the StkFrames object as inputs to the effect and replace with corresponding outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
- protected:
DelayL delayLine_[2];
StkFloat delay_[2];
StkFloat env_[2];
diff --git a/include/PluckTwo.h b/include/PluckTwo.h
index 49fc955..dfa3efe 100644
--- a/include/PluckTwo.h
+++ b/include/PluckTwo.h
@@ -14,7 +14,7 @@
use possibly subject to patents held by
Stanford University, Yamaha, and others.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -61,36 +61,24 @@ class PluckTwo : public Instrmnt
//! Stop a note with the given amplitude (speed of decay).
virtual void noteOff(StkFloat amplitude);
- //! Virtual (abstract) tick function is implemented by subclasses.
- virtual StkFloat tick() = 0;
+ protected:
- //! Computer \e vectorSize outputs and return them in \e vector.
- virtual StkFloat *tick(StkFloat *vector, unsigned int vectorSize) = 0;
+ virtual StkFloat computeSample( void ) = 0;
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- virtual StkFrames& tick( StkFrames& frames, unsigned int channel = 1 ) = 0;
+ DelayA delayLine_;
+ DelayA delayLine2_;
+ DelayL combDelay_;
+ OneZero filter_;
+ OneZero filter2_;
- protected:
- DelayA delayLine_;
- DelayA delayLine2_;
- DelayL combDelay_;
- OneZero filter_;
- OneZero filter2_;
-
- unsigned long length_;
- StkFloat loopGain_;
- StkFloat baseLoopGain_;
- StkFloat lastFrequency_;
- StkFloat lastLength_;
- StkFloat detuning_;
- StkFloat pluckAmplitude_;
- StkFloat pluckPosition_;
+ unsigned long length_;
+ StkFloat loopGain_;
+ StkFloat baseLoopGain_;
+ StkFloat lastFrequency_;
+ StkFloat lastLength_;
+ StkFloat detuning_;
+ StkFloat pluckAmplitude_;
+ StkFloat pluckPosition_;
};
diff --git a/include/Plucked.h b/include/Plucked.h
index 57290db..251a30e 100644
--- a/include/Plucked.h
+++ b/include/Plucked.h
@@ -13,7 +13,7 @@
Stanford, bearing the names of Karplus and/or
Strong.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -50,22 +50,10 @@ class Plucked : public Instrmnt
//! Stop a note with the given amplitude (speed of decay).
virtual void noteOff(StkFloat amplitude);
- //! Compute one output sample.
- virtual StkFloat tick();
-
- //! Computer \e vectorSize outputs and return them in \e vector.
- virtual StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
-
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- virtual StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
protected:
+
+ StkFloat computeSample( void );
+
DelayA delayLine_;
OneZero loopFilter_;
OnePole pickFilter_;
diff --git a/include/PoleZero.h b/include/PoleZero.h
index ba35e6d..989076c 100644
--- a/include/PoleZero.h
+++ b/include/PoleZero.h
@@ -8,7 +8,7 @@
filter with a given coefficient. Another
method is provided to create a DC blocking filter.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -61,28 +61,25 @@ class PoleZero : protected Filter
The gain is applied at the filter input and does not affect the
coefficient values. The default gain value is 1.0.
*/
- void setGain(StkFloat gain);
+ void setGain( StkFloat gain );
//! Return the current filter gain.
- StkFloat getGain(void) const;
+ StkFloat getGain( void ) const;
//! Return the last computed output value.
- StkFloat lastOut(void) const;
+ StkFloat lastOut( void ) const;
//! Input one sample to the filter and return one output.
- StkFloat tick(StkFloat sample);
-
- //! Input \e vectorSize samples to the filter and return an equal number of outputs in \e vector.
- StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
+ StkFloat tick( StkFloat sample );
//! Take a channel of the StkFrames object as inputs to the filter and replace with corresponding outputs.
/*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
+ The \c channel argument should be zero or greater (the first
+ channel is specified by 0). An StkError will be thrown if the \c
+ channel argument is equal to or greater than the number of
channels in the StkFrames object.
*/
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
+ StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
};
diff --git a/include/ReedTable.h b/include/ReedTable.h
index c090bd3..a01ea2b 100644
--- a/include/ReedTable.h
+++ b/include/ReedTable.h
@@ -13,7 +13,7 @@
Smith (1986), Hirschman, Cook, Scavone, and
others for more information.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -47,26 +47,10 @@ public:
*/
void setSlope(StkFloat slope);
- //! Return the function value for \e input.
- /*!
- The function input represents the differential
- pressure across the reeds.
- */
- StkFloat tick(StkFloat input);
+protected:
- //! Take \e vectorSize inputs from \e vector and replace them with corresponding outputs.
- StkFloat *tick( StkFloat *vector, unsigned int vectorSize );
+ StkFloat computeSample( StkFloat input );
- //! Take a channel of the StkFrames object as inputs to the function and replace with corresponding outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
-protected:
StkFloat offset_;
StkFloat slope_;
diff --git a/include/Resonate.h b/include/Resonate.h
index 8922a9d..2e51e33 100644
--- a/include/Resonate.h
+++ b/include/Resonate.h
@@ -13,7 +13,7 @@
- Zero Radii = 1
- Envelope Gain = 128
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -58,25 +58,13 @@ class Resonate : public Instrmnt
//! Stop a note with the given amplitude (speed of decay).
void noteOff(StkFloat amplitude);
- //! Compute one output sample.
- StkFloat tick();
-
- //! Computer \e vectorSize outputs and return them in \e vector.
- StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
-
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
void controlChange(int number, StkFloat value);
- protected:
+ protected:
+
+ StkFloat computeSample( void );
+
ADSR adsr_;
BiQuad filter_;
Noise noise_;
diff --git a/include/Rhodey.h b/include/Rhodey.h
index 05f7b51..3960554 100644
--- a/include/Rhodey.h
+++ b/include/Rhodey.h
@@ -26,7 +26,7 @@
type who should worry about this (making
money) worry away.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -53,20 +53,9 @@ class Rhodey : public FM
//! Start a note with the given frequency and amplitude.
void noteOn(StkFloat frequency, StkFloat amplitude);
- //! Compute one output sample.
- StkFloat tick();
+ protected:
- //! Computer \e vectorSize outputs and return them in \e vector.
- StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
-
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
+ StkFloat computeSample( void );
};
#endif
diff --git a/include/RtAudio.h b/include/RtAudio.h
index 98fce3e..e26f81d 100644
--- a/include/RtAudio.h
+++ b/include/RtAudio.h
@@ -10,7 +10,7 @@
RtAudio WWW site: http://music.mcgill.ca/~gary/rtaudio/
RtAudio: realtime audio i/o C++ classes
- Copyright (c) 2001-2004 Gary P. Scavone
+ Copyright (c) 2001-2005 Gary P. Scavone
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files
@@ -37,7 +37,7 @@
*/
/************************************************************************/
-// RtAudio: Version 3.0.2, pre-release for STK 4.2.0
+// RtAudio: Version 3.0.2 (14 October 2005)
#ifndef __RTAUDIO_H
#define __RTAUDIO_H
@@ -676,6 +676,53 @@ public:
void setStreamCallback( RtAudioCallback callback, void *userData );
void cancelStreamCallback();
+ public:
+ // \brief Internal structure that provide debug information on the state of a running DSound device.
+ struct RtDsStatistics {
+ // \brief Sample Rate.
+ long sampleRate;
+ // \brief The size of one sample * number of channels on the input device.
+ int inputFrameSize;
+ // \brief The size of one sample * number of channels on the output device.
+ int outputFrameSize;
+ /* \brief The number of times the read pointer had to be adjusted to avoid reading from an unsafe buffer position.
+ *
+ * This field is only used when running in DUPLEX mode. INPUT mode devices just wait until the data is
+ * available.
+ */
+ int numberOfReadOverruns;
+ // \brief The number of times the write pointer had to be adjusted to avoid writing in an unsafe buffer position.
+ int numberOfWriteUnderruns;
+ // \brief Number of bytes by attribute to buffer configuration by which writing must lead the current write pointer.
+ int writeDeviceBufferLeadBytes;
+ // \brief Number of bytes by attributable to the device driver by which writing must lead the current write pointer on this output device.
+ unsigned long writeDeviceSafeLeadBytes;
+ // \brief Number of bytes by which reading must trail the current read pointer on this input device.
+ unsigned long readDeviceSafeLeadBytes;
+ /* \brief Estimated latency in seconds.
+ *
+ * For INPUT mode devices, based the latency of the device's safe read pointer, plus one buffer's
+ * worth of additional latency.
+ *
+ * For OUTPUT mode devices, the latency of the device's safe write pointer, plus N buffers of
+ * additional buffer latency.
+ *
+ * For DUPLEX devices, the sum of latencies for both input and output devices. DUPLEX devices
+ * also back off the read pointers an additional amount in order to maintain synchronization
+ * between out-of-phase read and write pointers. This time is also included.
+ *
+ * Note that most software packages report latency between the safe write pointer
+ * and the software lead pointer, excluding the hardware device's safe write pointer
+ * latency. Figures of 1 or 2ms of latency on Windows audio devices are invariably of this type.
+ * The reality is that hardware devices often have latencies of 30ms or more (often much
+ * higher for duplex operation).
+ */
+
+ double latency;
+ };
+ // \brief Report on the current state of a running DSound device.
+ static RtDsStatistics getDsStatistics();
+
private:
void initialize(void);
@@ -683,6 +730,12 @@ public:
bool probeDeviceOpen( int device, StreamMode mode, int channels,
int sampleRate, RtAudioFormat format,
int *bufferSize, int numberOfBuffers );
+
+ bool coInitialized;
+ bool buffersRolling;
+ long duplexPrerollBytes;
+ static RtDsStatistics statistics;
+
};
#endif
@@ -716,6 +769,9 @@ public:
bool probeDeviceOpen( int device, StreamMode mode, int channels,
int sampleRate, RtAudioFormat format,
int *bufferSize, int numberOfBuffers );
+
+ bool coInitialized;
+
};
#endif
diff --git a/include/RtDuplex.h b/include/RtDuplex.h
index c43a790..f8c2818 100644
--- a/include/RtDuplex.h
+++ b/include/RtDuplex.h
@@ -24,7 +24,7 @@
methods, which take/return pointers to
multi-channel sample frames.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
diff --git a/include/RtMidi.h b/include/RtMidi.h
index c33bd40..c80462c 100644
--- a/include/RtMidi.h
+++ b/include/RtMidi.h
@@ -8,7 +8,7 @@
RtMidi WWW site: http://music.mcgill.ca/~gary/rtmidi/
RtMidi: realtime MIDI i/o C++ classes
- Copyright (c) 2003-2004 Gary P. Scavone
+ Copyright (c) 2003-2005 Gary P. Scavone
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files
@@ -35,7 +35,7 @@
*/
/**********************************************************************/
-// RtMidi: Version 1.0.2, 21 September 2004
+// RtMidi: Version 1.0.4, 14 October 2005
#ifndef RTMIDI_H
#define RTMIDI_H
@@ -45,10 +45,26 @@
class RtMidi
{
+ public:
+
+ //! Pure virtual openPort() function.
+ virtual void openPort( unsigned int portNumber = 0 ) = 0;
+
+ //! Pure virtual openVirtualPort() function.
+ virtual void openVirtualPort() = 0;
+
+ //! Pure virtual getPortCount() function.
+ virtual unsigned int getPortCount() = 0;
+
+ //! Pure virtual getPortName() function.
+ virtual std::string getPortName( unsigned int portNumber = 0 ) = 0;
+
+ //! Pure virtual closePort() function.
+ virtual void closePort( void ) = 0;
+
protected:
RtMidi();
-
virtual ~RtMidi() {};
// A basic error reporting function for internal use in the RtMidi
@@ -56,8 +72,6 @@ class RtMidi
// suit specific needs.
void error( RtError::Type type );
- virtual void openPort( unsigned int portNumber = 0 ) = 0;
-
void *apiData_;
bool connected_;
std::string errorString_;
diff --git a/include/RtWvIn.h b/include/RtWvIn.h
index 26c25a6..5e6f4d0 100644
--- a/include/RtWvIn.h
+++ b/include/RtWvIn.h
@@ -2,24 +2,19 @@
/*! \class RtWvIn
\brief STK realtime audio (blocking) input class.
- This class provides a simplified interface to
- RtAudio for realtime audio input. It is a
- protected subclass of WvIn. Because this
- class makes use of RtAudio's blocking output
- routines, its performance is less robust on
- systems where the audio API is callback-based
- (Macintosh CoreAudio and Windows ASIO).
+ This class provides a simplified interface to RtAudio for realtime
+ audio input. It is a subclass of WvIn. Because this class makes
+ use of RtAudio's blocking output routines, its performance is less
+ robust on systems where the audio API is callback-based (Macintosh
+ CoreAudio and Windows ASIO).
- RtWvIn supports multi-channel data in
- interleaved format. It is important to
- distinguish the tick() methods, which return
- samples produced by averaging across sample
- frames, from the tickFrame() methods, which
- return pointers to multi-channel sample frames.
- For single-channel data, these methods return
- equivalent values.
+ RtWvIn supports multi-channel data in interleaved format. It is
+ important to distinguish the tick() methods, which return samples
+ produced by averaging across sample frames, from the tickFrame()
+ methods, which return references or pointers to multi-channel
+ sample frames.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -29,7 +24,7 @@
#include "WvIn.h"
#include "RtAudio.h"
-class RtWvIn : protected WvIn
+class RtWvIn : public WvIn
{
public:
//! Default constructor.
@@ -44,75 +39,35 @@ public:
is defined in Stk.h. An StkError will be thrown if an error
occurs duing instantiation.
*/
- RtWvIn(int nChannels = 1, StkFloat sampleRate = Stk::sampleRate(), int device = 0, int bufferFrames = RT_BUFFER_SIZE, int nBuffers = 2);
+ RtWvIn( unsigned int nChannels = 1, StkFloat sampleRate = Stk::sampleRate(),
+ int device = 0, int bufferFrames = RT_BUFFER_SIZE, int nBuffers = 4 );
//! Class destructor.
~RtWvIn();
//! Start the audio input stream.
/*!
- The stream is started automatically, if necessary, when a tick() or tickFrame method is called.
+ The stream is started automatically, if necessary, when a
+ tick() or tickFrame() method is called.
*/
- void start(void);
+ void start( void );
//! Stop the audio input stream.
/*!
- It may be necessary to use this method to avoid audio underflow problems if you wish to temporarily stop audio input.
+ It may be necessary to use this method to avoid audio underflow
+ problems if you wish to temporarily stop audio input.
*/
- void stop(void);
-
- //! Return the average across the last output sample frame.
- StkFloat lastOut(void) const;
-
- //! Read out the average across one sample frame of data.
- /*!
- An StkError will be thrown if an error occurs during input.
- */
- StkFloat tick(void);
-
- //! Read out vectorSize averaged sample frames of data in \e vector.
- /*!
- An StkError will be thrown if an error occurs during input.
- */
- StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
-
- //! Fill a channel of the StkFrames object with averaged sample frames.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if an
- error occurs during input or the \c channel argument is zero or it
- is greater than the number of channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
- //! Return a pointer to the last output sample frame.
- const StkFloat *lastFrame(void) const;
-
- //! Return a pointer to the next sample frame of data.
- /*!
- An StkError will be thrown if an error occurs during input.
- */
- const StkFloat *tickFrame(void);
-
- //! Read out sample \e frames of data to \e frameVector.
- /*!
- An StkError will be thrown if an error occurs during input.
- */
- StkFloat *tickFrame(StkFloat *frameVector, unsigned int frames);
-
- //! Fill the StkFrames object with sample frames of data and return the same reference.
- /*!
- An StkError will be thrown if an error occurs during input or
- there is an incompatability between the number of channels in the
- RtWvIn object and that in the StkFrames object.
- */
- StkFrames& tickFrame( StkFrames& frames );
+ void stop( void );
protected:
- RtAudio *audio_;
+ void computeFrame( void );
+
+ RtAudio *adc_;
+ StkFloat *buffer_;
bool stopped_;
- long counter_;
+ unsigned int bufferFrames_;
+ unsigned int bufferIndex_;
};
diff --git a/include/RtWvOut.h b/include/RtWvOut.h
index 3668706..b5bc56e 100644
--- a/include/RtWvOut.h
+++ b/include/RtWvOut.h
@@ -2,23 +2,19 @@
/*! \class RtWvOut
\brief STK realtime audio (blocking) output class.
- This class provides a simplified interface to
- RtAudio for realtime audio output. It is a
- protected subclass of WvOut. Because this
- class makes use of RtAudio's blocking output
- routines, its performance is less robust on
- systems where the audio API is callback-based
+ This class provides a simplified interface to RtAudio for realtime
+ audio output. It is a subclass of WvOut. Because this class
+ makes use of RtAudio's blocking output routines, its performance
+ is less robust on systems where the audio API is callback-based
(Macintosh CoreAudio and Windows ASIO).
- RtWvOut supports multi-channel data in
- interleaved format. It is important to
- distinguish the tick() methods, which output
- single samples to all channels in a sample
- frame, from the tickFrame() method, which
- takes a pointer to multi-channel sample
+ RtWvOut supports multi-channel data in interleaved format. It is
+ important to distinguish the tick() methods, which output single
+ samples to all channels in a sample frame, from the tickFrame()
+ method, which take a pointer or reference to multi-channel sample
frame data.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -28,7 +24,7 @@
#include "WvOut.h"
#include "RtAudio.h"
-class RtWvOut : protected WvOut
+class RtWvOut : public WvOut
{
public:
@@ -44,70 +40,41 @@ class RtWvOut : protected WvOut
is defined in Stk.h. An StkError will be thrown if an error
occurs duing instantiation.
*/
- RtWvOut(unsigned int nChannels = 1, StkFloat sampleRate = Stk::sampleRate(), int device = 0, int bufferFrames = RT_BUFFER_SIZE, int nBuffers = 4 );
+ RtWvOut( unsigned int nChannels = 1, StkFloat sampleRate = Stk::sampleRate(),
+ int device = 0, int bufferFrames = RT_BUFFER_SIZE, int nBuffers = 4 );
//! Class destructor.
~RtWvOut();
//! Start the audio output stream.
/*!
- The stream is started automatically, if necessary, when a tick() or tickFrame method is called.
+ The stream is started automatically, if necessary, when a
+ tick() or tickFrame method is called.
*/
void start(void);
//! Stop the audio output stream.
/*!
- It may be necessary to use this method to avoid undesireable audio buffer cycling if you wish to temporarily stop audio output.
+ It may be necessary to use this method to avoid undesireable
+ audio buffer cycling if you wish to temporarily stop audio output.
*/
void stop(void);
- //! Return the number of sample frames output.
- unsigned long getFrames( void ) const;
-
- //! Return the number of seconds of data output.
- StkFloat getTime( void ) const;
-
- //! Output a single sample to all channels in a sample frame.
- /*!
- An StkError will be thrown if an error occurs during output.
- */
- void tick( const StkFloat sample );
-
- //! Output each sample in \e vector to all channels in \e vectorSize sample frames.
- /*!
- An StkError will be thrown if an error occurs during output.
- */
- void tick( const StkFloat *vector, unsigned int vectorSize );
-
- //! Output a channel of the StkFrames object to all channels of the RtWvOut object.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if an
- error occurs during output or the \c channel argument is zero or
- it is greater than the number of channels in the StkFrames object.
- */
- void tick( const StkFrames& frames, unsigned int channel = 1 );
-
- //! Output the \e frameVector of sample frames of the given length.
- /*!
- An StkError will be thrown if an error occurs during output.
- */
- void tickFrame( const StkFloat *frameVector, unsigned int frames = 1 );
-
- //! Output the StkFrames data to the RtWvOut object.
- /*!
- An StkError will be thrown if an error occurs during output or
- if there is an incompatability between the number of channels in
- the WvOut object and that in the StkFrames object.
- */
- void tickFrame( const StkFrames& frames );
-
protected:
- RtAudio *audio_;
- StkFloat *dataPtr_;
+ void computeSample( const StkFloat sample );
+
+ void computeFrames( const StkFrames& frames );
+
+ void incrementFrame( void );
+
+ RtAudio *dac_;
+ StkFloat *buffer_;
bool stopped_;
- int bufferSize_;
+ unsigned int nChannels_;
+ unsigned int bufferIndex_;
+ unsigned int iBuffer_;
+ unsigned int bufferFrames_;
};
diff --git a/include/Sampler.h b/include/Sampler.h
index edd3f09..518035c 100644
--- a/include/Sampler.h
+++ b/include/Sampler.h
@@ -5,7 +5,7 @@
This instrument provides an ADSR envelope, a one-pole filter, and
structures for an arbitrary number of attack and loop waves.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -14,7 +14,6 @@
#include "Instrmnt.h"
#include "ADSR.h"
-#include "WvIn.h"
#include "WaveLoop.h"
#include "OnePole.h"
@@ -42,27 +41,15 @@ class Sampler : public Instrmnt
//! Stop a note with the given amplitude (speed of decay).
virtual void noteOff(StkFloat amplitude);
- //! Compute one output sample.
- virtual StkFloat tick() = 0;
-
- //! Computer \e vectorSize outputs and return them in \e vector.
- virtual StkFloat *tick(StkFloat *vector, unsigned int vectorSize) = 0;
-
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- virtual StkFrames& tick( StkFrames& frames, unsigned int channel = 1 ) = 0;
-
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
virtual void controlChange(int number, StkFloat value) = 0;
- protected:
+ protected:
+
+ virtual StkFloat computeSample( void ) = 0;
+
ADSR adsr_;
- std::vector attacks_;
+ std::vector attacks_;
std::vector loops_;
OnePole filter_;
StkFloat baseFrequency_;
diff --git a/include/Saxofony.h b/include/Saxofony.h
index ef9e046..8221344 100644
--- a/include/Saxofony.h
+++ b/include/Saxofony.h
@@ -31,7 +31,7 @@
- Vibrato Gain = 1
- Breath Pressure = 128
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -44,7 +44,7 @@
#include "OneZero.h"
#include "Envelope.h"
#include "Noise.h"
-#include "WaveLoop.h"
+#include "SineWave.h"
class Saxofony : public Instrmnt
{
@@ -79,31 +79,19 @@ class Saxofony : public Instrmnt
//! Stop a note with the given amplitude (speed of decay).
void noteOff(StkFloat amplitude);
- //! Compute one output sample.
- StkFloat tick();
-
- //! Computer \e vectorSize outputs and return them in \e vector.
- StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
-
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
void controlChange(int number, StkFloat value);
protected:
+
+ StkFloat computeSample( void );
+
DelayL delays_[2];
ReedTable reedTable_;
OneZero filter_;
Envelope envelope_;
Noise noise_;
- WaveLoop *vibrato_;
+ SineWave vibrato_;
unsigned long length_;
StkFloat outputGain_;
StkFloat noiseGain_;
diff --git a/include/Shakers.h b/include/Shakers.h
index 91f6025..e41ded4 100644
--- a/include/Shakers.h
+++ b/include/Shakers.h
@@ -79,26 +79,12 @@ class Shakers : public Instrmnt
//! Stop a note with the given amplitude (speed of decay).
void noteOff(StkFloat amplitude);
- //! Compute one output sample.
- StkFloat tick();
-
- //! Computer \e vectorSize outputs and return them in \e vector.
- StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
-
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
void controlChange(int number, StkFloat value);
protected:
+ StkFloat computeSample( void );
int setupName(char* instr);
int setupNum(int inst);
int setFreqAndReson(int which, StkFloat freq, StkFloat reson);
diff --git a/include/Simple.h b/include/Simple.h
index bde74da..6a65558 100644
--- a/include/Simple.h
+++ b/include/Simple.h
@@ -13,7 +13,7 @@
- Envelope Rate = 11
- Gain = 128
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -57,25 +57,13 @@ class Simple : public Instrmnt
//! Stop a note with the given amplitude (speed of decay).
void noteOff(StkFloat amplitude);
- //! Compute one output sample.
- StkFloat tick();
-
- //! Computer \e vectorSize outputs and return them in \e vector.
- StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
-
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
void controlChange(int number, StkFloat value);
- protected:
+ protected:
+
+ StkFloat computeSample( void );
+
ADSR adsr_;
WaveLoop *loop_;
OnePole filter_;
diff --git a/include/SineWave.h b/include/SineWave.h
new file mode 100644
index 0000000..e4ca79a
--- /dev/null
+++ b/include/SineWave.h
@@ -0,0 +1,80 @@
+/***************************************************/
+/*! \class SineWave
+ \brief STK sinusoid oscillator class.
+
+ This class computes and saves a static sine "table" that can be
+ shared by multiple instances. It has an interface similar to the
+ WaveLoop class but inherits from the Generator class. Output
+ values are computed using linear interpolation.
+
+ The "table" length, set in SineWave.h, is 2048 samples by default.
+
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
+*/
+/***************************************************/
+
+#ifndef STK_SINEWAVE_H
+#define STK_SINEWAVE_H
+
+const unsigned long TABLE_SIZE = 2048;
+
+#include "Generator.h"
+
+class SineWave : public Generator
+{
+public:
+ //! Default constructor.
+ SineWave( void );
+
+ //! Class destructor.
+ virtual ~SineWave( void );
+
+ //! Clear output and reset time pointer to zero.
+ void reset( void );
+
+ //! 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 ) { rate_ = 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 );
+
+ //! 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 );
+
+protected:
+
+ StkFloat computeSample( void );
+
+ static StkFrames table_;
+ StkFloat time_;
+ StkFloat rate_;
+ StkFloat phaseOffset_;
+
+};
+
+#endif
diff --git a/include/SingWave.h b/include/SingWave.h
index 17a47bb..5ec836f 100644
--- a/include/SingWave.h
+++ b/include/SingWave.h
@@ -9,7 +9,7 @@
from pitch shifting. It will be used as an
excitation source for other instruments.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -28,7 +28,7 @@ class SingWave : public Generator
An StkError will be thrown if the file is not found, its format is
unknown, a read error occurs, or the rawwave path is incorrectly set.
*/
- SingWave( std::string fileName, bool raw=false);
+ SingWave( std::string fileName, bool raw = false);
//! Class destructor.
~SingWave();
@@ -69,25 +69,12 @@ class SingWave : public Generator
//! Stop a note.
void noteOff();
- //! Compute one output sample.
- StkFloat tick();
-
- //! Compute \e vectorSize outputs and return them in \e vector.
- StkFloat *tick( StkFloat *vector, unsigned int vectorSize );
-
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
protected:
+ StkFloat computeSample( void );
+
WaveLoop *wave_;
- Modulate *modulator_;
+ Modulate modulator_;
Envelope envelope_;
Envelope pitchEnvelope_;
StkFloat rate_;
diff --git a/include/Sitar.h b/include/Sitar.h
index 6fc6242..4cb9edb 100644
--- a/include/Sitar.h
+++ b/include/Sitar.h
@@ -13,7 +13,7 @@
Stanford, bearing the names of Karplus and/or
Strong.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -50,22 +50,10 @@ class Sitar : public Instrmnt
//! Stop a note with the given amplitude (speed of decay).
void noteOff(StkFloat amplitude);
- //! Compute one output sample.
- StkFloat tick();
+ protected:
- //! Computer \e vectorSize outputs and return them in \e vector.
- StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
+ StkFloat computeSample( void );
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
- protected:
DelayA delayLine_;
OneZero loopFilter_;
Noise noise_;
diff --git a/include/Skini.h b/include/Skini.h
index d80399f..3e8d1bc 100644
--- a/include/Skini.h
+++ b/include/Skini.h
@@ -21,7 +21,7 @@
\sa \ref skini
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
diff --git a/include/Socket.h b/include/Socket.h
index 9b780c1..8fe0e9d 100644
--- a/include/Socket.h
+++ b/include/Socket.h
@@ -1,20 +1,13 @@
/***************************************************/
/*! \class Socket
- \brief STK TCP socket client/server class.
+ \brief STK internet socket abstract base class.
- This class provides a uniform cross-platform
- TCP socket client or socket server interface.
- Methods are provided for reading or writing
- data buffers to/from connections. This class
- also provides a number of static functions for
- use with external socket descriptors.
+ This class provides common functionality for TCP and UDP internet
+ socket server and client subclasses. This class also provides a
+ number of static functions for use with external socket
+ descriptors.
- The user is responsible for checking the values
- returned by the read/write methods. Values
- less than or equal to zero indicate a closed
- or lost connection or the occurence of an error.
-
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -23,71 +16,62 @@
#include "Stk.h"
+#if (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__))
+
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+
+#elif defined(__OS_WINDOWS__)
+
+ #include
+
+#endif
+
class Socket : public Stk
{
public:
- //! Default constructor which creates a local socket server on port 2006 (or the specified port number).
- /*!
- An StkError will be thrown if a socket error occurs during instantiation.
- */
- Socket( int port = 2006 );
- //! Class constructor which creates a socket client connection to the specified host and port.
- /*!
- An StkError will be thrown if a socket error occurs during instantiation.
- */
- Socket( int port, const char *hostname );
+ enum ProtocolType {
+ PROTO_TCP,
+ PROTO_UDP
+ };
- //! The class destructor closes the socket instance, breaking any existing connections.
- ~Socket();
+ //! Class constructor
+ Socket();
- //! Connect a socket client to the specified host and port and returns the resulting socket descriptor.
- /*!
- This method is valid for socket clients only. If it is called for
- a socket server, -1 is returned. If the socket client is already
- connected, that connection is terminated and a new connection is
- attempted. Server connections are made using the accept() method.
- An StkError will be thrown if a socket error occurs during
- instantiation. \sa accept
- */
- int connect( int port, const char *hostname = "localhost" );
+ //! Class destructor.
+ virtual ~Socket();
- //! Close this socket.
- void close( void );
+ //! Close the socket.
+ static void close( int socket );
- //! Return the server/client socket descriptor.
+ //! Return the socket descriptor.
int id( void ) const;
- //! Return the server/client port number.
+ //! Return the socket port number.
int port( void ) const;
- //! If this is a socket server, extract the first pending connection request from the queue and create a new connection, returning the descriptor for the accepted socket.
- /*!
- If no connection requests are pending and the socket has not
- been set non-blocking, this function will block until a connection
- is present. If an error occurs or this is a socket client, -1 is
- returned.
- */
- int accept( void );
-
- //! If enable = false, the socket is set to non-blocking mode. When first created, sockets are by default in blocking mode.
- static void setBlocking( int socket, bool enable );
-
- //! Close the socket with the given descriptor.
- static void close( int socket );
-
//! Returns true if the socket descriptor is valid.
static bool isValid( int socket );
+ //! If enable = false, the socket is set to non-blocking mode. When first created, sockets are by default in blocking mode.
+ static void setBlocking( int socket, bool enable );
+
//! Write a buffer over the socket connection. Returns the number of bytes written or -1 if an error occurs.
- int writeBuffer(const void *buffer, long bufferSize, int flags = 0);
+ virtual int writeBuffer(const void *buffer, long bufferSize, int flags = 0) = 0;
+
+ //! Read an input buffer, up to length \e bufferSize. Returns the number of bytes read or -1 if an error occurs.
+ virtual int readBuffer(void *buffer, long bufferSize, int flags = 0) = 0;
//! Write a buffer via the specified socket. Returns the number of bytes written or -1 if an error occurs.
static int writeBuffer(int socket, const void *buffer, long bufferSize, int flags );
- //! Read a buffer from the socket connection, up to length \e bufferSize. Returns the number of bytes read or -1 if an error occurs.
- int readBuffer(void *buffer, long bufferSize, int flags = 0);
-
//! Read a buffer via the specified socket. Returns the number of bytes read or -1 if an error occurs.
static int readBuffer(int socket, void *buffer, long bufferSize, int flags );
@@ -95,7 +79,6 @@ class Socket : public Stk
int soket_;
int port_;
- bool server_;
};
diff --git a/include/StifKarp.h b/include/StifKarp.h
index 769aeac..aae4a32 100644
--- a/include/StifKarp.h
+++ b/include/StifKarp.h
@@ -17,7 +17,7 @@
- String Sustain = 11
- String Stretch = 1
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -69,39 +69,27 @@ class StifKarp : public Instrmnt
//! Stop a note with the given amplitude (speed of decay).
void noteOff(StkFloat amplitude);
- //! Compute one output sample.
- StkFloat tick();
-
- //! Computer \e vectorSize outputs and return them in \e vector.
- StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
-
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
void controlChange(int number, StkFloat value);
- protected:
- DelayA delayLine_;
- DelayL combDelay_;
- OneZero filter_;
- Noise noise_;
- BiQuad biquad_[4];
+ protected:
- unsigned long length_;
- StkFloat loopGain_;
- StkFloat baseLoopGain_;
- StkFloat lastFrequency_;
- StkFloat lastLength_;
- StkFloat stretching_;
- StkFloat pluckAmplitude_;
- StkFloat pickupPosition_;
+ StkFloat computeSample( void );
+
+ DelayA delayLine_;
+ DelayL combDelay_;
+ OneZero filter_;
+ Noise noise_;
+ BiQuad biquad_[4];
+
+ unsigned long length_;
+ StkFloat loopGain_;
+ StkFloat baseLoopGain_;
+ StkFloat lastFrequency_;
+ StkFloat lastLength_;
+ StkFloat stretching_;
+ StkFloat pluckAmplitude_;
+ StkFloat pickupPosition_;
};
diff --git a/include/Stk.h b/include/Stk.h
index c15c2b6..75e6363 100644
--- a/include/Stk.h
+++ b/include/Stk.h
@@ -8,7 +8,7 @@
this class provides error handling and
byte-swapping functions.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -18,7 +18,6 @@
#include
#include
#include
-#include
// Most data in STK is passed and calculated with the
// following user-definable floating-point type. You
@@ -52,6 +51,8 @@ public:
STATUS,
WARNING,
DEBUG_WARNING,
+ MEMORY_ALLOCATION,
+ MEMORY_ACCESS,
FUNCTION_ARGUMENT,
FILE_NOT_FOUND,
FILE_UNKNOWN_FORMAT,
@@ -70,7 +71,8 @@ protected:
public:
//! The constructor.
- StkError(const std::string& message, Type type = StkError::UNSPECIFIED) : message_(message), type_(type) {}
+ StkError(const std::string& message, Type type = StkError::UNSPECIFIED)
+ : message_(message), type_(type) {}
//! The destructor.
virtual ~StkError(void) {};
@@ -139,9 +141,17 @@ public:
//! Static function for error reporting and handling using c++ strings.
static void handleError( std::string message, StkError::Type type );
+ //! Toggle display of WARNING and STATUS messages.
+ static void showWarnings( bool status ) { showWarnings_ = status; }
+
+ //! Toggle display of error messages before throwing exceptions.
+ static void printErrors( bool status ) { printErrors_ = status; }
+
private:
static StkFloat srate_;
static std::string rawwavepath_;
+ static bool showWarnings_;
+ static bool printErrors_;
protected:
@@ -164,13 +174,14 @@ protected:
This class can hold single- or multi-channel audio data in either
interleaved or non-interleaved formats. The data type is always
- StkFloat.
+ StkFloat. In an effort to maintain efficiency, no out-of-bounds
+ checks are performed in this class.
- Possible future improvements in this class could include static
- functions to inter- or de-interleave the data and to convert to
- and return other data types.
+ Possible future improvements in this class could include functions
+ to inter- or de-interleave the data and to convert to and return
+ other data types.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -179,36 +190,82 @@ class StkFrames
public:
//! The default constructor initializes the frame data structure to size zero.
- StkFrames( unsigned int nFrames = 0, unsigned int nChannels = 1, bool interleaved = true );
+ StkFrames( unsigned int nFrames = 0, unsigned int nChannels = 0, bool interleaved = true );
- //! Overloaded constructor which initializes the frame data to the specified size with \c value.
+ //! Overloaded constructor that initializes the frame data to the specified size with \c value.
StkFrames( const StkFloat& value, unsigned int nFrames, unsigned int nChannels, bool interleaved = true );
+ //! The destructor.
+ ~StkFrames();
+
//! Subscript operator which returns a reference to element \c n of self.
/*!
The result can be used as an lvalue . This reference is valid
until the resize function is called or the array is destroyed. The
index \c n must be between 0 and size less one. No range checking
- is performed.
+ is performed unless _STK_DEBUG_ is defined.
*/
- StkFloat& operator[]( size_t n ) { return data_[n]; };
+ StkFloat& operator[] ( size_t n );
- //! Subscript operator which returns the value at element \c n of self.
+ //! Subscript operator that returns the value at element \c n of self.
/*!
The index \c n must be between 0 and size less one. No range
- checking is performed.
+ checking is performed unless _STK_DEBUG_ is defined.
*/
- StkFloat operator[]( size_t n ) const { return data_[n]; };
+ StkFloat operator[] ( size_t n ) const;
+
+ //! Channel / frame subscript operator that returns a reference.
+ /*!
+ The result can be used as an lvalue. This reference is valid
+ until the resize function is called or the array is destroyed. The
+ \c frame index must be between 0 and frames() - 1. The \c channel
+ index must be between 0 and channels() - 1. No range checking is
+ performed unless _STK_DEBUG_ is defined.
+ */
+ StkFloat& operator() ( size_t frame, unsigned int channel );
+
+ //! Channel / frame subscript operator that returns a value.
+ /*!
+ The \c frame index must be between 0 and frames() - 1. The \c
+ channel index must be between 0 and channels() - 1. No range checking
+ is performed unless _STK_DEBUG_ is defined.
+ */
+ StkFloat operator() ( size_t frame, unsigned int channel ) const;
+
+ //! Return an interpolated value at the fractional frame index and channel.
+ /*!
+ This function performs linear interpolation. The \c frame
+ index must be between 0.0 and frames() - 1. The \c channel index
+ must be between 0 and channels() - 1. No range checking is
+ performed unless _STK_DEBUG_ is defined.
+ */
+ StkFloat interpolate( StkFloat frame, unsigned int channel = 0 ) const;
//! Returns the total number of audio samples represented by the object.
size_t size() const { return size_; };
+ //! Returns \e true if the object size is zero and \e false otherwise.
+ bool empty() const;
+
//! Resize self to represent the specified number of channels and frames.
/*!
Changes the size of self based on the number of frames and
- channels, and assigns \c value to every element.
+ channels. No element assignment is performed. No memory
+ deallocation occurs if the new size is smaller than the previous
+ size. Further, no new memory is allocated when the new size is
+ smaller or equal to a previously allocated size.
*/
- void resize( unsigned int nFrames, unsigned int nChannels = 1, StkFloat value = 0.0 );
+ void resize( size_t nFrames, unsigned int nChannels = 1 );
+
+ //! Resize self to represent the specified number of channels and frames and perform element initialization.
+ /*!
+ Changes the size of self based on the number of frames and
+ channels, and assigns \c value to every element. No memory
+ deallocation occurs if the new size is smaller than the previous
+ size. Further, no new memory is allocated when the new size is
+ smaller or equal to a previously allocated size.
+ */
+ void resize( size_t nFrames, unsigned int nChannels, StkFloat value );
//! Return the number of channels represented by the data.
unsigned int channels( void ) const { return nChannels_; };
@@ -216,23 +273,47 @@ public:
//! Return the number of sample frames represented by the data.
unsigned int frames( void ) const { return nFrames_; };
+ //! Set the sample rate associated with the StkFrames data.
+ /*!
+ By default, this value is set equal to the current STK sample
+ rate at the time of instantiation.
+ */
+ void setDataRate( StkFloat rate ) { dataRate_ = rate; };
+
+ //! Return the sample rate associated with the StkFrames data.
+ /*!
+ By default, this value is set equal to the current STK sample
+ rate at the time of instantiation.
+ */
+ StkFloat dataRate( void ) const { return dataRate_; };
+
//! Returns \c true if the data is in interleaved format, \c false if the data is non-interleaved.
bool interleaved( void ) const { return interleaved_; };
//! Set the flag to indicate whether the internal data is in interleaved (\c true) or non-interleaved (\c false) format.
+ /*!
+ Note that this function does not modify the internal data order
+ with respect to the argument value. It simply changes the
+ indicator flag value.
+ */
void setInterleaved( bool isInterleaved ) { interleaved_ = isInterleaved; };
private:
- std::valarray data_;
- unsigned int nFrames_;
+
+ StkFloat *data_;
+ StkFloat dataRate_;
+ size_t nFrames_;
unsigned int nChannels_;
size_t size_;
+ size_t bufferSize_;
bool interleaved_;
};
// Here are a few other useful typedefs.
+typedef unsigned short UINT16;
+typedef unsigned int UINT32;
typedef signed short SINT16;
typedef signed int SINT32;
typedef float FLOAT32;
@@ -260,11 +341,11 @@ const unsigned int RT_BUFFER_SIZE = 512;
#define RAWWAVE_PATH "../../rawwaves/"
#endif
-const StkFloat PI = 3.14159265359;
+const StkFloat PI = 3.14159265358979;
const StkFloat TWO_PI = 2 * PI;
const StkFloat ONE_OVER_128 = 0.0078125;
-#if defined(__WINDOWS_DS__) || defined(__WINDOWS_ASIO__)
+#if defined(__WINDOWS_DS__) || defined(__WINDOWS_ASIO__) || defined(__WINDOWS_MM__)
#define __OS_WINDOWS__
#define __STK_REALTIME__
#elif defined(__LINUX_OSS__) || defined(__LINUX_ALSA__) || defined(__LINUX_JACK__)
diff --git a/include/SubNoise.h b/include/SubNoise.h
index 8f517cc..3dad039 100644
--- a/include/SubNoise.h
+++ b/include/SubNoise.h
@@ -6,7 +6,7 @@
using the C rand() function. The quality of the
rand() function varies from one OS to another.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -20,33 +20,21 @@ class SubNoise : public Noise
public:
//! Default constructor sets sub-sample rate to 16.
- SubNoise(int subRate = 16);
+ SubNoise( int subRate = 16 );
//! Class destructor.
~SubNoise();
//! Return the current sub-sampling rate.
- int subRate(void) const;
+ int subRate( void ) const { return rate_; };
//! Set the sub-sampling rate.
- void setRate(int subRate);
-
- //! Return a sub-sampled random number between -1.0 and 1.0.
- StkFloat tick();
-
- //! Compute \e vectorSize outputs and return them in \e vector.
- StkFloat *tick( StkFloat *vector, unsigned int vectorSize );
-
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
+ void setRate( int subRate );
protected:
+
+ StkFloat computeSample( void );
+
int counter_;
int rate_;
diff --git a/include/Table.h b/include/Table.h
deleted file mode 100644
index a35da3c..0000000
--- a/include/Table.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/***************************************************/
-/*! \class Table
- \brief STK table lookup class.
-
- This class loads a table of floating-point
- doubles, which are assumed to be in big-endian
- format. Linear interpolation is performed for
- fractional lookup indexes.
-
- An StkError will be thrown if the table file
- is not found.
-
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
-*/
-/***************************************************/
-
-#ifndef STK_TABLE_H
-#define STK_TABLE_H
-
-#include "Function.h"
-
-class Table : public Function
-{
-public:
- //! The constructor loads the data from \e fileName.
- /*!
- An StkError will be thrown in the file cannot be found or
- opened.
- */
- Table( std::string fileName );
-
- //! Class destructor.
- ~Table();
-
- //! Return the number of elements in the table.
- long getLength() const;
-
- //! Return the table value at position \e index.
- /*!
- Linear interpolation is performed if \e index is
- fractional.
- */
- StkFloat tick(StkFloat index);
-
- //! Take \e vectorSize inputs from \e vector and replace them with corresponding outputs.
- StkFloat *tick( StkFloat *vector, unsigned int vectorSize );
-
- //! Take a channel of the StkFrames object as inputs to the function and replace with corresponding outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
-protected:
- long length_;
- std::valarray data_;
-
-};
-
-#endif // defined(__TABLE_H)
diff --git a/include/TcpClient.h b/include/TcpClient.h
new file mode 100644
index 0000000..8c5ef1a
--- /dev/null
+++ b/include/TcpClient.h
@@ -0,0 +1,61 @@
+/***************************************************/
+/*! \class TcpClient
+ \brief STK TCP socket client class.
+
+ This class provides a uniform cross-platform TCP socket client
+ interface. Methods are provided for reading or writing data
+ buffers to/from connections.
+
+ TCP sockets are reliable and connection-oriented. A TCP socket
+ client must be connected to a TCP server before data can be sent
+ or received. Data delivery is guaranteed in order, without loss,
+ error, or duplication. That said, TCP transmissions tend to be
+ slower than those using the UDP protocol and data sent with
+ multiple \e write() calls can be arbitrarily combined by the
+ underlying system.
+
+ The user is responsible for checking the values
+ returned by the read/write methods. Values
+ less than or equal to zero indicate a closed
+ or lost connection or the occurence of an error.
+
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
+*/
+/***************************************************/
+
+#ifndef STK_TCPCLIENT_H
+#define STK_TCPCLIENT_H
+
+#include "Socket.h"
+
+class TcpClient : public Socket
+{
+ public:
+ //! Default class constructor creates a socket client connection to the specified host and port.
+ /*!
+ An StkError will be thrown if a socket error occurs during instantiation.
+ */
+ TcpClient( int port, std::string hostname = "localhost" );
+
+ //! The class destructor closes the socket instance, breaking any existing connections.
+ ~TcpClient();
+
+ //! Connect the socket client to the specified host and port and returns the resulting socket descriptor.
+ /*!
+ If the socket client is already connected, that connection is
+ terminated and a new connection is attempted. An StkError will be
+ thrown if a socket error occurs.
+ */
+ int connect( int port, std::string hostname = "localhost" );
+
+ //! Write a buffer over the socket connection. Returns the number of bytes written or -1 if an error occurs.
+ int writeBuffer(const void *buffer, long bufferSize, int flags = 0);
+
+ //! Read a buffer from the socket connection, up to length \e bufferSize. Returns the number of bytes read or -1 if an error occurs.
+ int readBuffer(void *buffer, long bufferSize, int flags = 0);
+
+ protected:
+
+};
+
+#endif // defined(STK_TCPCLIENT_H)
diff --git a/include/TcpServer.h b/include/TcpServer.h
new file mode 100644
index 0000000..7951ee2
--- /dev/null
+++ b/include/TcpServer.h
@@ -0,0 +1,61 @@
+/***************************************************/
+/*! \class TcpServer
+ \brief STK TCP socket server class.
+
+ This class provides a uniform cross-platform TCP socket server
+ interface. Methods are provided for reading or writing data
+ buffers to/from connections.
+
+ TCP sockets are reliable and connection-oriented. A TCP socket
+ server must accept a connection from a TCP client before data can
+ be sent or received. Data delivery is guaranteed in order,
+ without loss, error, or duplication. That said, TCP transmissions
+ tend to be slower than those using the UDP protocol and data sent
+ with multiple \e write() calls can be arbitrarily combined by the
+ underlying system.
+
+ The user is responsible for checking the values
+ returned by the read/write methods. Values
+ less than or equal to zero indicate a closed
+ or lost connection or the occurence of an error.
+
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
+*/
+/***************************************************/
+
+#ifndef STK_TCPSERVER_H
+#define STK_TCPSERVER_H
+
+#include "Socket.h"
+
+class TcpServer : public Socket
+{
+ public:
+ //! Default constructor creates a local socket server on port 2006 (or the specified port number).
+ /*!
+ An StkError will be thrown if a socket error occurs during instantiation.
+ */
+ TcpServer( int port = 2006 );
+
+ //! The class destructor closes the socket instance, breaking any existing connections.
+ ~TcpServer();
+
+ //! Extract the first pending connection request from the queue and create a new connection, returning the descriptor for the accepted socket.
+ /*!
+ If no connection requests are pending and the socket has not
+ been set non-blocking, this function will block until a connection
+ is present. If an error occurs, -1 is returned.
+ */
+ int accept( void );
+
+ //! Write a buffer over the socket connection. Returns the number of bytes written or -1 if an error occurs.
+ int writeBuffer(const void *buffer, long bufferSize, int flags = 0);
+
+ //! Read a buffer from the socket connection, up to length \e bufferSize. Returns the number of bytes read or -1 if an error occurs.
+ int readBuffer(void *buffer, long bufferSize, int flags = 0);
+
+ protected:
+
+};
+
+#endif // defined(STK_TCPSERVER_H)
diff --git a/include/TcpWvIn.h b/include/TcpWvIn.h
deleted file mode 100644
index 0766487..0000000
--- a/include/TcpWvIn.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/***************************************************/
-/*! \class TcpWvIn
- \brief STK internet streaming input class.
-
- This protected Wvin subclass can read streamed
- data over a network via a TCP socket connection.
- The data is assumed in big-endian, or network,
- byte order.
-
- TcpWvIn supports multi-channel data in
- interleaved format. It is important to
- distinguish the tick() methods, which return
- samples produced by averaging across sample
- frames, from the tickFrame() methods, which
- return pointers to multi-channel sample frames.
- For single-channel data, these methods return
- equivalent values.
-
- This class starts a socket server, which waits
- for a single remote connection. The default
- data type for the incoming stream is signed
- 16-bit integers, though any of the defined
- StkFormats are permissible.
-
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
-*/
-/***************************************************/
-
-#ifndef STK_TCPWVIN_H
-#define STK_TCPWVIN_H
-
-#include "WvIn.h"
-#include "Socket.h"
-#include "Thread.h"
-#include "Mutex.h"
-
-typedef struct {
- bool finished;
- void *object;
-} thread_info;
-
-class TcpWvIn : protected WvIn
-{
-public:
- //! Default constructor starts a socket server. If not specified, the server is associated with port 2006.
- /*!
- An StkError will be thrown if an error occurs while initializing the input thread or starting the socket server.
- */
- TcpWvIn( int port = 2006 );
-
- //! Class destructor.
- ~TcpWvIn();
-
- //! Listen for a (new) connection with specified data channels and format.
- /*!
- An StkError will be thrown a socket error or an invalid function argument.
- */
- void listen(unsigned int nChannels = 1, Stk::StkFormat format = STK_SINT16);
-
- //! Returns true is an input connection exists or input data remains in the queue.
- /*!
- This method will not return false after an input connection has been closed until
- all buffered input data has been read out.
- */
- bool isConnected(void);
-
- //! Return the average across the last output sample frame.
- StkFloat lastOut(void) const;
-
- //! Read out the average across one sample frame of data.
- StkFloat tick(void);
-
- //! Read out vectorSize averaged sample frames of data in \e vector.
- StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
-
- //! Fill a channel of the StkFrames object with averaged sample frames.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
- //! Return a pointer to the last output sample frame.
- const StkFloat *lastFrame(void) const;
-
- //! Return a pointer to the next sample frame of data.
- const StkFloat *tickFrame(void);
-
- //! Read out sample \e frames of data to \e frameVector.
- StkFloat *tickFrame(StkFloat *frameVector, unsigned int frames);
-
- //! Fill the StkFrames object with sample frames of data and return the same reference.
- /*!
- An StkError will be thrown if there is an incompatability
- between the number of channels in the TcpWvIn object and that in
- the StkFrames object.
- */
- StkFrames& tickFrame( StkFrames& frames );
-
- // Called by the thread routine to receive data via the socket connection
- // and fill the socket buffer. This is not intended for general use but
- // had to be made public for access from the thread.
- void receive(void);
-
-protected:
-
- // Initialize class variables.
- void init( int port );
-
- // Read buffered socket data into the data buffer ... will block if none available.
- int readData( void );
-
- Socket *soket_;
- Thread *thread_;
- Mutex mutex_;
- char *buffer_;
- long bufferBytes_;
- long bytesFilled_;
- long writePoint_;
- long readPoint_;
- long counter_;
- int dataSize_;
- bool connected_;
- int fd_;
- thread_info threadInfo_;
-
-};
-
-#endif
diff --git a/include/TcpWvOut.h b/include/TcpWvOut.h
deleted file mode 100644
index 57f5b64..0000000
--- a/include/TcpWvOut.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/***************************************************/
-/*! \class TcpWvOut
- \brief STK internet streaming output class.
-
- This protected WvOut subclass can stream
- data over a network via a TCP socket connection.
- The data is converted to big-endian byte order,
- if necessary, before being transmitted.
-
- TcpWvOut supports multi-channel data in
- interleaved format. It is important to
- distinguish the tick() methods, which output
- single samples to all channels in a sample
- frame, from the tickFrame() method, which
- takes a pointer to multi-channel sample
- frame data.
-
- This class connects to a socket server, the
- port and IP address of which must be specified
- as constructor arguments. The default data
- type is signed 16-bit integers but any of the
- defined StkFormats are permissible.
-
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
-*/
-/***************************************************/
-
-#ifndef STK_TCPWVOUT_H
-#define STK_TCPWVOUT_H
-
-#include "WvOut.h"
-#include "Socket.h"
-
-class TcpWvOut : protected WvOut
-{
- public:
- //! Default constructor ... the socket is not instantiated.
- TcpWvOut();
-
- //! Overloaded constructor which opens a network connection during instantiation.
- /*!
- An StkError is thrown if a socket error occurs or an invalid argument is specified.
- */
- TcpWvOut(int port, const char *hostname = "localhost", unsigned int nChannels = 1, Stk::StkFormat format = STK_SINT16);
-
- //! Class destructor.
- ~TcpWvOut();
-
- //! Connect to the specified host and port and prepare to stream \e nChannels of data in the given data format.
- /*!
- An StkError is thrown if a socket error occurs or an invalid argument is specified.
- */
- void connect(int port, const char *hostname = "localhost", unsigned int nChannels = 1, Stk::StkFormat format = STK_SINT16);
-
- //! If a connection is open, write out remaining samples in the queue and then disconnect.
- void disconnect(void);
-
- //! Return the number of sample frames output.
- unsigned long getFrames( void ) const;
-
- //! Return the number of seconds of data output.
- StkFloat getTime( void ) const;
-
- //! Output a single sample to all channels in a sample frame.
- /*!
- An StkError is thrown if a socket write error occurs.
- */
- void tick( const StkFloat sample );
-
- //! Output each sample in \e vector to all channels in \e vectorSize sample frames.
- /*!
- An StkError is thrown if a socket write error occurs.
- */
- void tick( const StkFloat *vector, unsigned int vectorSize );
-
- //! Output a channel of the StkFrames object to all channels of the TcpWvOut object.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if a
- socket write error occurs or the \c channel argument is zero or it
- is greater than the number of channels in the StkFrames object.
- */
- void tick( const StkFrames& frames, unsigned int channel = 1 );
-
- //! Output the \e frameVector of sample frames of the given length.
- /*!
- An StkError is thrown if a socket write error occurs.
- */
- void tickFrame( const StkFloat *frameVector, unsigned int frames = 1 );
-
- //! Output the StkFrames data to the TcpWvOut object.
- /*!
- An StkError will be thrown if a socket write error occurs or if
- there is an incompatability between the number of channels in the
- TcpWvOut object and that in the StkFrames object.
- */
- virtual void tickFrame( const StkFrames& frames );
-
- protected:
-
- // Write a buffer of length \e frames via the socket connection.
- void writeData( unsigned long frames );
-
- char *buffer_;
- Socket *soket_;
- int dataSize_;
-};
-
-#endif
diff --git a/include/Thread.h b/include/Thread.h
index 9336bcc..f082ff2 100644
--- a/include/Thread.h
+++ b/include/Thread.h
@@ -16,7 +16,7 @@
THREAD_RETURN THREAD_TYPE thread_function(void *ptr)
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
diff --git a/include/TubeBell.h b/include/TubeBell.h
index 206a97a..ac993c3 100644
--- a/include/TubeBell.h
+++ b/include/TubeBell.h
@@ -26,7 +26,7 @@
type who should worry about this (making
money) worry away.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -50,20 +50,9 @@ class TubeBell : public FM
//! Start a note with the given frequency and amplitude.
void noteOn(StkFloat frequency, StkFloat amplitude);
- //! Compute one output sample.
- StkFloat tick();
+ protected:
- //! Computer \e vectorSize outputs and return them in \e vector.
- StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
-
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
+ StkFloat computeSample( void );
};
#endif
diff --git a/include/TwoPole.h b/include/TwoPole.h
index 9d15d06..94a76d8 100644
--- a/include/TwoPole.h
+++ b/include/TwoPole.h
@@ -8,7 +8,7 @@
frequency response while maintaining a nearly
constant filter gain.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -71,17 +71,14 @@ class TwoPole : protected Filter
//! Input one sample to the filter and return one output.
StkFloat tick(StkFloat sample);
- //! Input \e vectorSize samples to the filter and return an equal number of outputs in \e vector.
- StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
-
//! Take a channel of the StkFrames object as inputs to the filter and replace with corresponding outputs.
/*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
+ The \c channel argument should be zero or greater (the first
+ channel is specified by 0). An StkError will be thrown if the \c
+ channel argument is equal to or greater than the number of
channels in the StkFrames object.
*/
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
+ StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
};
#endif
diff --git a/include/TwoZero.h b/include/TwoZero.h
index 605772a..1054a42 100644
--- a/include/TwoZero.h
+++ b/include/TwoZero.h
@@ -8,7 +8,7 @@
frequency response while maintaining a
constant filter gain.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -67,17 +67,14 @@ class TwoZero : protected Filter
//! Input one sample to the filter and return one output.
StkFloat tick(StkFloat sample);
- //! Input \e vectorSize samples to the filter and return an equal number of outputs in \e vector.
- StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
-
//! Take a channel of the StkFrames object as inputs to the filter and replace with corresponding outputs.
/*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
+ The \c channel argument should be zero or greater (the first
+ channel is specified by 0). An StkError will be thrown if the \c
+ channel argument is equal to or greater than the number of
channels in the StkFrames object.
*/
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
+ StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
};
#endif
diff --git a/include/UdpSocket.h b/include/UdpSocket.h
new file mode 100644
index 0000000..c81e6fd
--- /dev/null
+++ b/include/UdpSocket.h
@@ -0,0 +1,72 @@
+/***************************************************/
+/*! \class UdpSocket
+ \brief STK UDP socket server/client class.
+
+ This class provides a uniform cross-platform UDP socket
+ server/client interface. Methods are provided for reading or
+ writing data buffers. The constructor creates a UDP socket and
+ binds it to the specified port. Note that only one socket can be
+ bound to a given port on the same machine.
+
+ UDP sockets provide unreliable, connection-less service. Messages
+ can be lost, duplicated, or received out of order. That said,
+ data transmission tends to be faster than with TCP connections and
+ datagrams are not potentially combined by the underlying system.
+
+ The user is responsible for checking the values returned by the
+ read/write methods. Values less than or equal to zero indicate
+ the occurence of an error.
+
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
+*/
+/***************************************************/
+
+#ifndef STK_UDPSOCKET_H
+#define STK_UDPSOCKET_H
+
+#include "Socket.h"
+
+class UdpSocket : public Socket
+{
+ public:
+ //! Default constructor creates a local UDP socket on port 2006 (or the specified port number).
+ /*!
+ An StkError will be thrown if a socket error occurs during instantiation.
+ */
+ UdpSocket( int port = 2006 );
+
+ //! The class destructor closes the socket instance.
+ ~UdpSocket();
+
+ //! Set the address for subsequent outgoing data sent via the \e writeBuffer() function.
+ /*!
+ An StkError will be thrown if the host is unknown.
+ */
+ void setDestination( int port = 2006, std::string hostname = "localhost" );
+
+ //! Send a buffer to the address specified with the \e setDestination() function. Returns the number of bytes written or -1 if an error occurs.
+ /*!
+ This function will fail if the default address (set with \e setDestination()) is invalid or has not been specified.
+ */
+ int writeBuffer(const void *buffer, long bufferSize, int flags = 0);
+
+ //! Read an input buffer, up to length \e bufferSize. Returns the number of bytes read or -1 if an error occurs.
+ int readBuffer(void *buffer, long bufferSize, int flags = 0);
+
+ //! Write a buffer to the specified socket. Returns the number of bytes written or -1 if an error occurs.
+ int writeBufferTo(const void *buffer, long bufferSize, int port, std::string hostname = "localhost", int flags = 0 );
+
+ protected:
+
+ //! A protected function for use in writing a socket address structure.
+ /*!
+ An StkError will be thrown if the host is unknown.
+ */
+ void setAddress( struct sockaddr_in *address, int port = 2006, std::string hostname = "localhost" );
+
+ struct sockaddr_in address_;
+ bool validAddress_;
+
+};
+
+#endif // defined(STK_UDPSOCKET_H)
diff --git a/include/VoicForm.h b/include/VoicForm.h
index f183a19..1e6bbf1 100644
--- a/include/VoicForm.h
+++ b/include/VoicForm.h
@@ -21,7 +21,7 @@
- Vibrato Gain = 1
- Loudness (Spectral Tilt) = 128
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -81,25 +81,13 @@ class VoicForm : public Instrmnt
//! Stop a note with the given amplitude (speed of decay).
void noteOff(StkFloat amplitude);
- //! Compute one output sample.
- StkFloat tick();
-
- //! Computer \e vectorSize outputs and return them in \e vector.
- StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
-
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
void controlChange(int number, StkFloat value);
protected:
+
+ StkFloat computeSample( void );
+
SingWave *voiced_;
Noise noise_;
Envelope noiseEnv_;
diff --git a/include/Voicer.h b/include/Voicer.h
index 48a90bc..ab5a5ca 100644
--- a/include/Voicer.h
+++ b/include/Voicer.h
@@ -25,7 +25,7 @@
an ensemble. Alternately, control changes can
be sent to all voices on a given channel.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
diff --git a/include/WaveLoop.h b/include/WaveLoop.h
index 8576af1..27d4c2e 100644
--- a/include/WaveLoop.h
+++ b/include/WaveLoop.h
@@ -2,87 +2,89 @@
/*! \class WaveLoop
\brief STK waveform oscillator class.
- This class inherits from WvIn and provides
- audio file looping functionality.
+ This class inherits from FileWvIn and provides audio file looping
+ functionality. Any audio file that can be loaded by FileRead can
+ be looped using this class.
- WaveLoop supports multi-channel data in
- interleaved format. It is important to
- distinguish the tick() methods, which return
- samples produced by averaging across sample
- frames, from the tickFrame() methods, which
- return pointers to multi-channel sample frames.
- For single-channel data, these methods return
- equivalent values.
+ WaveLoop supports multi-channel data. It is important to
+ distinguish the tick() methods, which return samples produced by
+ averaging across sample frames, from the tickFrame() methods,
+ which return references or pointers to multi-channel sample
+ frames.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
#ifndef STK_WAVELOOP_H
#define STK_WAVELOOP_H
-#include "WvIn.h"
+#include "FileWvIn.h"
-class WaveLoop : public WvIn
+class WaveLoop : public FileWvIn
{
public:
- //! Class constructor.
- WaveLoop( std::string fileName, bool raw = false );
+ //! Default constructor.
+ WaveLoop( unsigned long chunkThreshold = 1000000, unsigned long chunkSize = 1024 );
+
+ //! Class constructor that opens a specified file.
+ WaveLoop( std::string fileName, bool raw = false, bool doNormalize = true,
+ unsigned long chunkThreshold = 1000000, unsigned long chunkSize = 1024 );
//! Class destructor.
virtual ~WaveLoop();
+ //! 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 );
+
+ //! 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 aFrequency value
+ 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);
+ void setFrequency( StkFloat frequency );
- //! Increment the read pointer by \e aTime samples, modulo file size.
- void addTime(StkFloat time);
+ //! Increment the read pointer by \e time samples, modulo file size.
+ void addTime( StkFloat time );
- //! Increment current read pointer by \e anAngle, relative to a looping frequency.
+ //! 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);
+ 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 anAngle value
+ size and the current Stk::sampleRate. The \e angle value
is a multiple of file size.
*/
- void addPhaseOffset(StkFloat angle);
-
- //! Return a pointer to the next sample frame of data.
- const StkFloat *tickFrame(void);
-
- //! Read out sample \e frames of data to \e frameVector.
- /*!
- An StkError will be thrown if a file is read incrementally and a read error occurs.
- */
- StkFloat *tickFrame(StkFloat *frameVector, unsigned int frames);
-
- //! Fill the StkFrames object with sample frames of data and return the same reference.
- /*!
- An StkError will be thrown if a file is read incrementally and
- a read error occurs or there is an incompatability between the
- number of channels in the RtWvIn object and that in the StkFrames
- object.
- */
- StkFrames& tickFrame( StkFrames& frames );
+ void addPhaseOffset( StkFloat angle );
protected:
- // Read file data.
- void readData(unsigned long index);
+ virtual void computeFrame( void );
+ StkFrames firstFrame_;
StkFloat phaseOffset_;
};
diff --git a/include/Whistle.h b/include/Whistle.h
index b788f6c..6d29757 100644
--- a/include/Whistle.h
+++ b/include/Whistle.h
@@ -23,7 +23,7 @@
#include "Sphere.h"
#include "Vector3D.h"
#include "Noise.h"
-#include "WaveLoop.h"
+#include "SineWave.h"
#include "OnePole.h"
#include "Envelope.h"
@@ -57,25 +57,12 @@ public:
//! Stop a note with the given amplitude (speed of decay).
void noteOff(StkFloat amplitude);
- //! Compute one output sample.
- StkFloat tick();
-
- //! Computer \e vectorSize outputs and return them in \e vector.
- StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
-
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
//! Perform the control change specified by \e number and \e value (0.0 - 128.0).
void controlChange(int number, StkFloat value);
-protected:
+protected:
+
+ StkFloat computeSample( void );
Vector3D *tempVectorP_;
Vector3D tempVector_;
@@ -85,7 +72,7 @@ protected:
Sphere can_; // Declare a Spherical "can".
Sphere pea_, bumper_; // One spherical "pea", and a spherical "bumper".
- WaveLoop *sine_;
+ SineWave sine_;
StkFloat baseFrequency_;
StkFloat noiseGain_;
diff --git a/include/Wurley.h b/include/Wurley.h
index b5a0e47..deecf08 100644
--- a/include/Wurley.h
+++ b/include/Wurley.h
@@ -26,7 +26,7 @@
type who should worry about this (making
money) worry away.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -53,20 +53,9 @@ class Wurley : public FM
//! Start a note with the given frequency and amplitude.
void noteOn(StkFloat frequency, StkFloat amplitude);
- //! Compute one output sample.
- StkFloat tick();
+ protected:
- //! Computer \e vectorSize outputs and return them in \e vector.
- StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
-
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
+ StkFloat computeSample( void );
};
#endif
diff --git a/include/WvIn.h b/include/WvIn.h
index d60e21d..e3e3c3f 100644
--- a/include/WvIn.h
+++ b/include/WvIn.h
@@ -1,58 +1,27 @@
/***************************************************/
/*! \class WvIn
- \brief STK audio data input base class.
+ \brief STK audio input abstract base class.
- This class provides input support for various
- audio file formats. It also serves as a base
- class for "realtime" streaming subclasses.
+ This class provides common functionality for a variety of audio
+ data input subclasses.
- WvIn loads the contents of an audio file for
- subsequent output. Linear interpolation is
- used for fractional "read rates".
+ WvIn supports multi-channel data. It is important to distinguish
+ the tick() methods, which return samples produced by averaging
+ across sample frames, from the tickFrame() methods, which return
+ references or pointers to multi-channel sample frames.
- WvIn supports multi-channel data in
- interleaved format. It is important to
- distinguish the tick() methods, which return
- samples produced by averaging across sample
- frames, from the tickFrame() methods, which
- return pointers to multi-channel sample
- frames. For single-channel data, these
- methods return equivalent values.
+ Both interleaved and non-interleaved data is supported via the use
+ of StkFrames objects.
- Small files are completely read into local
- memory during instantiation. Large files are
- read incrementally from disk. The file size
- threshold and the increment size values are
- defined in WvIn.h.
-
- When the end of a file is reached, subsequent
- calls to the tick() functions return the data
- values at the end of the file.
-
- WvIn currently supports WAV, AIFF, SND (AU),
- MAT-file (Matlab), and STK RAW file formats.
- Signed integer (8-, 16-, and 32-bit) and floating-
- point (32- and 64-bit) data types are supported.
- Compressed data types are not supported. If using
- MAT-files, data should be saved in an array with
- each data channel filling a matrix row. The sample
- rate for MAT-files is assumed to be 44100 Hz.
-
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
#ifndef STK_WVIN_H
#define STK_WVIN_H
-// Files larger than CHUNK_THRESHOLD will be copied into memory
-// in CHUNK_SIZE increments, rather than completely loaded into
-// a buffer at once.
-
-const unsigned long CHUNK_THRESHOLD = 5000000; // 5 Mb
-const long CHUNK_SIZE = 1024; // sample frames
-
#include "Stk.h"
+#include
class WvIn : public Stk
{
@@ -60,171 +29,59 @@ public:
//! Default constructor.
WvIn();
- //! 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.
- */
- WvIn( std::string fileName, bool raw = false, bool doNormalize = true );
-
//! Class destructor.
virtual ~WvIn();
- //! Open the specified file and load its data.
- /*!
- An StkError will be thrown if the file is not found, its format is
- unknown, or a read error occurs.
- */
- void openFile( std::string fileName, bool raw = false, bool doNormalize = true );
-
- //! If a file is open, close it.
- void closeFile(void);
-
- //! Clear outputs and reset time (file pointer) to zero.
- void reset(void);
-
- //! Normalize data to a maximum of +-1.0.
- /*!
- For large, incrementally loaded files with integer data types,
- normalization is computed relative to the data type maximum.
- No normalization is performed for incrementally loaded files
- with floating-point data types.
- */
- void normalize(void);
-
- //! Normalize data to a maximum of \e +-peak.
- /*!
- For large, incrementally loaded files with integer data types,
- normalization is computed relative to the data type maximum
- (\e peak/maximum). For incrementally loaded files with floating-
- point data types, direct scaling by \e peak is performed.
- */
- void normalize(StkFloat peak);
-
- //! Return the file size in sample frames.
- unsigned long getSize(void) const;
-
- //! Return the number of audio channels in the file.
- unsigned int getChannels(void) const;
-
- //! 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;
-
- //! Query whether reading is complete.
- bool isFinished(void) const;
-
- //! 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 aRate);
-
- //! Increment the read pointer by \e aTime samples.
- virtual void addTime(StkFloat aTime);
-
- //! 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);
+ //! Return the number of audio channels in the data.
+ unsigned int getChannels( void ) const { return data_.channels(); };
//! Return the average across the last output sample frame.
- virtual StkFloat lastOut(void) const;
+ /*!
+ If no file data is loaded, the returned value is 0.0.
+ */
+ StkFloat lastOut( void ) const;
+
+ //! Return an StkFrames reference to the last output sample frame.
+ /*!
+ If no file data is loaded, an empty container is returned.
+ */
+ const StkFrames& lastFrame( void ) const { return lastOutputs_; };
//! Read out the average across one sample frame of data.
/*!
- An StkError will be thrown if a file is read incrementally and a read error occurs.
+ If no file data is loaded, the returned value is 0.0.
*/
- virtual StkFloat tick(void);
-
- //! Read out vectorSize averaged sample frames of data in \e vector.
- /*!
- An StkError will be thrown if a file is read incrementally and a read error occurs.
- */
- virtual StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
+ StkFloat tick( void );
//! Fill a channel of the StkFrames object with averaged sample frames.
/*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if a file
- is read incrementally and a read error occurs or the \c channel
- argument is zero or it is greater than the number of channels in
- the StkFrames object.
+ The \c channel argument should be zero or greater (the first
+ channel is specified by 0). An StkError will be thrown if the \c
+ channel argument is greater than or equal to the number of
+ channels in the StkFrames object. If no file data is loaded, the
+ container is filled with zeroes.
*/
- virtual StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
+ StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
- //! Return a pointer to the last output sample frame.
- virtual const StkFloat *lastFrame(void) const;
-
- //! Return a pointer to the next sample frame of data.
+ //! Fill the StkFrames argument with data and return the same reference.
/*!
- An StkError will be thrown if a file is read incrementally and a read error occurs.
+ An StkError will be thrown if there is an incompatability
+ between the number of channels in the loaded data and that in the
+ StkFrames argument. If no file data is loaded, the container is
+ filled with zeroes.
*/
- virtual const StkFloat *tickFrame(void);
-
- //! Read out sample \e frames of data to \e frameVector.
- /*!
- An StkError will be thrown if a file is read incrementally and a read error occurs.
- */
- virtual StkFloat *tickFrame(StkFloat *frameVector, unsigned int frames);
-
- //! Fill the StkFrames object with sample frames of data and return the same reference.
- /*!
- An StkError will be thrown if a file is read incrementally and
- a read error occurs or if there is an incompatability between the
- number of channels in the WvIn object and that in the StkFrames
- object.
- */
- virtual StkFrames& tickFrame( StkFrames& frames );
+ StkFrames& tickFrame( StkFrames& frames );
protected:
- // Initialize class variables.
- void init( void );
+ // This abstract function must be implemented in all subclasses.
+ // It is used to get around a C++ problem with overloaded virtual
+ // functions.
+ virtual void computeFrame( void ) = 0;
- // Read file data.
- virtual void readData(unsigned long index);
+ StkFrames data_;
+ StkFrames lastOutputs_;
- // Get STK RAW file information.
- bool getRawInfo( const char *fileName );
-
- // 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 );
-
- FILE *fd_;
- StkFloat *data_;
- StkFloat *lastOutputs_;
- bool chunking_;
- bool finished_;
- bool interpolate_;
- bool byteswap_;
- unsigned long fileSize_;
- unsigned long bufferSize_;
- unsigned long dataOffset_;
- unsigned int channels_;
- long chunkPointer_;
- StkFormat dataType_;
- StkFloat fileRate_;
- StkFloat gain_;
- StkFloat time_;
- StkFloat rate_;
};
#endif
diff --git a/include/WvOut.h b/include/WvOut.h
index 815e8cb..5ee2d3b 100644
--- a/include/WvOut.h
+++ b/include/WvOut.h
@@ -1,35 +1,22 @@
/***************************************************/
/*! \class WvOut
- \brief STK audio data output base class.
+ \brief STK audio output abstract base class.
- This class provides output support for various
- audio file formats. It also serves as a base
- class for "realtime" streaming subclasses.
+ This class provides common functionality for a variety of audio
+ data output subclasses.
- WvOut writes samples to an audio file. It
- supports multi-channel data in interleaved
- format. It is important to distinguish the
- tick() methods, which output single samples
- to all channels in a sample frame, from the
- tickFrame() method, which takes a pointer
- to multi-channel sample frame data.
+ WvOut supports multi-channel data. It is important to distinguish
+ the tick() methods, which output single samples to all channels in
+ a sample frame, from the tickFrame() methods, which take a pointer
+ or reference to multi-channel sample frame data.
- WvOut currently supports uncompressed WAV,
- AIFF, AIFC, SND (AU), MAT-file (Matlab), and
- STK RAW file formats. Signed integer (8-,
- 16-, 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.
+ Both interleaved and non-interleaved data is supported via the use
+ of StkFrames objects.
- Currently, WvOut is non-interpolating and the
- output rate is always Stk::sampleRate().
+ Currently, WvOut is non-interpolating and the output rate is
+ always Stk::sampleRate().
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -37,136 +24,67 @@
#define STK_WVOUT_H
#include "Stk.h"
-
-const unsigned long BUFFER_SIZE = 1024; // sample frames
+#include
class WvOut : public Stk
{
public:
- typedef unsigned long FILE_TYPE;
-
- static const FILE_TYPE WVOUT_RAW; /*!< STK RAW file type. */
- static const FILE_TYPE WVOUT_WAV; /*!< WAV file type. */
- static const FILE_TYPE WVOUT_SND; /*!< SND (AU) file type. */
- static const FILE_TYPE WVOUT_AIF; /*!< AIFF file type. */
- static const FILE_TYPE WVOUT_MAT; /*!< Matlab MAT-file type. */
-
//! Default constructor.
WvOut();
- //! 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.
- */
- WvOut( const char *fileName, unsigned int nChannels = 1, FILE_TYPE type = WVOUT_WAV, Stk::StkFormat format = STK_SINT16 );
-
//! Class destructor.
virtual ~WvOut();
- //! 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 openFile( const char *fileName, unsigned int nChannels = 1,
- WvOut::FILE_TYPE type = WVOUT_WAV, Stk::StkFormat format = STK_SINT16 );
-
- //! If a file is open, write out samples in the queue and then close it.
- void closeFile( void );
-
//! Return the number of sample frames output.
- unsigned long getFrames( void ) const;
+ unsigned long getFrameCount( void ) const;
//! Return the number of seconds of data output.
StkFloat getTime( void ) const;
//! Returns \c true if clipping has been detected during output since instantiation or the last reset.
- bool getClipStatus( void ) { return clipping_; };
+ bool clipStatus( void ) { return clipping_; };
//! Reset the clipping status to \c false.
void resetClipStatus( void ) { clipping_ = false; };
//! Output a single sample to all channels in a sample frame.
/*!
- An StkError is thrown if a file write error occurs.
+ An StkError is thrown if an output error occurs.
*/
- virtual void tick(const StkFloat sample);
-
- //! Output each sample in \e vector to all channels in \e vectorSize sample frames.
- /*!
- An StkError is thrown if a file write error occurs.
- */
- virtual void tick( const StkFloat *vector, unsigned int vectorSize );
+ void tick( const StkFloat sample );
//! Output a channel of the StkFrames object to all channels of the WvOut object.
/*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if a file
- write error occurs or the \c channel argument is zero or it is
+ The \c channel argument should be 0 or greater (the first
+ channel is specified by 0). An StkError will be thrown if an
+ output error occurs or if the \c channel argument is equal to or
greater than the number of channels in the StkFrames object.
*/
- virtual void tick( const StkFrames& frames, unsigned int channel = 1 );
+ void tick( const StkFrames& frames, unsigned int channel = 0 );
- //! Output the \e frameVector of sample frames of the given length.
+ //! Output the StkFrames data.
/*!
- An StkError is thrown if a file write error occurs.
- */
- virtual void tickFrame( const StkFloat *frameVector, unsigned int frames = 1);
-
- //! Output the StkFrames data to the WvOut object.
- /*!
- An StkError will be thrown if a file write error occurs or if
+ An StkError will be thrown if an output error occurs or if
there is an incompatability between the number of channels in the
WvOut object and that in the StkFrames object.
*/
- virtual void tickFrame( const StkFrames& frames );
+ void tickFrame( const StkFrames& frames );
protected:
- // Initialize class variables.
- void init( void );
+ // These abstract functions must be implemented in all subclasses.
+ // They are used to get around a C++ problem with overloaded virtual
+ // functions.
+ virtual void computeSample( const StkFloat sample ) = 0;
- // Write data to output file;
- virtual void writeData( unsigned long frames );
+ virtual void computeFrames( const StkFrames& frames ) = 0;
// Check for sample clipping and clamp.
- void clipTest( StkFloat& sample );
+ StkFloat& clipTest( StkFloat& sample );
- // Write STK RAW file header.
- bool setRawFile( const char *fileName );
-
- // Write WAV file header.
- bool setWavFile( const char *fileName );
-
- // Close WAV file, updating the header.
- void closeWavFile( void );
-
- // Write SND (AU) file header.
- bool setSndFile( const char *fileName );
-
- // Close SND file, updating the header.
- void closeSndFile( void );
-
- // Write AIFF file header.
- bool setAifFile( const char *fileName );
-
- // Close AIFF file, updating the header.
- void closeAifFile( void );
-
- // Write MAT-file header.
- bool setMatFile( const char *fileName );
-
- // Close MAT-file, updating the header.
- void closeMatFile( void );
-
- FILE *fd_;
- std::valarray data_;
- FILE_TYPE fileType_;
- StkFormat dataType_;
- unsigned int channels_;
- unsigned long counter_;
- unsigned long totalCount_;
- bool byteswap_;
+ StkFrames data_;
+ unsigned long frameCounter_;
bool clipping_;
};
diff --git a/projects/demo/Makefile.in b/projects/demo/Makefile.in
index ac5d4e5..9f64d42 100644
--- a/projects/demo/Makefile.in
+++ b/projects/demo/Makefile.in
@@ -1,14 +1,14 @@
### STK demo Makefile - for various flavors of unix
-PROGRAMS = demo
+PROGRAMS = demo Md2Skini
RM = /bin/rm
SRC_PATH = ../../src
OBJECT_PATH = @object_path@
vpath %.o $(OBJECT_PATH)
OBJECTS = Stk.o Generator.o Noise.o SubNoise.o Envelope.o ADSR.o \
- Modulate.o SingWave.o \
- WvIn.o WaveLoop.o WvOut.o \
+ Modulate.o SingWave.o SineWave.o FileRead.o FileWrite.o \
+ WvIn.o FileWvIn.o WaveLoop.o WvOut.o FileWvOut.o \
Filter.o OneZero.o OnePole.o PoleZero.o TwoZero.o \
BiQuad.o FormSwep.o Delay.o DelayL.o DelayA.o \
Function.o ReedTable.o JetTable.o BowTable.o \
@@ -39,7 +39,7 @@ LIBRARY += @frameworks@
REALTIME = @realtime@
ifeq ($(REALTIME),yes)
- OBJECTS += RtMidi.o RtAudio.o Thread.o Mutex.o Socket.o
+ OBJECTS += RtMidi.o RtAudio.o Thread.o Mutex.o Socket.o TcpServer.o
DEFS += @audio_apis@
endif
diff --git a/projects/demo/Md2Skini.cpp b/projects/demo/Md2Skini.cpp
index f16c087..41c4f14 100644
--- a/projects/demo/Md2Skini.cpp
+++ b/projects/demo/Md2Skini.cpp
@@ -23,10 +23,16 @@ void usage(void) {
std::cout << " With flag = -f , the output stream is simultaneously\n";
std::cout << " written to the file specified by the optional \n";
std::cout << " (default = test.ski).\n";
+ std::cout << " With flag = -c, MIDI control change messages will not be\n";
+ std::cout << " converted to SKINI-specific named controls.\n";
std::cout << " A MIDI input port can be specified with flag = -p portNumber.\n" << std::endl;
exit(0);
}
+#include
+static void finish( int ignore ){ std::cout << "Type 'Exit' to quit." << std::endl; }
+bool parseSkiniControl = true;
+
void midiCallback( double deltatime, std::vector< unsigned char > *bytes, void *userData )
{
if ( bytes->size() < 2 ) return;
@@ -35,7 +41,7 @@ void midiCallback( double deltatime, std::vector< unsigned char > *bytes, void *
if ( bytes->at(0) > 239 ) return;
register long type = bytes->at(0) & 0xF0;
- register long channel = bytes->at(0) & 0x0F;
+ register int channel = bytes->at(0) & 0x0F;
register long databyte1 = bytes->at(1);
register long databyte2 = 0;
if ( ( type != 0xC0 ) && ( type != 0xD0 ) ) {
@@ -75,56 +81,63 @@ void midiCallback( double deltatime, std::vector< unsigned char > *bytes, void *
case __SK_ControlChange_:
+ if ( parseSkiniControl != true ) {
+ typeName = "ControlChange\t";
+ goto output;
+ }
+
switch( databyte1 ) {
case __SK_PitchChange_:
typeName = "PitchChange\t";
- break;
+ goto output;
case __SK_Volume_:
typeName = "Volume\t";
- break;
+ goto output;
case __SK_ModWheel_:
typeName = "ModWheel\t";
- break;
+ goto output;
case __SK_Breath_:
typeName = "Breath\t\t";
- break;
+ goto output;
case __SK_FootControl_:
typeName = "FootControl\t";
- break;
+ goto output;
case __SK_Portamento_:
typeName = "Portamento\t";
- break;
+ goto output;
case __SK_Balance_:
typeName = "Balance\t";
- break;
+ goto output;
case __SK_Pan_:
typeName = "Pan\t\t";
- break;
+ goto output;
case __SK_Sustain_:
typeName = "Sustain\t";
- break;
+ goto output;
case __SK_Expression_:
typeName = "Expression\t";
- break;
+ goto output;
default:
typeName = "ControlChange\t";
- break;
+ goto output;
}
default:
- typeName = "Unknown\t";
+ typeName = "Unknown\t";
}
+ output:
+
FILE *file = (FILE *) userData;
if ( type == 0xC0 || type == 0xD0 || type == 0xE0 ) { // program change, channel pressure, or pitchbend
fprintf( stdout, "%s %.3f %d %.1f\n", typeName.c_str(), 0.0, channel, (float)databyte1 );
@@ -132,9 +145,16 @@ void midiCallback( double deltatime, std::vector< unsigned char > *bytes, void *
fprintf( file, "%s %.3f %d %.1f\n", typeName.c_str(), deltatime, channel, (float)databyte1 );
}
else if ( type == 0xB0 ) { // control change
+ if ( typeName == "ControlChange\t" ) {
+ fprintf( stdout, "%s %.3f %d %.1f %.1f\n", typeName.c_str(), 0.0, channel, (float)databyte1, (float)databyte2 );
+ if ( file != NULL )
+ fprintf( file, "%s %.3f %d %.1f %.1f\n", typeName.c_str(), deltatime, channel, (float)databyte1, (float)databyte2 );
+ }
+ else {
fprintf( stdout, "%s %.3f %d %.1f\n", typeName.c_str(), 0.0, channel, (float)databyte2 );
if ( file != NULL )
fprintf( file, "%s %.3f %d %.1f\n", typeName.c_str(), deltatime, channel, (float)databyte2 );
+ }
}
else { // noteon, noteoff, aftertouch, and unknown
fprintf( stdout, "%s %.3f %d %.1f %.1f\n", typeName.c_str(), 0.0, channel, (float)databyte1, (float)databyte2 );
@@ -149,6 +169,7 @@ int main( int argc,char *argv[] )
std::string fileName;
RtMidiIn *midiin = 0;
unsigned int port = 0;
+ std::string input;
if ( argc > 5 ) usage();
@@ -172,6 +193,10 @@ int main( int argc,char *argv[] )
if ( i++ >= argc) usage();
port = (unsigned int) atoi( argv[i] );
break;
+
+ case 'c':
+ parseSkiniControl = false;
+ break;
default:
usage();
@@ -219,9 +244,15 @@ int main( int argc,char *argv[] )
// We'll ignore sysex, timing, and active sensing messages.
midiin->ignoreTypes( true, true, true );
- std::cout << "\nReading MIDI input ... press to quit.\n";
- char input;
- std::cin.get(input);
+ // Install an interrupt handler function.
+ (void) signal(SIGINT, finish);
+
+ std::cout << "\nReading MIDI input ... type 'Exit' to quit.\n";
+ while ( input != "Exit" && input != "exit" ) {
+ input.erase();
+ std::cin >> input;
+ std::cout << input << std::endl;
+ }
cleanup:
delete midiin;
diff --git a/projects/demo/demo.cpp b/projects/demo/demo.cpp
index 9ee9fbb..04f3a4f 100644
--- a/projects/demo/demo.cpp
+++ b/projects/demo/demo.cpp
@@ -194,6 +194,10 @@ int main( int argc, char *argv[] )
// specified in the command line, it will override this setting.
Stk::setSampleRate( 44100.0 );
+ // By default, warning messages are not printed. If we want to see
+ // them, we need to specify that here.
+ Stk::showWarnings( true );
+
// Check the command-line arguments for errors and to determine
// the number of WvOut objects to be instantiated (in utilities.cpp).
data.nWvOuts = checkArgs(argc, argv);
@@ -276,12 +280,14 @@ int main( int argc, char *argv[] )
// Shut down the callback and output stream.
#if defined(__STK_REALTIME__)
- try {
- dac->cancelStreamCallback();
- dac->closeStream();
- }
- catch (RtError& error) {
- error.printMessage();
+ if ( data.realtime ) {
+ try {
+ dac->cancelStreamCallback();
+ dac->closeStream();
+ }
+ catch (RtError& error) {
+ error.printMessage();
+ }
}
#endif
diff --git a/projects/demo/demo.dsp b/projects/demo/demo.dsp
index 6c343c8..9f835cb 100644
--- a/projects/demo/demo.dsp
+++ b/projects/demo/demo.dsp
@@ -159,6 +159,22 @@ SOURCE=..\..\src\Envelope.cpp
# End Source File
# Begin Source File
+SOURCE=..\..\src\FileRead.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\FileWrite.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\FileWvIn.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\FileWvOut.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\..\src\Filter.cpp
# End Source File
# Begin Source File
@@ -323,6 +339,10 @@ SOURCE=..\..\src\Simple.cpp
# End Source File
# Begin Source File
+SOURCE=..\..\src\SineWave.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\..\src\SingWave.cpp
# End Source File
# Begin Source File
@@ -355,6 +375,10 @@ SOURCE=..\..\src\SubNoise.cpp
# End Source File
# Begin Source File
+SOURCE=..\..\src\TcpServer.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\..\src\Thread.cpp
# End Source File
# Begin Source File
@@ -479,6 +503,22 @@ SOURCE=..\..\include\Envelope.h
# End Source File
# Begin Source File
+SOURCE=..\..\include\FileRead.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\FileWrite.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\FileWvIn.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\FileWvOut.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\include\Filter.h
# End Source File
# Begin Source File
@@ -643,6 +683,10 @@ SOURCE=..\..\include\Simple.h
# End Source File
# Begin Source File
+SOURCE=..\..\include\SineWave.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\include\SingWave.h
# End Source File
# Begin Source File
@@ -675,6 +719,10 @@ SOURCE=..\..\include\SubNoise.h
# End Source File
# Begin Source File
+SOURCE=..\..\include\TcpServer.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\include\Thread.h
# End Source File
# Begin Source File
diff --git a/projects/demo/tcl/Demo.tcl b/projects/demo/tcl/Demo.tcl
index 01c4efa..fa79ccc 100644
--- a/projects/demo/tcl/Demo.tcl
+++ b/projects/demo/tcl/Demo.tcl
@@ -659,7 +659,7 @@ proc patchChange {value} {
.right.cont4 config -state normal -label "Stick Position"
set preset [expr $value-2400]
if {$preset == 1} {
- .right.cont11 config -state normal -label "Vibrato Gain"
+ .right.cont11 config -state normal -label "Vibrato Rate"
} else {
.right.cont11 config -state disabled -label "Disabled"
}
diff --git a/projects/demo/tcl/Modal.tcl b/projects/demo/tcl/Modal.tcl
index 2f605a5..1003299 100644
--- a/projects/demo/tcl/Modal.tcl
+++ b/projects/demo/tcl/Modal.tcl
@@ -176,7 +176,7 @@ proc noteOff {pitchVal pressVal} {
proc patchChange {value} {
global outID preset
if {$preset == 1} {
- .right.cont11 config -state normal -label "Vibrato Gain"
+ .right.cont11 config -state normal -label "Vibrato Rate"
} else {
.right.cont11 config -state disabled -label "Disabled"
}
diff --git a/projects/demo/utilities.cpp b/projects/demo/utilities.cpp
index 676613e..853c25c 100644
--- a/projects/demo/utilities.cpp
+++ b/projects/demo/utilities.cpp
@@ -128,8 +128,8 @@ void usage(char *function) {
printf(" -im for realtime control input by MIDI (virtual port = 0, default = 1),\n");
#endif
printf(" and Instrument = one of these:\n");
- for (i=0;itick();
+
+ if ( counter++ % 500 == 0 && frequency < 3000.0 ) {
+ frequency *= 1.01;
+ blit->setFrequency( frequency );
+ }
+ }
+
+ return 0;
+}
+
+int main()
+{
+ // Set the global sample rate before creating class instances.
+ Stk::setSampleRate( 44100.0 );
+ Stk::showWarnings( true );
+
+ BlitSaw blit;
+ RtAudio *dac = 0;
+
+ // Figure out how many bytes in an StkFloat and setup the RtAudio object.
+ RtAudioFormat format = ( sizeof(StkFloat) == 8 ) ? RTAUDIO_FLOAT64 : RTAUDIO_FLOAT32;
+ int bufferSize = RT_BUFFER_SIZE;
+ try {
+ dac = new RtAudio(0, 1, 0, 0, format, (int)Stk::sampleRate(), &bufferSize, 4);
+ }
+ catch (RtError& error) {
+ error.printMessage();
+ exit(0);
+ }
+
+ blit.setFrequency( frequency );
+ blit.setHarmonics( 20 );
+
+ try {
+ dac->setStreamCallback(&tick, (void *)&blit);
+ dac->startStream();
+ }
+ catch (RtError &error) {
+ error.printMessage();
+ goto cleanup;
+ }
+
+ // Block waiting here.
+ char keyhit;
+ std::cout << "\nPlaying ... press to quit.\n";
+ std::cin.get(keyhit);
+
+ // Shut down the callback and output stream.
+ try {
+ dac->cancelStreamCallback();
+ dac->closeStream();
+ }
+ catch (RtError &error) {
+ error.printMessage();
+ }
+
+ cleanup:
+
+ delete dac;
+
+ return 0;
+}
diff --git a/projects/examples/crtsine.cpp b/projects/examples/crtsine.cpp
index 9989ba5..68acb9b 100644
--- a/projects/examples/crtsine.cpp
+++ b/projects/examples/crtsine.cpp
@@ -1,6 +1,6 @@
// crtsine.cpp STK tutorial program
-#include "WaveLoop.h"
+#include "SineWave.h"
#include "RtAudio.h"
// This tick() function handles sample computation only. It will be
@@ -8,7 +8,7 @@
// samples.
int tick(char *buffer, int bufferSize, void *dataPointer)
{
- WaveLoop *sine = (WaveLoop *) dataPointer;
+ SineWave *sine = (SineWave *) dataPointer;
register StkFloat *samples = (StkFloat *) buffer;
for ( int i=0; isetFrequency(440.0);
-
- try {
- dac->setStreamCallback(&tick, (void *)sine);
+ dac->setStreamCallback(&tick, (void *)&sine);
dac->startStream();
}
catch (RtError &error) {
@@ -71,7 +63,6 @@ int main()
cleanup:
- delete sine;
delete dac;
return 0;
diff --git a/projects/examples/crtsine.dsp b/projects/examples/crtsine.dsp
index b1ad486..8daa8fb 100755
--- a/projects/examples/crtsine.dsp
+++ b/projects/examples/crtsine.dsp
@@ -49,7 +49,7 @@ BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib dsound.lib /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "crtsine - Win32 Debug"
@@ -65,15 +65,15 @@ LINK32=link.exe
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__LITTLE_ENDIAN__" /D "__WINDOWS_DS__" /YX /FD /GZ /c
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__LITTLE_ENDIAN__" /D "__WINDOWS_DS__" /YX /FD /GZ /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib dsound.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ENDIF
@@ -91,10 +91,26 @@ SOURCE=.\crtsine.cpp
# End Source File
# Begin Source File
+SOURCE=..\..\src\FileRead.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\FileWvIn.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\Generator.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\..\src\RtAudio.cpp
# End Source File
# Begin Source File
+SOURCE=..\..\src\SineWave.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\..\src\Stk.cpp
# End Source File
# Begin Source File
diff --git a/projects/examples/examples.dsw b/projects/examples/examples.dsw
index aa24e97..ea2061a 100644
--- a/projects/examples/examples.dsw
+++ b/projects/examples/examples.dsw
@@ -51,6 +51,42 @@ Package=<4>
###############################################################################
+Project: "grains"=".\grains.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "inetIn"=".\inetIn.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "inetOut"=".\inetOut.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
Project: "io"=".\io.dsp" - Package Owner=<4>
Package=<5>
@@ -75,6 +111,18 @@ Package=<4>
###############################################################################
+Project: "playsmf"=".\playsmf.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
Project: "record"=".\record.dsp" - Package Owner=<4>
Package=<5>
@@ -123,30 +171,6 @@ Package=<4>
###############################################################################
-Project: "tcpIn"=".\tcpIn.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "tcpOut"=".\tcpOut.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
Project: "threebees"=".\threebees.dsp" - Package Owner=<4>
Package=<5>
diff --git a/projects/examples/foursine.cpp b/projects/examples/foursine.cpp
index 3bab6f6..8480b1f 100644
--- a/projects/examples/foursine.cpp
+++ b/projects/examples/foursine.cpp
@@ -1,54 +1,40 @@
// foursine.cpp STK tutorial program
-#include "WaveLoop.h"
-#include "WvOut.h"
+#include "SineWave.h"
+#include "FileWvOut.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;
+ int i;
+ FileWvOut output;
+ SineWave inputs[4];
- // 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;
- }
+ // Set the sine wave frequencies.
+ for ( i=0; i<4; i++ )
+ inputs[i].setFrequency( 220.0 * (i+1) );
// 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 );
+ output.openFile( "foursine.aif", 4, FileWrite::FILE_AIF, Stk::STK_SINT16 );
}
catch (StkError &) {
- goto cleanup;
+ exit(0);
}
// Write two seconds of four sines to the output file
- StkFloat frame[4];
- for ( j=0; j<88200; j++ ) {
- for ( i=0; i<4; i++ )
- frame[i] = inputs[i]->tick();
+ StkFrames frames( 88200, 4 );
+ for ( i=0; i<4; i++ )
+ inputs[i].tick( frames, i );
- output->tickFrame( frame );
- }
+ output.tickFrame( frames );
// Now write the first sine to all four channels for two seconds
- for ( j=0; j<88200; j++ ) {
- output->tick( inputs[0]->tick() );
+ for ( i=0; i<88200; i++ ) {
+ output.tick( inputs[0].tick() );
}
- cleanup:
- for ( i=0; i<4; i++ ) delete inputs[i];
- delete output;
-
return 0;
}
diff --git a/projects/examples/foursine.dsp b/projects/examples/foursine.dsp
index da625b3..75ef26a 100755
--- a/projects/examples/foursine.dsp
+++ b/projects/examples/foursine.dsp
@@ -85,10 +85,34 @@ LINK32=link.exe
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
+SOURCE=..\..\src\FileRead.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\FileWrite.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\FileWvIn.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\FileWvOut.cpp
+# End Source File
+# Begin Source File
+
SOURCE=.\foursine.cpp
# End Source File
# Begin Source File
+SOURCE=..\..\src\Generator.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\SineWave.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\..\src\Stk.cpp
# End Source File
# Begin Source File
@@ -109,6 +133,14 @@ SOURCE=..\..\src\WvOut.cpp
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
+SOURCE=..\..\include\FileWrite.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\FileWvOut.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\include\Stk.h
# End Source File
# Begin Source File
diff --git a/projects/examples/grains.cpp b/projects/examples/grains.cpp
new file mode 100644
index 0000000..0268cbc
--- /dev/null
+++ b/projects/examples/grains.cpp
@@ -0,0 +1,105 @@
+// grains.cpp
+//
+// A simple test program for the STK Granulate class.
+
+#include "Granulate.h"
+#include "RtAudio.h"
+
+// This tick() function handles sample computation only. It will be
+// called automatically when the system needs a new buffer of audio
+// samples.
+int tick(char *buffer, int bufferSize, void *dataPointer)
+{
+ Granulate *grani = (Granulate *) dataPointer;
+ register StkFloat *samples = (StkFloat *) buffer;
+
+ for ( int i=0; itick();
+
+ return 0;
+}
+
+void usage(void) {
+ // Error function in case of incorrect command-line
+ // argument specifications.
+ printf("\nuseage: grains file N dur ramp offset delay stretch ramdomness\n");
+ printf(" where file = a soundfile to granulate,\n");
+ printf(" N = the number of grain voices to use,\n");
+ printf(" dur = the grain duration (ms),\n");
+ printf(" ramp = the envelope percent (0-100),\n");
+ printf(" offset = hop time between grains (ms),\n");
+ printf(" delay = pause time between grains (ms),\n");
+ printf(" stretch = stetch factor (1-1000),\n");
+ printf(" and randomness = factor between 0 - 1.0 to control grain parameter randomness.\n\n");
+ exit(0);
+}
+
+int main( int argc, char *argv[] )
+{
+ // Minimal command-line checking.
+ if (argc != 9) usage();
+ unsigned int N = (unsigned int) atoi(argv[2]);
+ unsigned int duration = (unsigned int) atoi(argv[3]);
+ unsigned int ramp = (unsigned int) atoi(argv[4]);
+ unsigned int offset = (unsigned int) atoi(argv[5]);
+ unsigned int delay = (unsigned int) atoi(argv[6]);
+ unsigned int stretch = (unsigned int) atoi(argv[7]);
+ StkFloat random = (StkFloat) atof(argv[8]);
+
+ // Set the global sample rate before creating class instances.
+ Stk::setSampleRate( 44100.0 );
+
+ RtAudio *dac = 0;
+ Granulate grani;
+ grani.setRandomFactor( random );
+ grani.setStretch( stretch );
+ grani.setGrainParameters( duration, ramp, offset, delay );
+
+ try {
+ grani.openFile( argv[1] );
+ }
+ catch ( StkError& ) {
+ exit(0);
+ }
+ grani.setVoices( N );
+
+ // Figure out how many bytes in an StkFloat and setup the RtAudio object.
+ RtAudioFormat format = ( sizeof(StkFloat) == 8 ) ? RTAUDIO_FLOAT64 : RTAUDIO_FLOAT32;
+ int bufferSize = RT_BUFFER_SIZE;
+ try {
+ dac = new RtAudio(0, 1, 0, 0, format, (int)Stk::sampleRate(), &bufferSize, 4);
+ }
+ catch (RtError& error) {
+ error.printMessage();
+ goto cleanup;
+ }
+
+ try {
+ dac->setStreamCallback(&tick, (void *)&grani);
+ dac->startStream();
+ }
+ catch (RtError &error) {
+ error.printMessage();
+ goto cleanup;
+ }
+
+
+ // Block waiting here.
+ char keyhit;
+ std::cout << "\nPlaying ... press to quit.\n";
+ std::cin.get(keyhit);
+
+ // Shut down the callback and output stream.
+ try {
+ dac->cancelStreamCallback();
+ dac->closeStream();
+ }
+ catch (RtError &error) {
+ error.printMessage();
+ }
+
+ cleanup:
+ delete dac;
+
+ return 0;
+}
diff --git a/projects/examples/tcpOut.dsp b/projects/examples/grains.dsp
old mode 100644
new mode 100755
similarity index 58%
rename from projects/examples/tcpOut.dsp
rename to projects/examples/grains.dsp
index ac608ed..7409b54
--- a/projects/examples/tcpOut.dsp
+++ b/projects/examples/grains.dsp
@@ -1,24 +1,24 @@
-# Microsoft Developer Studio Project File - Name="tcpOut" - Package Owner=<4>
+# Microsoft Developer Studio Project File - Name="grains" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
-CFG=tcpOut - Win32 Debug
+CFG=grains - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
-!MESSAGE NMAKE /f "tcpOut.mak".
+!MESSAGE NMAKE /f "grains.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
-!MESSAGE NMAKE /f "tcpOut.mak" CFG="tcpOut - Win32 Debug"
+!MESSAGE NMAKE /f "grains.mak" CFG="grains - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
-!MESSAGE "tcpOut - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "tcpOut - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "grains - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "grains - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
@@ -28,111 +28,119 @@ CFG=tcpOut - Win32 Debug
CPP=cl.exe
RSC=rc.exe
-!IF "$(CFG)" == "tcpOut - Win32 Release"
+!IF "$(CFG)" == "grains - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "tcpOut___Win32_Release"
-# PROP BASE Intermediate_Dir "tcpOut___Win32_Release"
+# PROP BASE Output_Dir "grains___Win32_Release"
+# PROP BASE Intermediate_Dir "grains___Win32_Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir ""
-# PROP Intermediate_Dir "release"
+# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../include" /D "NDEBUG" /D "__WINDOWS_DS__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__LITTLE_ENDIAN__" /D "__WINDOWS_MM__" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__LITTLE_ENDIAN__" /D "__WINDOWS_DS__" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib /nologo /subsystem:console /machine:I386
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib dsound.lib /nologo /subsystem:console /machine:I386
-!ELSEIF "$(CFG)" == "tcpOut - Win32 Debug"
+!ELSEIF "$(CFG)" == "grains - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "tcpOut___Win32_Debug"
-# PROP BASE Intermediate_Dir "tcpOut___Win32_Debug"
+# PROP BASE Output_Dir "grains___Win32_Debug"
+# PROP BASE Intermediate_Dir "grains___Win32_Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir ""
-# PROP Intermediate_Dir "debug"
+# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../include" /D "_DEBUG" /D "__WINDOWS_DS__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__LITTLE_ENDIAN__" /D "__WINDOWS_MM__" /YX /FD /GZ /c
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__LITTLE_ENDIAN__" /D "__WINDOWS_DS__" /YX /FD /GZ /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib dsound.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
-# Name "tcpOut - Win32 Release"
-# Name "tcpOut - Win32 Debug"
+# Name "grains - Win32 Release"
+# Name "grains - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
-SOURCE=..\..\src\Socket.cpp
+SOURCE=..\..\src\FileRead.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\Generator.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\grains.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\Granulate.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\Noise.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\RtAudio.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\Stk.cpp
# End Source File
-# Begin Source File
-
-SOURCE=.\tcpOut.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\TcpWvOut.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\WvIn.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\WvOut.cpp
-# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
-SOURCE=..\..\include\Socket.h
+SOURCE=..\..\include\FileRead.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\Generator.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\Granulate.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\Noise.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\RtAudio.h
# End Source File
# Begin Source File
SOURCE=..\..\include\Stk.h
# End Source File
-# Begin Source File
-
-SOURCE=..\..\include\TcpWvOut.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\include\WvIn.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\include\WvOut.h
-# End Source File
# End Group
# Begin Group "Resource Files"
diff --git a/projects/examples/inetIn.cpp b/projects/examples/inetIn.cpp
new file mode 100644
index 0000000..7e4ff46
--- /dev/null
+++ b/projects/examples/inetIn.cpp
@@ -0,0 +1,81 @@
+/******************************************/
+/*
+ Example program to read N channels of audio data that are streamed
+ over a network connection.
+
+ by Gary P. Scavone, 2000
+
+ NOTE: This program makes use of blocking audio input/output
+ routines. On systems where the underlying audio API is based on a
+ callback scheme (Macintosh OS-X, Windows ASIO, and Linux JACK),
+ these routines are not fully robust (over/underruns can happen with
+ some frequency). See the STK tutorial for example programs using
+ callback schemes and/or visit the RtAudio tutorial page
+ (http://music.mcgill.ca/~gary/rtaudio/) for more information.
+
+ This program is currently written to play the input data in
+ realtime. However, it is simple to replace the instance of RtWvOut
+ with FileWvOut for writing to a soundfile.
+
+ The streamed data format is assumed to be signed 16-bit integers.
+ However, both InetWvIn and InetWvOut can be initialized to
+ read/write any of the defined StkFormats.
+
+ The class InetWvIn sets up a socket server and waits for a
+ connection. Therefore, this program needs to be started before the
+ streaming client. This program will terminate when the socket
+ connection is closed.
+*/
+/******************************************/
+
+#include "InetWvIn.h"
+#include "RtWvOut.h"
+
+void usage(void) {
+ // Error function in case of incorrect command-line
+ // argument specifications.
+ printf("\nuseage: inetIn N fs \n");
+ printf(" where N = number of channels,\n");
+ printf(" and fs = the data sample rate.\n\n");
+ exit(0);
+}
+
+int main(int argc, char *argv[])
+{
+ // Minimal command-line checking.
+ if (argc != 3) usage();
+
+ Stk::showWarnings( true );
+ Stk::setSampleRate( atof(argv[2]) );
+ int channels = (int) atoi(argv[1]);
+ StkFrames frame( 1, channels );
+
+ // Create instances and pointers.
+ InetWvIn input;
+ RtWvOut *output = 0;
+
+ // Listen for a socket connection.
+ try {
+ //input.listen( 2006, channels, Stk::STK_SINT16, Socket::PROTO_UDP );
+ input.listen( 2006, channels, Stk::STK_SINT16, Socket::PROTO_TCP );
+ }
+ catch (StkError &) {
+ goto cleanup;
+ }
+
+ // Open the realtime output device.
+ try {
+ output = new RtWvOut( channels );
+ }
+ catch (StkError &) {
+ goto cleanup;
+ }
+
+ // Here's the runtime loop.
+ while ( input.isConnected() )
+ output->tickFrame( input.tickFrame( frame ) );
+
+ cleanup:
+ delete output;
+ return 0;
+}
diff --git a/projects/examples/tcpIn.dsp b/projects/examples/inetIn.dsp
old mode 100644
new mode 100755
similarity index 64%
rename from projects/examples/tcpIn.dsp
rename to projects/examples/inetIn.dsp
index 741c8b5..f43b9cb
--- a/projects/examples/tcpIn.dsp
+++ b/projects/examples/inetIn.dsp
@@ -1,24 +1,24 @@
-# Microsoft Developer Studio Project File - Name="tcpIn" - Package Owner=<4>
+# Microsoft Developer Studio Project File - Name="inetIn" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
-CFG=tcpIn - Win32 Debug
+CFG=inetIn - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
-!MESSAGE NMAKE /f "tcpIn.mak".
+!MESSAGE NMAKE /f "inetIn.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
-!MESSAGE NMAKE /f "tcpIn.mak" CFG="tcpIn - Win32 Debug"
+!MESSAGE NMAKE /f "inetIn.mak" CFG="inetIn - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
-!MESSAGE "tcpIn - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "tcpIn - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "inetIn - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "inetIn - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
@@ -28,65 +28,73 @@ CFG=tcpIn - Win32 Debug
CPP=cl.exe
RSC=rc.exe
-!IF "$(CFG)" == "tcpIn - Win32 Release"
+!IF "$(CFG)" == "inetIn - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Output_Dir "inetIn___Win32_Release"
+# PROP BASE Intermediate_Dir "inetIn___Win32_Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir ""
-# PROP Intermediate_Dir "release"
+# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../include" /D "NDEBUG" /D "__WINDOWS_DS__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__LITTLE_ENDIAN__" /D "__WINDOWS_MM__" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_DS__" /D "__LITTLE_ENDIAN__" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib WSock32.lib dsound.lib /nologo /subsystem:console /machine:I386
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib dsound.lib wsock32.lib /nologo /subsystem:console /machine:I386
-!ELSEIF "$(CFG)" == "tcpIn - Win32 Debug"
+!ELSEIF "$(CFG)" == "inetIn - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "tcpIn___Win32_Debug"
-# PROP BASE Intermediate_Dir "tcpIn___Win32_Debug"
+# PROP BASE Output_Dir "inetIn___Win32_Debug"
+# PROP BASE Intermediate_Dir "inetIn___Win32_Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir ""
-# PROP Intermediate_Dir "debug"
+# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../include" /D "_DEBUG" /D "__WINDOWS_DS__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__LITTLE_ENDIAN__" /D "__WINDOWS_MM__" /YX /FD /GZ /c
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_DS__" /D "__LITTLE_ENDIAN__" /YX /FD /GZ /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib WSock32.lib dsound.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib dsound.lib wsock32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
-# Name "tcpIn - Win32 Release"
-# Name "tcpIn - Win32 Debug"
+# Name "inetIn - Win32 Release"
+# Name "inetIn - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
+SOURCE=.\inetIn.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\InetWvIn.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\..\src\Mutex.cpp
# End Source File
# Begin Source File
@@ -107,11 +115,7 @@ SOURCE=..\..\src\Stk.cpp
# End Source File
# Begin Source File
-SOURCE=.\tcpIn.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\TcpWvIn.cpp
+SOURCE=..\..\src\TcpServer.cpp
# End Source File
# Begin Source File
@@ -119,6 +123,10 @@ SOURCE=..\..\src\Thread.cpp
# End Source File
# Begin Source File
+SOURCE=..\..\src\UdpSocket.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\..\src\WvIn.cpp
# End Source File
# Begin Source File
@@ -131,6 +139,10 @@ SOURCE=..\..\src\WvOut.cpp
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
+SOURCE=..\..\include\InetWvIn.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\include\RtAudio.h
# End Source File
# Begin Source File
@@ -139,19 +151,11 @@ SOURCE=..\..\include\RtWvOut.h
# End Source File
# Begin Source File
-SOURCE=..\..\include\Socket.h
-# End Source File
-# Begin Source File
-
SOURCE=..\..\include\Stk.h
# End Source File
# Begin Source File
-SOURCE=..\..\include\TcpWvIn.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\include\Thread.h
+SOURCE=..\..\include\UdpSocket.h
# End Source File
# Begin Source File
diff --git a/projects/examples/inetOut.cpp b/projects/examples/inetOut.cpp
new file mode 100644
index 0000000..5175423
--- /dev/null
+++ b/projects/examples/inetOut.cpp
@@ -0,0 +1,78 @@
+/******************************************/
+/*
+ Example program to output N channels of audio
+ data over a network socket connection.
+
+ by Gary P. Scavone, 2000
+
+ This program will load a specified WAV, SND, AIFF, STK RAW, or
+ MAT-file formatted file. The output data format is set for signed
+ 16-bit integers. However, it is easy to change the InetWvOut
+ setting to any of the other defined StkFormats. If using tcpIn, it
+ will be necessary to change the expected data format there as well.
+
+ The class InetWvOut first attempts to establish a socket connection
+ to a socket server running on port 2006. Therefore, this program
+ needs to be started AFTER the streaming server.
+*/
+/******************************************/
+
+#include "FileWvIn.h"
+#include "InetWvOut.h"
+#include
+
+void usage(void) {
+ // Error function in case of incorrect command-line
+ // argument specifications.
+ printf("\nuseage: inetOut file host \n");
+ printf(" where file = the file to load,\n");
+ printf(" host = the hostname where the receiving\n");
+ printf(" application is running.\n");
+ printf(" and rate = an optional playback rate for the file.\n");
+ printf(" (default = 1.0, can be negative)\n\n");
+ exit(0);
+}
+
+int main(int argc, char *argv[])
+{
+ // Minimal command-line checking.
+ if (argc < 3 || argc > 4) usage();
+
+ FileWvIn input;
+ InetWvOut output;
+
+ // Load the file.
+ try {
+ input.openFile( (char *)argv[1] );
+ }
+ catch (StkError &) {
+ exit(0);
+ }
+
+ // Set the global STK sample rate to the file rate.
+ Stk::setSampleRate( input.getFileRate() );
+
+ // Set input read rate.
+ double rate = 1.0;
+ if ( argc == 4 ) rate = atof(argv[3]);
+ input.setRate( rate );
+
+ // Find out how many channels we have.
+ int channels = input.getChannels();
+ StkFrames frames( 4096, channels );
+
+ // Attempt to connect to the socket server.
+ try {
+ //output.connect( 2006, Socket::PROTO_UDP, (char *)argv[2], channels, Stk::STK_SINT16 );
+ output.connect( 2006, Socket::PROTO_TCP, (char *)argv[2], channels, Stk::STK_SINT16 );
+ }
+ catch (StkError &) {
+ exit(0);
+ }
+
+ // Here's the runtime loop
+ while ( !input.isFinished() )
+ output.tickFrame( input.tickFrame( frames ) );
+
+ return 0;
+}
diff --git a/projects/examples/inetOut.dsp b/projects/examples/inetOut.dsp
new file mode 100755
index 0000000..85995be
--- /dev/null
+++ b/projects/examples/inetOut.dsp
@@ -0,0 +1,162 @@
+# Microsoft Developer Studio Project File - Name="inetOut" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=inetOut - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "inetOut.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "inetOut.mak" CFG="inetOut - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "inetOut - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "inetOut - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "inetOut - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "inetOut___Win32_Release"
+# PROP BASE Intermediate_Dir "inetOut___Win32_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "../../include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_DS__" /D "__LITTLE_ENDIAN__" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF "$(CFG)" == "inetOut - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "inetOut___Win32_Debug"
+# PROP BASE Intermediate_Dir "inetOut___Win32_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_DS__" /D "__LITTLE_ENDIAN__" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "inetOut - Win32 Release"
+# Name "inetOut - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\src\FileRead.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\FileWvIn.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\inetOut.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\InetWvOut.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\Socket.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\Stk.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\TcpClient.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\UdpSocket.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\WvIn.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\WvOut.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\include\FileRead.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\FileWvIn.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\InetWvOut.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\Stk.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\TcpClient.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\WvOut.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/projects/examples/libMakefile.in b/projects/examples/libMakefile.in
index a61039b..e16dff8 100644
--- a/projects/examples/libMakefile.in
+++ b/projects/examples/libMakefile.in
@@ -1,6 +1,6 @@
### STK examples Makefile - for various flavors of unix
-PROGRAMS = sine play record io tcpIn tcpOut sineosc rtsine crtsine bethree controlbee foursine threebees playsmf
+PROGRAMS = sine play record io inetIn inetOut sineosc rtsine crtsine bethree controlbee foursine threebees playsmf grains
RM = /bin/rm
INCLUDE = @include@
@@ -20,7 +20,6 @@ LIBRARY += @frameworks@
REALTIME = @realtime@
ifeq ($(REALTIME),yes)
DEFS += @audio_apis@
- DEFS += @midiator@
endif
RAWWAVES = @rawwaves@
@@ -39,7 +38,6 @@ clean :
strip :
strip $(PROGRAMS)
-#play: play.cpp Stk.o WvIn.o WvOut.o RtWvOut.o RtAudio.o
play: play.cpp
$(CC) $(CFLAGS) $(DEFS) -o play play.cpp -L../../src $(LIBRARY) -lstk
@@ -52,11 +50,11 @@ sine: sine.cpp
io: io.cpp
$(CC) $(CFLAGS) $(DEFS) -o io io.cpp -L../../src $(LIBRARY) -lstk
-tcpIn: tcpIn.cpp
- $(CC) $(CFLAGS) $(DEFS) -o tcpIn tcpIn.cpp -L../../src $(LIBRARY) -lstk
+inetIn: inetIn.cpp
+ $(CC) $(CFLAGS) $(DEFS) -o inetIn inetIn.cpp -L../../src $(LIBRARY) -lstk
-tcpOut: tcpOut.cpp
- $(CC) $(CFLAGS) $(DEFS) -o tcpOut tcpOut.cpp -L../../src $(LIBRARY) -lstk
+inetOut: inetOut.cpp
+ $(CC) $(CFLAGS) $(DEFS) -o inetOut inetOut.cpp -L../../src $(LIBRARY) -lstk
sineosc: sineosc.cpp
$(CC) $(CFLAGS) $(DEFS) -o sineosc sineosc.cpp -L../../src $(LIBRARY) -lstk
@@ -82,3 +80,6 @@ threebees: threebees.cpp
playsmf: playsmf.cpp
$(CC) $(CFLAGS) $(DEFS) -o playsmf playsmf.cpp -L../../src $(LIBRARY) -lstk
+grains: grains.cpp
+ $(CC) $(CFLAGS) $(DEFS) -o grains grains.cpp -L../../src $(LIBRARY) -lstk
+
diff --git a/projects/examples/play.cpp b/projects/examples/play.cpp
index a3a64b8..b113a91 100644
--- a/projects/examples/play.cpp
+++ b/projects/examples/play.cpp
@@ -13,7 +13,7 @@
*/
/******************************************/
-#include "WvIn.h"
+#include "FileWvIn.h"
#include "RtAudio.h"
#include
@@ -40,7 +40,7 @@ void usage(void) {
// samples.
int tick(char *buffer, int bufferSize, void *dataPointer)
{
- WvIn *input = (WvIn *) dataPointer;
+ FileWvIn *input = (FileWvIn *) dataPointer;
register StkFloat *samples = (StkFloat *) buffer;
input->tickFrame( frames );
@@ -65,11 +65,11 @@ int main(int argc, char *argv[])
// Initialize our WvIn and RtAudio pointers.
RtAudio *dac = 0;
- WvIn *input = 0;
+ FileWvIn *input = 0;
// Try to load the soundfile.
try {
- input = new WvIn( argv[1] );
+ input = new FileWvIn( argv[1] );
}
catch (StkError &) {
exit(0);
diff --git a/projects/examples/play.dsp b/projects/examples/play.dsp
index c5fcb12..2d2c8f5 100644
--- a/projects/examples/play.dsp
+++ b/projects/examples/play.dsp
@@ -87,6 +87,14 @@ LINK32=link.exe
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
+SOURCE=..\..\src\FileRead.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\FileWvIn.cpp
+# End Source File
+# Begin Source File
+
SOURCE=.\play.cpp
# End Source File
# Begin Source File
diff --git a/projects/examples/playsmf.cpp b/projects/examples/playsmf.cpp
index 5dc1466..ec91312 100644
--- a/projects/examples/playsmf.cpp
+++ b/projects/examples/playsmf.cpp
@@ -8,7 +8,6 @@
#include "MidiFileIn.h"
#include "RtMidi.h"
#include
-#include
bool done = false;
static void finish(int ignore){ done = true; }
diff --git a/projects/examples/playsmf.dsp b/projects/examples/playsmf.dsp
new file mode 100644
index 0000000..2758488
--- /dev/null
+++ b/projects/examples/playsmf.dsp
@@ -0,0 +1,126 @@
+# Microsoft Developer Studio Project File - Name="playsmf" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=playsmf - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "playsmf.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "playsmf.mak" CFG="playsmf - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "playsmf - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "playsmf - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "playsmf - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "../../include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__LITTLE_ENDIAN__" /D "__WINDOWS_DS__" /D "__WINDOWS_MM__" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF "$(CFG)" == "playsmf - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "playsmf___Win32_Debug"
+# PROP BASE Intermediate_Dir "playsmf___Win32_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__LITTLE_ENDIAN__" /D "__WINDOWS_DS__" /D "__WINDOWS_MM__" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "playsmf - Win32 Release"
+# Name "playsmf - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\src\MidiFileIn.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\playsmf.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\RtMidi.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\Stk.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\include\MidiFileIn.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\RtMidi.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\Stk.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/projects/examples/record.cpp b/projects/examples/record.cpp
index 928bd2f..0b273c3 100644
--- a/projects/examples/record.cpp
+++ b/projects/examples/record.cpp
@@ -23,7 +23,7 @@
/******************************************/
#include "RtWvIn.h"
-#include "WvOut.h"
+#include "FileWvOut.h"
void usage(void) {
// Error function in case of incorrect command-line
@@ -41,17 +41,20 @@ int main(int argc, char *argv[])
// minimal command-line checking
if (argc != 5) usage();
+ Stk::showWarnings( true );
+
int channels = (int) atoi(argv[1]);
double sample_rate = atof(argv[4]);
double time = atof(argv[3]);
long samples, i;
+ StkFrames frame( 1, channels );
// Set the global sample rate.
Stk::setSampleRate( sample_rate );
// Initialize our WvIn/WvOut pointers.
RtWvIn *input = 0;
- WvOut *output = 0;
+ FileWvOut *output = 0;
// Open the realtime input device
try {
@@ -63,7 +66,7 @@ int main(int argc, char *argv[])
// Open the soundfile for output.
try {
- output = new WvOut(argv[2], channels, WvOut::WVOUT_WAV);
+ output = new FileWvOut(argv[2], channels, FileWrite::FILE_WAV);
}
catch (StkError &) {
goto cleanup;
@@ -71,8 +74,9 @@ int main(int argc, char *argv[])
// Here's the runtime loop
samples = (long) (time * Stk::sampleRate());
- for ( i=0; itickFrame( input->tickFrame() );
+ for ( i=0; itickFrame( input->tickFrame( frame ) );
+ }
cleanup:
delete input;
diff --git a/projects/examples/record.dsp b/projects/examples/record.dsp
index e837bd9..40fb1ac 100644
--- a/projects/examples/record.dsp
+++ b/projects/examples/record.dsp
@@ -89,6 +89,14 @@ LINK32=link.exe
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
+SOURCE=..\..\src\FileWrite.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\FileWvOut.cpp
+# End Source File
+# Begin Source File
+
SOURCE=.\record.cpp
# End Source File
# Begin Source File
diff --git a/projects/examples/rtsine.cpp b/projects/examples/rtsine.cpp
index 40012b4..a9324c2 100644
--- a/projects/examples/rtsine.cpp
+++ b/projects/examples/rtsine.cpp
@@ -1,6 +1,6 @@
// rtsine.cpp STK tutorial program
-#include "WaveLoop.h"
+#include "SineWave.h"
#include "RtWvOut.h"
int main()
@@ -8,27 +8,24 @@ int main()
// Set the global sample rate before creating class instances.
Stk::setSampleRate( 44100.0 );
- WaveLoop *sine = 0;
+ SineWave sine;
RtWvOut *dac = 0;
try {
- // Define and load the sine wave file
- sine = new WaveLoop( "rawwaves/sinewave.raw", true );
-
// Define and open the default realtime output device for one-channel playback
dac = new RtWvOut(1);
}
catch (StkError &) {
- goto cleanup;
+ exit(0);
}
- sine->setFrequency(440.0);
+ sine.setFrequency(440.0);
// Play the oscillator for 40000 samples
int i;
for ( i=0; i<40000; i++ ) {
try {
- dac->tick( sine->tick() );
+ dac->tick( sine.tick() );
}
catch (StkError &) {
goto cleanup;
@@ -36,7 +33,6 @@ int main()
}
cleanup:
- delete sine;
delete dac;
return 0;
diff --git a/projects/examples/rtsine.dsp b/projects/examples/rtsine.dsp
index 285a933..acaf1dd 100755
--- a/projects/examples/rtsine.dsp
+++ b/projects/examples/rtsine.dsp
@@ -87,6 +87,18 @@ LINK32=link.exe
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
+SOURCE=..\..\src\FileRead.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\FileWvIn.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\Generator.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\..\src\RtAudio.cpp
# End Source File
# Begin Source File
@@ -99,6 +111,10 @@ SOURCE=..\..\src\RtWvOut.cpp
# End Source File
# Begin Source File
+SOURCE=..\..\src\SineWave.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\..\src\Stk.cpp
# End Source File
# Begin Source File
@@ -119,6 +135,14 @@ SOURCE=..\..\src\WvOut.cpp
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
+SOURCE=..\..\include\FileRead.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\FileWvIn.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\include\RtAudio.h
# End Source File
# Begin Source File
diff --git a/projects/examples/sine.cpp b/projects/examples/sine.cpp
index 933ad3c..5aa3bc9 100644
--- a/projects/examples/sine.cpp
+++ b/projects/examples/sine.cpp
@@ -6,14 +6,14 @@
By default, the program will write an
N channel WAV file. However, it is
simple to change the file type argument
- in the WvOut constructor.
+ in the FileWvOut constructor.
By Gary P. Scavone, 2000 - 2002.
*/
/******************************************/
-#include "WaveLoop.h"
-#include "WvOut.h"
+#include "SineWave.h"
+#include "FileWvOut.h"
#include
void usage(void) {
@@ -31,7 +31,6 @@ int
main(int argc, char *argv[])
{
float base_freq = 220.0;
- int samples;
int i;
// Minimal command-line checking.
@@ -41,55 +40,47 @@ main(int argc, char *argv[])
double time = atof(argv[3]);
double srate = atof(argv[4]);
- // Initialize our object and data pointers.
- WvOut *output = 0;
- StkFloat *vector = 0;
- WaveLoop **oscs = (WaveLoop **) malloc( channels * sizeof(WaveLoop *) );
+ // Create our object instances.
+ FileWvOut output;
+ SineWave **oscs = (SineWave **) malloc( channels * sizeof(SineWave *) );
for (i=0; isetFrequency( base_freq + i*(45.0) );
- // Define and open the soundfile for output. Other file
- // format options include: WVOUT_SND, WVOUT_AIF, WVOUT_MAT,
- // and WVOUT_RAW. Other data type options include:
- // STK_SINT8, STK_SINT32, StkFloat32, and StkFloat64.
+ long nFrames = (long) ( time * Stk::sampleRate() );
+ StkFrames frames( nFrames, channels );
+
+ // Open the soundfile for output. Other file format options
+ // include: FILE_SND, FILE_AIF, FILE_MAT, and FILE_RAW. Other data
+ // type options include: STK_SINT8, STK_SINT32, StkFloat32, and
+ // StkFloat64.
try {
- output = new WvOut( argv[2], channels, WvOut::WVOUT_WAV, Stk::STK_SINT16 );
+ output.openFile( argv[2], channels, FileWrite::FILE_WAV, Stk::STK_SINT16 );
}
catch (StkError &) {
goto cleanup;
}
- // Here's the runtime loop
- samples = (int) ( time * Stk::sampleRate() );
- vector = (StkFloat *) new StkFloat[channels];
- for ( i=0; itick();
- }
- output->tickFrame(vector);
- }
+ // Here's the runtime code ... no loop
+ for ( i=0; itick( frames, i );
+
+ output.tickFrame( frames );
cleanup:
- for (i=0; isetFrequency( 440.0 );
+ input.setFrequency( 440.0 );
// Run the oscillator for 40000 samples, writing to the output file
int i;
for ( i=0; i<40000; i++ ) {
try {
- output->tick( input->tick() );
+ output.tick( input.tick() );
}
catch ( StkError & ) {
- goto cleanup;
+ exit(0);
}
}
- cleanup:
- delete input;
- delete output;
-
return 0;
}
diff --git a/projects/examples/sineosc.dsp b/projects/examples/sineosc.dsp
index 0f4c9a8..c2c3f29 100755
--- a/projects/examples/sineosc.dsp
+++ b/projects/examples/sineosc.dsp
@@ -86,6 +86,26 @@ LINK32=link.exe
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
+SOURCE=..\..\src\FileRead.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\FileWrite.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\FileWvIn.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\FileWvOut.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\Generator.cpp
+# End Source File
+# Begin Source File
+
SOURCE=.\sineosc.cpp
# End Source File
# Begin Source File
@@ -110,6 +130,10 @@ SOURCE=..\..\src\WvOut.cpp
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
+SOURCE=..\..\include\Generator.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\include\Stk.h
# End Source File
# Begin Source File
diff --git a/projects/examples/tcpIn.cpp b/projects/examples/tcpIn.cpp
deleted file mode 100644
index 187c02d..0000000
--- a/projects/examples/tcpIn.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-/******************************************/
-/*
- Example program to read N channels of audio
- data that are streamed over a TCP network
- connection.
-
- by Gary P. Scavone, 2000
-
- NOTE: This program makes use of blocking audio
- input/output routines. On systems where the
- underlying audio API is based on a callback scheme
- (Macintosh OS-X, Windows ASIO, and Linux JACK), these
- routines are not fully robust (over/underruns can
- happen with some frequency). See the STK tutorial
- for example programs using callback schemes and/or
- visit the RtAudio tutorial page
- (http://music.mcgill.ca/~gary/rtaudio/) for more
- information.
-
- This program is currently written to play
- the input data in realtime. However, it
- is simple to replace the instance of
- RtWvOut with WvOut for writing to a
- soundfile.
-
- The streamed data format is assumed to be
- signed 16-bit integers. However, both
- TcpWvIn and TcpWvOut can be initialized
- to read/write any of the defined StkFormats.
-
- The class TcpWvIn sets up a socket server
- and waits for a connection. Therefore,
- this program needs to be started before
- the streaming client. This program will
- terminate when the socket connection is
- closed.
-*/
-/******************************************/
-
-#include "TcpWvIn.h"
-#include "RtWvOut.h"
-
-void usage(void) {
- // Error function in case of incorrect command-line
- // argument specifications.
- printf("\nuseage: tcpIn N fs \n");
- printf(" where N = number of channels,\n");
- printf(" and fs = the data sample rate.\n\n");
- exit(0);
-}
-
-int main(int argc, char *argv[])
-{
- // Minimal command-line checking.
- if (argc != 3) usage();
-
- Stk::setSampleRate( atof(argv[2]) );
- int channels = (int) atoi(argv[1]);
-
- // Initialize the object pointers.
- RtWvOut *output = 0;
- TcpWvIn *input = 0;
-
- // Instantiate the TcpWvIn object.
- try {
- input = new TcpWvIn();
- input->listen( channels, Stk::STK_SINT16 );
- }
- catch (StkError &) {
- goto cleanup;
- }
-
- // Open the realtime output device.
- try {
- output = new RtWvOut(channels);
- }
- catch (StkError &) {
- goto cleanup;
- }
-
- // Here's the runtime loop.
- while ( input->isConnected() )
- output->tickFrame( input->tickFrame() );
-
- cleanup:
- delete input;
- delete output;
- return 0;
-}
diff --git a/projects/examples/tcpOut.cpp b/projects/examples/tcpOut.cpp
deleted file mode 100644
index 6bebf8a..0000000
--- a/projects/examples/tcpOut.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-/******************************************/
-/*
- Example program to output N channels of audio
- data over a TCP network socket connection.
-
- by Gary P. Scavone, 2000
-
- This program will load a specified WAV,
- SND, AIFF, STK RAW, or MAT-file formatted
- file. The output data format is set for
- signed 16-bit integers. However, it is
- easy to change the TcpWvOut setting to
- any of the other defined StkFormats.
- If using tcpIn, it will be necessary to
- change the expected data format there
- as well.
-
- The class StrmWvOut first attempts to
- establish a socket connection to a socket
- server running on port 2006. Therefore,
- this program needs to be started AFTER the
- streaming server.
-*/
-/******************************************/
-
-#include "WvIn.h"
-#include "TcpWvOut.h"
-#include
-
-void usage(void) {
- // Error function in case of incorrect command-line
- // argument specifications.
- printf("\nuseage: tcpOut file host \n");
- printf(" where file = the file to load,\n");
- printf(" host = the hostname where the receiving\n");
- printf(" application is running.\n");
- printf(" and rate = an optional playback rate for the file.\n");
- printf(" (default = 1.0, can be negative)\n\n");
- exit(0);
-}
-
-int main(int argc, char *argv[])
-{
- // Minimal command-line checking.
- if (argc < 3 || argc > 4) usage();
-
- // Initialize the object pointers.
- TcpWvOut *output = 0;
- WvIn *input = 0;
-
- // Load the file.
- try {
- input = new WvIn( (char *)argv[1] );
- }
- catch (StkError &) {
- exit(0);
- }
-
- // Set the global STK sample rate to the file rate.
- Stk::setSampleRate( input->getFileRate() );
-
- // Set input read rate.
- double rate = 1.0;
- if ( argc == 4 ) rate = atof(argv[3]);
- input->setRate( rate );
-
- // Find out how many channels we have.
- int channels = input->getChannels();
-
- // Define and open the output device
- try {
- output = new TcpWvOut(2006, (char *)argv[2], channels, Stk::STK_SINT16);
- }
- catch (StkError &) {
- goto cleanup;
- }
-
- // Here's the runtime loop
- while ( !input->isFinished() )
- output->tickFrame( input->tickFrame() );
-
- cleanup:
- delete input;
- delete output;
- return 0;
-}
diff --git a/projects/examples/threebees.dsp b/projects/examples/threebees.dsp
index b0d3c3f..773e0e2 100755
--- a/projects/examples/threebees.dsp
+++ b/projects/examples/threebees.dsp
@@ -99,6 +99,14 @@ SOURCE=..\..\src\Envelope.cpp
# End Source File
# Begin Source File
+SOURCE=..\..\src\FileRead.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\FileWvIn.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\..\src\Filter.cpp
# End Source File
# Begin Source File
@@ -135,6 +143,10 @@ SOURCE=..\..\src\RtWvOut.cpp
# End Source File
# Begin Source File
+SOURCE=..\..\src\SineWave.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\..\src\SKINI.cpp
# End Source File
# Begin Source File
@@ -147,6 +159,10 @@ SOURCE=..\..\src\Stk.cpp
# End Source File
# Begin Source File
+SOURCE=..\..\src\TcpServer.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\..\src\Thread.cpp
# End Source File
# Begin Source File
diff --git a/projects/ragamatic/Drone.cpp b/projects/ragamatic/Drone.cpp
index 836e933..bb424a1 100644
--- a/projects/ragamatic/Drone.cpp
+++ b/projects/ragamatic/Drone.cpp
@@ -13,13 +13,13 @@
Stanford, bearing the names of Karplus and/or
Strong.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
#include "Drone.h"
-Drone :: Drone(StkFloat lowestFrequency)
+Drone :: Drone( StkFloat lowestFrequency )
{
length_ = (unsigned long) (Stk::sampleRate() / lowestFrequency + 1);
loopGain_ = 0.999;
@@ -39,7 +39,7 @@ void Drone :: clear()
loopFilter_.clear();
}
-void Drone :: setFrequency(StkFloat frequency)
+void Drone :: setFrequency( StkFloat frequency )
{
StkFloat freakency = frequency;
if ( frequency <= 0.0 ) {
@@ -59,12 +59,12 @@ void Drone :: setFrequency(StkFloat frequency)
if ( loopGain_ >= 1.0 ) loopGain_ = 0.99999;
}
-void Drone :: pluck(StkFloat amplitude)
+void Drone :: pluck( StkFloat amplitude )
{
envelope_.keyOn();
}
-void Drone :: noteOn(StkFloat frequency, StkFloat amplitude)
+void Drone :: noteOn( StkFloat frequency, StkFloat amplitude )
{
this->setFrequency( frequency );
this->pluck( amplitude );
@@ -75,7 +75,7 @@ void Drone :: noteOn(StkFloat frequency, StkFloat amplitude)
#endif
}
-void Drone :: noteOff(StkFloat amplitude)
+void Drone :: noteOff( StkFloat amplitude )
{
loopGain_ = 1.0 - amplitude;
if ( loopGain_ < 0.0 ) {
@@ -95,19 +95,11 @@ void Drone :: noteOff(StkFloat amplitude)
#endif
}
-StkFloat Drone :: tick()
+StkFloat Drone :: computeSample()
{
// Here's the whole inner loop of the instrument!!
- lastOutput_ = delayLine_.tick( loopFilter_.tick( delayLine_.lastOut() * loopGain_ ) + (0.005 * envelope_.tick() * noise_.tick()));
+ lastOutput_ = delayLine_.tick( loopFilter_.tick( delayLine_.lastOut() * loopGain_ )
+ + (0.005 * envelope_.tick() * noise_.tick()));
return lastOutput_;
}
-StkFloat *Drone :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Instrmnt::tick( vector, vectorSize );
-}
-
-StkFrames& Drone :: tick( StkFrames& frames, unsigned int channel )
-{
- return Instrmnt::tick( frames, channel );
-}
diff --git a/projects/ragamatic/Drone.h b/projects/ragamatic/Drone.h
index 04cfa89..540c33f 100644
--- a/projects/ragamatic/Drone.h
+++ b/projects/ragamatic/Drone.h
@@ -13,7 +13,7 @@
Stanford, bearing the names of Karplus and/or
Strong.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -50,22 +50,10 @@ class Drone : public Instrmnt
//! Stop a note with the given amplitude (speed of decay).
virtual void noteOff(StkFloat amplitude);
- //! Compute one output sample.
- virtual StkFloat tick();
+ protected:
- //! Computer \e vectorSize outputs and return them in \e vector.
- virtual StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
+ StkFloat computeSample( void );
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- virtual StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
- protected:
DelayA delayLine_;
OneZero loopFilter_;
ADSR envelope_;
diff --git a/projects/ragamatic/Makefile.in b/projects/ragamatic/Makefile.in
index 1fe8d89..6ed4301 100644
--- a/projects/ragamatic/Makefile.in
+++ b/projects/ragamatic/Makefile.in
@@ -10,7 +10,7 @@ OBJECTS = Stk.o Generator.o Noise.o Envelope.o ADSR.o \
Filter.o DelayA.o Delay.o \
OnePole.o OneZero.o Skini.o \
Tabla.o Instrmnt.o Sitar.o \
- Drone.o VoicDrum.o WvOut.o WvIn.o \
+ Drone.o VoicDrum.o FileRead.o WvOut.o WvIn.o FileWvIn.o \
Effect.o JCRev.o Messager.o
INCLUDE = @include@
@@ -29,7 +29,7 @@ LIBRARY += @frameworks@
REALTIME = @realtime@
ifeq ($(REALTIME),yes)
- OBJECTS += RtMidi.o RtAudio.o RtWvOut.o Thread.o Mutex.o Socket.o
+ OBJECTS += RtMidi.o RtAudio.o RtWvOut.o Thread.o Mutex.o Socket.o TcpServer.o
DEFS += @audio_apis@
endif
diff --git a/projects/ragamatic/Tabla.cpp b/projects/ragamatic/Tabla.cpp
index 4e284b6..da2446f 100644
--- a/projects/ragamatic/Tabla.cpp
+++ b/projects/ragamatic/Tabla.cpp
@@ -2,39 +2,49 @@
/*! \class Tabla
\brief STK tabla drum class.
- This class implements a drum sampling
- synthesizer using WvIn objects and one-pole
- filters. The drum rawwave files are sampled
- at 22050 Hz, but will be appropriately
- interpolated for other sample rates. You can
- specify the maximum polyphony (maximum number
- of simultaneous voices) in Drummer.h.
+ This class implements a drum sampling synthesizer using FileWvIn
+ objects and one-pole filters. The drum rawwave files are sampled
+ at 22050 Hz, but will be appropriately interpolated for other
+ sample rates. You can specify the maximum polyphony (maximum
+ number of simultaneous voices) in Tabla.h.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
#include "Tabla.h"
-#include
+#include
Tabla :: Tabla() : Instrmnt()
{
- for ( int i=0; i (TABLA_POLYPHONY, -1);
+ soundNumber_ = std::vector (TABLA_POLYPHONY, -1);
}
Tabla :: ~Tabla()
{
- int i;
- for ( i=0; i= 0 ) {
- // Reset this sound.
- waves_[waveIndex]->reset();
- filters_[waveIndex]->setPole( 0.999 - (gain * 0.6) );
- filters_[waveIndex]->setGain( gain );
- }
- else {
- if ( nSounding_ == TABLA_POLYPHONY ) {
- // If we're already at maximum polyphony, then preempt the oldest voice.
- delete waves_[0];
- filters_[0]->clear();
- OnePole *tempFilt = filters_[0];
- // Re-order the list.
- for ( i=0; inormalize(0.4);
+ if ( iWave == TABLA_POLYPHONY ) { // This note number is not currently loaded.
+ if ( nSounding_ < TABLA_POLYPHONY ) {
+ for ( iWave=0; iWave soundOrder_[iWave] )
+ soundOrder_[j] -= 1;
+ }
+ }
+ soundOrder_[iWave] = nSounding_ - 1;
+ soundNumber_[iWave] = noteNumber;
+
+ // Concatenate the rawwave path to the rawwave file
+ waves_[iWave].openFile( (std::string("rawwaves/") + tablaWaves[ noteNumber ]).c_str(), true );
if ( Stk::sampleRate() != 22050.0 )
- waves_[nSounding_-1]->setRate( 22050.0 / Stk::sampleRate() );
- filters_[nSounding_-1]->setPole( 0.999 - (gain * 0.6) );
- filters_[nSounding_-1]->setGain( gain );
+ waves_[iWave].setRate( 22050.0 / Stk::sampleRate() );
+ filters_[iWave].setPole( 0.999 - (gain * 0.6) );
+ filters_[iWave].setGain( gain );
}
#if defined(_STK_DEBUG_)
errorString_ << "Tabla::noteOn: number sounding = " << nSounding_ << '\n';
- for (i=0; isetGain( amplitude * 0.01 );
+ while ( i < nSounding_ ) filters_[i++].setGain( amplitude * 0.01 );
}
-StkFloat Tabla :: tick()
+StkFloat Tabla :: computeSample()
{
- OnePole *tempFilt;
-
- int j, i = 0;
lastOutput_ = 0.0;
- while ( i < nSounding_ ) {
- if ( waves_[i]->isFinished() ) {
- delete waves_[i];
- tempFilt = filters_[i];
- // Re-order the list.
- for ( j=i; j= 0 ) {
+ if ( waves_[i].isFinished() ) {
+ // Re-order the list.
+ for ( int j=0; j soundOrder_[i] )
+ soundOrder_[j] -= 1;
+ }
+ soundOrder_[i] = -1;
+ nSounding_--;
}
- filters_[j] = tempFilt;
- filters_[j]->clear();
- sounding_[j] = -1;
- nSounding_ -= 1;
- i -= 1;
+ else
+ lastOutput_ += filters_[i].tick( waves_[i].tick() );
}
- else
- lastOutput_ += filters_[i]->tick( waves_[i]->tick() );
- i++;
}
return lastOutput_;
}
-StkFloat *Tabla :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Instrmnt::tick( vector, vectorSize );
-}
-
-StkFrames& Tabla :: tick( StkFrames& frames, unsigned int channel )
-{
- return Instrmnt::tick( frames, channel );
-}
diff --git a/projects/ragamatic/Tabla.h b/projects/ragamatic/Tabla.h
index 45afc7c..152c7ff 100644
--- a/projects/ragamatic/Tabla.h
+++ b/projects/ragamatic/Tabla.h
@@ -2,15 +2,13 @@
/*! \class Tabla
\brief STK tabla drum class.
- This class implements a drum sampling
- synthesizer using WvIn objects and one-pole
- filters. The drum rawwave files are sampled
- at 22050 Hz, but will be appropriately
- interpolated for other sample rates. You can
- specify the maximum polyphony (maximum number
- of simultaneous voices) in Drummer.h.
+ This class implements a drum sampling synthesizer using FileWvIn
+ objects and one-pole filters. The drum rawwave files are sampled
+ at 22050 Hz, but will be appropriately interpolated for other
+ sample rates. You can specify the maximum polyphony (maximum
+ number of simultaneous voices) in Tabla.h.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -18,7 +16,7 @@
#define STK_TABLA_H
#include "Instrmnt.h"
-#include "WvIn.h"
+#include "FileWvIn.h"
#include "OnePole.h"
const int TABLA_NUMWAVES = 15;
@@ -39,25 +37,14 @@ class Tabla : public Instrmnt
//! Stop a note with the given amplitude (speed of decay).
void noteOff(StkFloat amplitude);
- //! Compute one output sample.
- StkFloat tick();
+ protected:
- //! Computer \e vectorSize outputs and return them in \e vector.
- StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
+ StkFloat computeSample( void );
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
- protected:
- WvIn *waves_[TABLA_POLYPHONY];
- OnePole *filters_[TABLA_POLYPHONY];
- int sounding_[TABLA_POLYPHONY];
+ FileWvIn waves_[TABLA_POLYPHONY];
+ OnePole filters_[TABLA_POLYPHONY];
+ std::vector soundOrder_;
+ std::vector soundNumber_;
int nSounding_;
};
diff --git a/projects/ragamatic/VoicDrum.cpp b/projects/ragamatic/VoicDrum.cpp
index c3a852e..0bd9863 100644
--- a/projects/ragamatic/VoicDrum.cpp
+++ b/projects/ragamatic/VoicDrum.cpp
@@ -2,39 +2,46 @@
/*! \class VoicDrum
\brief STK vocal drum sample player class.
- This class implements a drum sampling
- synthesizer using WvIn objects and one-pole
- filters. The drum rawwave files are sampled
- at 22050 Hz, but will be appropriately
- interpolated for other sample rates. You can
- specify the maximum polyphony (maximum number
- of simultaneous voices) in Drummer.h.
+ This class implements a drum sampling synthesizer using FileWvIn
+ objects and one-pole filters. The drum rawwave files are sampled
+ at 22050 Hz, but will be appropriately interpolated for other
+ sample rates. You can specify the maximum polyphony (maximum
+ number of simultaneous voices) in VoicDrum.h.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
#include "VoicDrum.h"
-#include
+#include
VoicDrum :: VoicDrum() : Instrmnt()
{
- for ( int i=0; i (VOICE_POLYPHONY, -1);
+ soundNumber_ = std::vector (VOICE_POLYPHONY, -1);
}
VoicDrum :: ~VoicDrum()
{
- int i;
- for ( i=0; i= 0 ) {
- // Reset this sound.
- waves_[waveIndex]->reset();
- filters_[waveIndex]->setPole( 0.999 - (gain * 0.6) );
- filters_[waveIndex]->setGain( gain );
- }
- else {
- if ( nSounding_ == VOICE_POLYPHONY ) {
- // If we're already at maximum polyphony, then preempt the oldest voice.
- delete waves_[0];
- filters_[0]->clear();
- OnePole *tempFilt = filters_[0];
- // Re-order the list.
- for ( i=0; inormalize(0.4);
- if (Stk::sampleRate() != 22050.0)
- waves_[nSounding_-1]->setRate( 22050.0 / Stk::sampleRate() );
- filters_[nSounding_-1]->setPole( 0.999 - (gain * 0.6) );
- filters_[nSounding_-1]->setGain( gain );
+ if ( iWave == VOICE_POLYPHONY ) { // This note number is not currently loaded.
+ if ( nSounding_ < VOICE_POLYPHONY ) {
+ for ( iWave=0; iWave soundOrder_[iWave] )
+ soundOrder_[j] -= 1;
+ }
+ }
+ soundOrder_[iWave] = nSounding_ - 1;
+ soundNumber_[iWave] = noteNumber;
+
+ // Concatenate the rawwave path to the rawwave file
+ waves_[iWave].openFile( (std::string("rawwaves/") + voiceNames[ noteNumber ]).c_str(), true );
+ if ( Stk::sampleRate() != 22050.0 )
+ waves_[iWave].setRate( 22050.0 / Stk::sampleRate() );
+ filters_[iWave].setPole( 0.999 - (gain * 0.6) );
+ filters_[iWave].setGain( gain );
}
#if defined(_STK_DEBUG_)
errorString_ << "VoicDrum::noteOn: number sounding = " << nSounding_ << '\n';
- for (i=0; isetGain( amplitude * 0.01 );
+ while ( i < nSounding_ ) filters_[i++].setGain( amplitude * 0.01 );
}
-StkFloat VoicDrum :: tick()
+StkFloat VoicDrum :: computeSample()
{
- OnePole *tempFilt;
-
- int j, i = 0;
lastOutput_ = 0.0;
- while ( i < nSounding_ ) {
- if ( waves_[i]->isFinished() ) {
- delete waves_[i];
- tempFilt = filters_[i];
- // Re-order the list.
- for ( j=i; j= 0 ) {
+ if ( waves_[i].isFinished() ) {
+ // Re-order the list.
+ for ( int j=0; j soundOrder_[i] )
+ soundOrder_[j] -= 1;
+ }
+ soundOrder_[i] = -1;
+ nSounding_--;
}
- filters_[j] = tempFilt;
- filters_[j]->clear();
- sounding_[j] = -1;
- nSounding_ -= 1;
- i -= 1;
+ else
+ lastOutput_ += filters_[i].tick( waves_[i].tick() );
}
- else
- lastOutput_ += filters_[i]->tick( waves_[i]->tick() );
- i++;
}
return lastOutput_;
}
-
-StkFloat *VoicDrum :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Instrmnt::tick( vector, vectorSize );
-}
-
-StkFrames& VoicDrum :: tick( StkFrames& frames, unsigned int channel )
-{
- return Instrmnt::tick( frames, channel );
-}
diff --git a/projects/ragamatic/VoicDrum.h b/projects/ragamatic/VoicDrum.h
index 0a21009..069c1a7 100644
--- a/projects/ragamatic/VoicDrum.h
+++ b/projects/ragamatic/VoicDrum.h
@@ -2,15 +2,13 @@
/*! \class VoicDrum
\brief STK vocal drum sample player class.
- This class implements a drum sampling
- synthesizer using WvIn objects and one-pole
- filters. The drum rawwave files are sampled
- at 22050 Hz, but will be appropriately
- interpolated for other sample rates. You can
- specify the maximum polyphony (maximum number
- of simultaneous voices) in Drummer.h.
+ This class implements a drum sampling synthesizer using FileWvIn
+ objects and one-pole filters. The drum rawwave files are sampled
+ at 22050 Hz, but will be appropriately interpolated for other
+ sample rates. You can specify the maximum polyphony (maximum
+ number of simultaneous voices) in VoicDrum.h.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -18,7 +16,7 @@
#define STK_VOICDRUM_H
#include "Instrmnt.h"
-#include "WvIn.h"
+#include "FileWvIn.h"
#include "OnePole.h"
const int VOICE_NUMWAVES = 11;
@@ -39,25 +37,14 @@ class VoicDrum : public Instrmnt
//! Stop a note with the given amplitude (speed of decay).
void noteOff(StkFloat amplitude);
- //! Compute one output sample.
- StkFloat tick();
+ protected:
- //! Computer \e vectorSize outputs and return them in \e vector.
- StkFloat *tick(StkFloat *vector, unsigned int vectorSize);
+ StkFloat computeSample( void );
- //! Fill a channel of the StkFrames object with computed outputs.
- /*!
- The \c channel argument should be one or greater (the first
- channel is specified by 1). An StkError will be thrown if the \c
- channel argument is zero or it is greater than the number of
- channels in the StkFrames object.
- */
- StkFrames& tick( StkFrames& frames, unsigned int channel = 1 );
-
- protected:
- WvIn *waves_[VOICE_POLYPHONY];
- OnePole *filters_[VOICE_POLYPHONY];
- int sounding_[VOICE_POLYPHONY];
+ FileWvIn waves_[VOICE_POLYPHONY];
+ OnePole filters_[VOICE_POLYPHONY];
+ std::vector soundOrder_;
+ std::vector soundNumber_;
int nSounding_;
};
diff --git a/projects/ragamatic/ragamat.cpp b/projects/ragamatic/ragamat.cpp
index 66201d1..cc5c128 100644
--- a/projects/ragamatic/ragamat.cpp
+++ b/projects/ragamatic/ragamat.cpp
@@ -188,24 +188,22 @@ int tick(char *buffer, int bufferSize, void *dataPointer)
// Do a bunch of random controls unless settling down to end.
if ( data->settling ) {
if ( data->counter == 0 ) {
- if ( data->endPhase++ == 0 ) {
- data->counter = (int) (data->t60 * Stk::sampleRate());
+ data->counter = (int) (data->t60 * Stk::sampleRate());
+ if ( data->endPhase == 0 ) {
data->drones[2].noteOn( droneFreqs[2], 0.1 );
std::cout << "What Need Have I for This?\n";
}
else if ( data->endPhase == 1 ) {
- data->counter = (int) (data->t60 * Stk::sampleRate());
data->drones[0].noteOn( droneFreqs[0], 0.1 );
std::cout << "RagaMatic finished ... \n";
}
else if ( data->endPhase == 2 ) {
- data->counter = (int) (data->t60 * Stk::sampleRate());
std::cout << "All is Bliss ...\n";
}
else if ( data->endPhase == 3 ) {
std::cout << "All is Bliss ...\n";
- data->counter = (int) (data->t60 * Stk::sampleRate());
}
+ data->endPhase++;
}
}
else {
diff --git a/projects/ragamatic/ragamat.dsp b/projects/ragamatic/ragamat.dsp
index 9a362c1..4d5868b 100644
--- a/projects/ragamatic/ragamat.dsp
+++ b/projects/ragamatic/ragamat.dsp
@@ -140,6 +140,22 @@ SOURCE=..\..\include\Envelope.h
# End Source File
# Begin Source File
+SOURCE=..\..\src\FileRead.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\FileRead.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\FileWvIn.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\FileWvIn.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\src\Filter.cpp
# End Source File
# Begin Source File
@@ -272,6 +288,14 @@ SOURCE=.\Tabla.h
# End Source File
# Begin Source File
+SOURCE=..\..\src\TcpServer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\TcpServer.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\src\Thread.cpp
# End Source File
# Begin Source File
diff --git a/rawwaves/sine.c b/rawwaves/sine.c
new file mode 100644
index 0000000..c43dc82
--- /dev/null
+++ b/rawwaves/sine.c
@@ -0,0 +1,22 @@
+// Utility to make a rawwave sine table (assumes big-endian machine).
+
+#include
+#include
+#include
+
+#define LENGTH 1024
+#define PI 3.14159265358979323846
+
+void main()
+{
+ int i,j;
+ double temp;
+ short data[LENGTH + 2];
+ FILE *fd;
+
+ fd = fopen("sinewave.raw","wb");
+ for (i=0; iCfhm3QL%Zqyz_bpy6-YGsc
zzB7I`K`22t0h5rH(3}8x
znt)~@2J`{?4DCZ~=m`1_oq%%$?)%{F1E|e{oQ%cEhMWz`-txE3yr6;g9G5jCjLa!tKJ?fSY0H3Sg)ZG7#b(d;qv=1kr*pfh@pU
zF`z5J+<(zO(C-NRgQRbruO_w^YvMEM-{_x9cm$5uxfhcx>y_8xXLJ1yHXTh6<_cP8(k
zY)Y&Ttle(+-q;CC0
zlzb_{l0f|!bgn^sMO^9!`?J|%V`3bldLrS%O+srzQi8T;G6aVC5BarD`}0*H<`E*i
zraXA=POeW}N~c^n^Eqf7949*8gOBTumX6LInja9^-K=ev$~TX%#ru={JYNj8BB)K-G$3SsYc&T~t_vEbJ^aE1(yI7x3j%@^$j2^8)gCbE|U=
zbCz@PIda(p*x|Vc0aW=6bF(%PGQI@z%d`+Yfqlq>|
zbs~bWP8cFo6Nm(Ff+^u5K@?`e444MD!xT6Z#=-uuGi(W?VHB(e%fk||C@cUYU~c#n
z%n1%RxC?+c2~bl5J!sJD3}$d(mI5?rK#N5X1-hm{p9uC05!Q(au-69crvM+jiL$^`
z4DdFabQ<^!0e%;g#enxDkl~1=2l8~0SSk7--(V^NWGzZvPE!Th2hs%rhvxL-3~RvU
zYo-NYbdYs7t2rA1xDDjU0fx)DhPl;wynyR;zD_=+fDf>y7n&7z79ooYi@Cu+FiTuY
zrb=&?z94In8_N{SDj!KcDk>K%e%y$f*>m%%_M`$d6?o*Hm4oYOB_-91?wvsE;aN$v3augG`jIjV^xz*(`2(x^U1T)7Oj?v-~3v6TWi{k+8DpXRC(%P
zyH^Kq$J0)$&fTt(=LXN$yEA*Vd+0Any&AoXFH`zZeT@FBfvW?XgXAHzA@*?NE7uXB
zk-^c(G1al9*LgHk+VLOMKmErQ#up|ECM~CUruwIGZ?xZR|JD4~cLq7L`i}D6ZB}Y_
zVU9fSv>>@Kzerwkrc2Z5%ap${3?&A0rExWAO>=F3y=Mdek1>;vIq{+3U#CsE&5e&u
z|Al|j+v3<7`<%UPzaz7=vHNT<>WjfX&;I1s;%^=-71lPp`+#_8esuO|>A3ED@QKd<
DB?bC1
literal 512
zcmV+b0{{I000SfjM+s^Siw~<3#}(li_#6u#86qPkCnzQ>9xf0t`!n7)xjBqHRzDU&
z%|v=f97(fGKTf|58hOO33LACRJwHXE5N6aG61<~--;@8^R+1=gX=i~L~2
+#include
BandedWG :: BandedWG()
{
@@ -264,7 +263,7 @@ void BandedWG :: noteOff(StkFloat amplitude)
#endif
}
-StkFloat BandedWG :: tick()
+StkFloat BandedWG :: computeSample()
{
int k;
@@ -308,16 +307,6 @@ StkFloat BandedWG :: tick()
return lastOutput_;
}
-StkFloat *BandedWG :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Instrmnt::tick( vector, vectorSize );
-}
-
-StkFrames& BandedWG :: tick( StkFrames& frames, unsigned int channel )
-{
- return Instrmnt::tick( frames, channel );
-}
-
void BandedWG :: controlChange(int number, StkFloat value)
{
StkFloat norm = value * ONE_OVER_128;
diff --git a/src/BeeThree.cpp b/src/BeeThree.cpp
index 389fce9..0e30b5b 100644
--- a/src/BeeThree.cpp
+++ b/src/BeeThree.cpp
@@ -28,7 +28,7 @@
type who should worry about this (making
money) worry away.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -79,12 +79,12 @@ void BeeThree :: noteOn(StkFloat frequency, StkFloat amplitude)
#endif
}
-StkFloat BeeThree :: tick()
+StkFloat BeeThree :: computeSample()
{
register StkFloat temp;
if (modDepth_ > 0.0) {
- temp = 1.0 + (modDepth_ * vibrato_->tick() * 0.1);
+ 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]);
@@ -103,12 +103,4 @@ StkFloat BeeThree :: tick()
return lastOutput_;
}
-StkFloat *BeeThree :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Instrmnt::tick( vector, vectorSize );
-}
-StkFrames& BeeThree :: tick( StkFrames& frames, unsigned int channel )
-{
- return Instrmnt::tick( frames, channel );
-}
diff --git a/src/BiQuad.cpp b/src/BiQuad.cpp
index b2e7f9d..8998c43 100644
--- a/src/BiQuad.cpp
+++ b/src/BiQuad.cpp
@@ -8,12 +8,12 @@
frequency response while maintaining a constant
filter gain.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
#include "BiQuad.h"
-#include
+#include
BiQuad :: BiQuad() : Filter()
{
@@ -100,9 +100,9 @@ StkFloat BiQuad :: lastOut(void) const
return Filter::lastOut();
}
-StkFloat BiQuad :: tick(StkFloat sample)
+StkFloat BiQuad :: computeSample( StkFloat input )
{
- inputs_[0] = gain_ * sample;
+ inputs_[0] = gain_ * input;
outputs_[0] = b_[0] * inputs_[0] + b_[1] * inputs_[1] + b_[2] * inputs_[2];
outputs_[0] -= a_[2] * outputs_[2] + a_[1] * outputs_[1];
inputs_[2] = inputs_[1];
@@ -113,9 +113,9 @@ StkFloat BiQuad :: tick(StkFloat sample)
return outputs_[0];
}
-StkFloat *BiQuad :: tick(StkFloat *vector, unsigned int vectorSize)
+StkFloat BiQuad :: tick( StkFloat input )
{
- return Filter::tick( vector, vectorSize );
+ return this->computeSample( input );
}
StkFrames& BiQuad :: tick( StkFrames& frames, unsigned int channel )
diff --git a/src/Blit.cpp b/src/Blit.cpp
new file mode 100644
index 0000000..0755a04
--- /dev/null
+++ b/src/Blit.cpp
@@ -0,0 +1,105 @@
+/***************************************************/
+/*! \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.
+*/
+/***************************************************/
+
+#include "Blit.h"
+#include
+#include
+
+Blit:: Blit( StkFloat frequency )
+{
+ nHarmonics_ = 0;
+ this->setFrequency( frequency );
+ this->reset();
+}
+
+Blit :: ~Blit()
+{
+}
+
+void Blit :: reset()
+{
+ phase_ = 0.0;
+ lastOutput_ = 0;
+}
+
+void Blit :: setFrequency( StkFloat frequency )
+{
+#if defined(_STK_DEBUG_)
+ errorString_ << "Blit::setFrequency: frequency = " << frequency << '.';
+ handleError( StkError::DEBUG_WARNING );
+#endif
+
+ p_ = Stk::sampleRate() / frequency;
+ rate_ = PI / p_;
+ this->updateHarmonics();
+}
+
+void Blit :: setHarmonics( unsigned int nHarmonics )
+{
+ nHarmonics_ = nHarmonics;
+ this->updateHarmonics();
+}
+
+void Blit :: updateHarmonics( void )
+{
+ if ( nHarmonics_ <= 0 ) {
+ unsigned int maxHarmonics = (unsigned int) floor( 0.5 * p_ );
+ m_ = 2 * maxHarmonics + 1;
+ }
+ else
+ m_ = 2 * nHarmonics_ + 1;
+
+#if defined(_STK_DEBUG_)
+ errorString_ << "Blit::updateHarmonics: nHarmonics_ = " << nHarmonics_ << ", m_ = " << m_ << '.';
+ handleError( StkError::DEBUG_WARNING );
+#endif
+}
+
+StkFloat Blit :: computeSample( 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 denominator = sin( phase_ );
+ if ( denominator <= std::numeric_limits::epsilon() ) {
+ lastOutput_ = 1.0;
+ } else {
+ lastOutput_ = sin( m_ * phase_ );
+ lastOutput_ /= m_ * denominator;
+ }
+
+ phase_ += rate_;
+ if ( phase_ >= PI ) phase_ -= PI;
+
+ return lastOutput_;
+}
+
diff --git a/src/BlitSaw.cpp b/src/BlitSaw.cpp
new file mode 100644
index 0000000..42908e3
--- /dev/null
+++ b/src/BlitSaw.cpp
@@ -0,0 +1,125 @@
+/***************************************************/
+/*! \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.
+*/
+/***************************************************/
+
+#include "BlitSaw.h"
+#include
+#include
+
+BlitSaw:: BlitSaw( StkFloat frequency )
+{
+ nHarmonics_ = 0;
+ this->reset();
+ this->setFrequency( frequency );
+}
+
+BlitSaw :: ~BlitSaw()
+{
+}
+
+void BlitSaw :: reset()
+{
+ phase_ = 0.0f;
+ state_ = 0.0;
+ lastOutput_ = 0;
+}
+
+void BlitSaw :: setFrequency( StkFloat frequency )
+{
+#if defined(_STK_DEBUG_)
+ errorString_ << "BlitSaw::setFrequency: frequency = " << frequency << '.';
+ handleError( StkError::DEBUG_WARNING );
+#endif
+
+ p_ = Stk::sampleRate() / frequency;
+ C2_ = 1 / p_;
+ rate_ = PI * C2_;
+ this->updateHarmonics();
+}
+
+void BlitSaw :: setHarmonics( unsigned int nHarmonics )
+{
+ nHarmonics_ = nHarmonics;
+ this->updateHarmonics();
+
+ // I found that the initial DC offset could be minimized with an
+ // initial state setting as given below. This initialization should
+ // only happen before starting the oscillator for the first time
+ // (but after setting the frequency and number of harmonics). I
+ // struggled a bit to decide where best to put this and finally
+ // settled on here. In general, the user shouldn't be messing with
+ // the number of harmonics once the oscillator is running because
+ // this is automatically taken care of in the setFrequency()
+ // function. (GPS - 1 October 2005)
+ state_ = -0.5 * a_;
+}
+
+void BlitSaw :: updateHarmonics( void )
+{
+ if ( nHarmonics_ <= 0 ) {
+ unsigned int maxHarmonics = (unsigned int) floor( 0.5 * p_ );
+ m_ = 2 * maxHarmonics + 1;
+ }
+ else
+ m_ = 2 * nHarmonics_ + 1;
+
+ a_ = m_ / p_;
+
+#if defined(_STK_DEBUG_)
+ errorString_ << "BlitSaw::updateHarmonics: nHarmonics_ = " << nHarmonics_ << ", m_ = " << m_ << '.';
+ handleError( StkError::DEBUG_WARNING );
+#endif
+}
+
+StkFloat BlitSaw :: computeSample( 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 denominator = sin( phase_ );
+ if ( fabs(denominator) <= std::numeric_limits::epsilon() )
+ lastOutput_ = a_;
+ else {
+ lastOutput_ = sin( m_ * phase_ );
+ lastOutput_ /= p_ * denominator;
+ }
+
+ lastOutput_ += state_ - C2_;
+ state_ = lastOutput_ * 0.995;
+
+ phase_ += rate_;
+ if ( phase_ >= PI ) phase_ -= PI;
+
+ return lastOutput_;
+}
+
diff --git a/src/BlitSquare.cpp b/src/BlitSquare.cpp
new file mode 100644
index 0000000..ba67ac7
--- /dev/null
+++ b/src/BlitSquare.cpp
@@ -0,0 +1,122 @@
+/***************************************************/
+/*! \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 but that is
+ subtracted off the output signal.
+
+ 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).
+
+ Based on initial code of Robin Davies, 2005.
+ Modified algorithm code by Gary Scavone, 2005.
+*/
+/***************************************************/
+
+#include "BlitSquare.h"
+#include
+#include
+
+BlitSquare:: BlitSquare( StkFloat frequency )
+{
+ nHarmonics_ = 0;
+ this->setFrequency( frequency );
+ this->reset();
+}
+
+BlitSquare :: ~BlitSquare()
+{
+}
+
+void BlitSquare :: reset()
+{
+ phase_ = 0.0;
+ lastOutput_ = 0;
+}
+
+void BlitSquare :: setFrequency( StkFloat frequency )
+{
+#if defined(_STK_DEBUG_)
+ errorString_ << "BlitSquare::setFrequency: frequency = " << frequency << '.';
+ handleError( StkError::DEBUG_WARNING );
+#endif
+
+ // By using an even value of the parameter M, we get a bipolar blit
+ // waveform at half the blit frequency. Thus, we need to scale the
+ // frequency value here by 2.0. (GPS, 2005).
+ p_ = 2.0 * Stk::sampleRate() / frequency;
+ rate_ = PI / p_;
+ this->updateHarmonics();
+}
+
+void BlitSquare :: setHarmonics( unsigned int nHarmonics )
+{
+ nHarmonics_ = nHarmonics;
+ this->updateHarmonics();
+}
+
+void BlitSquare :: updateHarmonics( void )
+{
+ // Make sure we end up with an even value of the parameter M here.
+ if ( nHarmonics_ <= 0 ) {
+ unsigned int maxHarmonics = (unsigned int) floor( 0.5 * p_ );
+ m_ = 2 * maxHarmonics;
+ }
+ else
+ m_ = 2 * nHarmonics_;
+
+ // This offset value was derived empirically. (GPS, 2005)
+ offset_ = 1.0 - 0.5 * m_ / p_;
+
+#if defined(_STK_DEBUG_)
+ errorString_ << "BlitSquare::updateHarmonics: nHarmonics_ = " << nHarmonics_ << ", m_ = " << m_ << '.';
+ handleError( StkError::DEBUG_WARNING );
+#endif
+}
+
+StkFloat BlitSquare :: computeSample( void )
+{
+ StkFloat temp = lastOutput_;
+
+ // 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::epsilon() ) {
+ // Inexact comparison safely distinguishes betwen *close to zero*, and *close to PI*.
+ if ( phase_ < 0.1f || phase_ > TWO_PI - 0.1f )
+ lastOutput_ = 1.0;
+ else
+ lastOutput_ = -1.0;
+ }
+ else {
+ lastOutput_ = sin( m_ * phase_ );
+ lastOutput_ /= p_ * denominator;
+ }
+
+ lastOutput_ += temp;
+
+ phase_ += rate_;
+ if ( phase_ >= TWO_PI ) phase_ -= TWO_PI;
+
+ return lastOutput_ - offset_;
+}
+
diff --git a/src/BlowBotl.cpp b/src/BlowBotl.cpp
index a1930fd..34490a1 100644
--- a/src/BlowBotl.cpp
+++ b/src/BlowBotl.cpp
@@ -12,7 +12,7 @@
- Vibrato Gain = 1
- Volume = 128
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -25,9 +25,7 @@ BlowBotl :: BlowBotl()
{
dcBlock_.setBlockZero();
- // Concatenate the STK rawwave path to the rawwave file
- vibrato_ = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), true );
- vibrato_->setFrequency( 5.925 );
+ vibrato_.setFrequency( 5.925 );
vibratoGain_ = 0.0;
resonator_.setResonance(500.0, __BOTTLE_RADIUS_, true);
@@ -39,7 +37,6 @@ BlowBotl :: BlowBotl()
BlowBotl :: ~BlowBotl()
{
- delete vibrato_;
}
void BlowBotl :: clear()
@@ -94,7 +91,7 @@ void BlowBotl :: noteOff(StkFloat amplitude)
#endif
}
-StkFloat BlowBotl :: tick()
+StkFloat BlowBotl :: computeSample()
{
StkFloat breathPressure;
StkFloat randPressure;
@@ -102,7 +99,7 @@ StkFloat BlowBotl :: tick()
// Calculate the breath pressure (envelope + vibrato)
breathPressure = maxPressure_ * adsr_.tick();
- breathPressure += vibratoGain_ * vibrato_->tick();
+ breathPressure += vibratoGain_ * vibrato_.tick();
pressureDiff = breathPressure - resonator_.lastOut();
@@ -116,16 +113,6 @@ StkFloat BlowBotl :: tick()
return lastOutput_;
}
-StkFloat *BlowBotl :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Instrmnt::tick( vector, vectorSize );
-}
-
-StkFrames& BlowBotl :: tick( StkFrames& frames, unsigned int channel )
-{
- return Instrmnt::tick( frames, channel );
-}
-
void BlowBotl :: controlChange(int number, StkFloat value)
{
StkFloat norm = value * ONE_OVER_128;
@@ -143,7 +130,7 @@ void BlowBotl :: controlChange(int number, StkFloat value)
if (number == __SK_NoiseLevel_) // 4
noiseGain_ = norm * 30.0;
else if (number == __SK_ModFrequency_) // 11
- vibrato_->setFrequency( norm * 12.0 );
+ vibrato_.setFrequency( norm * 12.0 );
else if (number == __SK_ModWheel_) // 1
vibratoGain_ = norm * 0.4;
else if (number == __SK_AfterTouch_Cont_) // 128
diff --git a/src/BlowHole.cpp b/src/BlowHole.cpp
index 2efb8c5..62bb72b 100644
--- a/src/BlowHole.cpp
+++ b/src/BlowHole.cpp
@@ -29,7 +29,7 @@
- Register State = 1
- Breath Pressure = 128
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -77,9 +77,7 @@ BlowHole :: BlowHole(StkFloat lowestFrequency)
// Start with register vent closed
vent_.setGain(0.0);
- // Concatenate the STK rawwave path to the rawwave file
- vibrato_ = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), true );
- vibrato_->setFrequency((StkFloat) 5.735);
+ vibrato_.setFrequency((StkFloat) 5.735);
outputGain_ = 1.0;
noiseGain_ = 0.2;
vibratoGain_ = 0.01;
@@ -87,7 +85,6 @@ BlowHole :: BlowHole(StkFloat lowestFrequency)
BlowHole :: ~BlowHole()
{
- delete vibrato_;
}
void BlowHole :: clear()
@@ -187,7 +184,7 @@ void BlowHole :: noteOff(StkFloat amplitude)
#endif
}
-StkFloat BlowHole :: tick()
+StkFloat BlowHole :: computeSample()
{
StkFloat pressureDiff;
StkFloat breathPressure;
@@ -196,7 +193,7 @@ StkFloat BlowHole :: tick()
// Calculate the breath pressure (envelope + noise + vibrato)
breathPressure = envelope_.tick();
breathPressure += breathPressure * noiseGain_ * noise_.tick();
- breathPressure += breathPressure * vibratoGain_ * vibrato_->tick();
+ breathPressure += breathPressure * vibratoGain_ * vibrato_.tick();
// Calculate the differential pressure = reflected - mouthpiece pressures
pressureDiff = delays_[0].lastOut() - breathPressure;
@@ -222,16 +219,6 @@ StkFloat BlowHole :: tick()
return lastOutput_;
}
-StkFloat *BlowHole :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Instrmnt::tick( vector, vectorSize );
-}
-
-StkFrames& BlowHole :: tick( StkFrames& frames, unsigned int channel )
-{
- return Instrmnt::tick( frames, channel );
-}
-
void BlowHole :: controlChange(int number, StkFloat value)
{
StkFloat norm = value * ONE_OVER_128;
diff --git a/src/BowTable.cpp b/src/BowTable.cpp
index 45d17d3..1ea386e 100644
--- a/src/BowTable.cpp
+++ b/src/BowTable.cpp
@@ -5,7 +5,7 @@
This class implements a simple bowed string
non-linear function, as described by Smith (1986).
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -32,7 +32,7 @@ void BowTable :: setSlope(StkFloat slope)
slope_ = slope;
}
-StkFloat BowTable :: tick(StkFloat input)
+StkFloat BowTable :: computeSample(StkFloat input)
{
// The input represents differential string vs. bow velocity.
StkFloat sample;
@@ -49,12 +49,3 @@ StkFloat BowTable :: tick(StkFloat input)
return lastOutput_;
}
-StkFloat *BowTable :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Function::tick( vector, vectorSize );
-}
-
-StkFrames& BowTable :: tick( StkFrames& frames, unsigned int channel )
-{
- return Function::tick( frames, channel );
-}
diff --git a/src/Bowed.cpp b/src/Bowed.cpp
index ebd493a..0e2e731 100644
--- a/src/Bowed.cpp
+++ b/src/Bowed.cpp
@@ -17,7 +17,7 @@
- Vibrato Gain = 1
- Volume = 128
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -37,9 +37,7 @@ Bowed :: Bowed(StkFloat lowestFrequency)
bowTable_.setSlope(3.0 );
- // Concatenate the STK rawwave path to the rawwave file
- vibrato_ = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), true );
- vibrato_->setFrequency( 6.12723 );
+ vibrato_.setFrequency( 6.12723 );
vibratoGain_ = 0.0;
stringFilter_.setPole( 0.6 - (0.1 * 22050.0 / Stk::sampleRate()) );
@@ -58,7 +56,6 @@ Bowed :: Bowed(StkFloat lowestFrequency)
Bowed :: ~Bowed()
{
- delete vibrato_;
}
void Bowed :: clear()
@@ -122,7 +119,7 @@ void Bowed :: setVibrato(StkFloat gain)
vibratoGain_ = gain;
}
-StkFloat Bowed :: tick()
+StkFloat Bowed :: computeSample()
{
StkFloat bowVelocity;
StkFloat bridgeRefl;
@@ -143,7 +140,7 @@ StkFloat Bowed :: tick()
if ( vibratoGain_ > 0.0 ) {
neckDelay_.setDelay( (baseDelay_ * (1.0 - betaRatio_) ) +
- (baseDelay_ * vibratoGain_ * vibrato_->tick()) );
+ (baseDelay_ * vibratoGain_ * vibrato_.tick()) );
}
lastOutput_ = bodyFilter_.tick( bridgeDelay_.lastOut() );
@@ -151,16 +148,6 @@ StkFloat Bowed :: tick()
return lastOutput_;
}
-StkFloat *Bowed :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Instrmnt::tick( vector, vectorSize );
-}
-
-StkFrames& Bowed :: tick( StkFrames& frames, unsigned int channel )
-{
- return Instrmnt::tick( frames, channel );
-}
-
void Bowed :: controlChange(int number, StkFloat value)
{
StkFloat norm = value * ONE_OVER_128;
@@ -183,7 +170,7 @@ void Bowed :: controlChange(int number, StkFloat value)
neckDelay_.setDelay( baseDelay_ * (1.0 - betaRatio_) );
}
else if (number == __SK_ModFrequency_) // 11
- vibrato_->setFrequency( norm * 12.0 );
+ vibrato_.setFrequency( norm * 12.0 );
else if (number == __SK_ModWheel_) // 1
vibratoGain_ = ( norm * 0.4 );
else if (number == __SK_AfterTouch_Cont_) // 128
diff --git a/src/Brass.cpp b/src/Brass.cpp
index f5aee41..0143beb 100644
--- a/src/Brass.cpp
+++ b/src/Brass.cpp
@@ -16,13 +16,13 @@
- Vibrato Gain = 1
- Volume = 128
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
#include "Brass.h"
#include "SKINI.msg"
-#include
+#include
Brass :: Brass(StkFloat lowestFrequency)
{
@@ -35,9 +35,7 @@ Brass :: Brass(StkFloat lowestFrequency)
adsr_.setAllTimes( 0.005, 0.001, 1.0, 0.010);
- // Concatenate the STK rawwave path to the rawwave file
- vibrato_ = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), true );
- vibrato_->setFrequency( 6.137 );
+ vibrato_.setFrequency( 6.137 );
vibratoGain_ = 0.0;
this->clear();
@@ -50,7 +48,6 @@ Brass :: Brass(StkFloat lowestFrequency)
Brass :: ~Brass()
{
- delete vibrato_;
}
void Brass :: clear()
@@ -123,10 +120,10 @@ void Brass :: noteOff(StkFloat amplitude)
#endif
}
-StkFloat Brass :: tick()
+StkFloat Brass :: computeSample()
{
StkFloat breathPressure = maxPressure_ * adsr_.tick();
- breathPressure += vibratoGain_ * vibrato_->tick();
+ breathPressure += vibratoGain_ * vibrato_.tick();
StkFloat mouthPressure = 0.3 * breathPressure;
StkFloat borePressure = 0.85 * delayLine_.lastOut();
@@ -142,16 +139,6 @@ StkFloat Brass :: tick()
return lastOutput_;
}
-StkFloat *Brass :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Instrmnt::tick( vector, vectorSize );
-}
-
-StkFrames& Brass :: tick( StkFrames& frames, unsigned int channel )
-{
- return Instrmnt::tick( frames, channel );
-}
-
void Brass :: controlChange(int number, StkFloat value)
{
StkFloat norm = value * ONE_OVER_128;
@@ -173,7 +160,7 @@ void Brass :: controlChange(int number, StkFloat value)
else if (number == __SK_SlideLength_) // 4
delayLine_.setDelay( slideTarget_ * (0.5 + norm) );
else if (number == __SK_ModFrequency_) // 11
- vibrato_->setFrequency( norm * 12.0 );
+ vibrato_.setFrequency( norm * 12.0 );
else if (number == __SK_ModWheel_ ) // 1
vibratoGain_ = norm * 0.4;
else if (number == __SK_AfterTouch_Cont_) // 128
diff --git a/src/Chorus.cpp b/src/Chorus.cpp
index b779024..60879eb 100644
--- a/src/Chorus.cpp
+++ b/src/Chorus.cpp
@@ -4,7 +4,7 @@
This class implements a chorus effect.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -19,11 +19,8 @@ Chorus :: Chorus(StkFloat baseDelay)
delayLine_[1].setDelay( baseDelay );
baseLength_ = baseDelay;
- // Concatenate the STK rawwave path to the rawwave file
- mods_[0] = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), true );
- mods_[1] = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), true );
- mods_[0]->setFrequency(0.2);
- mods_[1]->setFrequency(0.222222);
+ mods_[0].setFrequency(0.2);
+ mods_[1].setFrequency(0.222222);
modDepth_ = 0.05;
effectMix_ = 0.5;
this->clear();
@@ -31,8 +28,6 @@ Chorus :: Chorus(StkFloat baseDelay)
Chorus :: ~Chorus()
{
- delete mods_[0];
- delete mods_[1];
}
void Chorus :: clear()
@@ -50,27 +45,17 @@ void Chorus :: setModDepth(StkFloat depth)
void Chorus :: setModFrequency(StkFloat frequency)
{
- mods_[0]->setFrequency(frequency);
- mods_[1]->setFrequency(frequency * 1.1111);
+ mods_[0].setFrequency(frequency);
+ mods_[1].setFrequency(frequency * 1.1111);
}
-StkFloat Chorus :: tick(StkFloat input)
+StkFloat Chorus :: computeSample(StkFloat input)
{
- delayLine_[0].setDelay( baseLength_ * 0.707 * (1.0 + mods_[0]->tick()) );
- delayLine_[1].setDelay( baseLength_ * 0.5 * (1.0 - mods_[1]->tick()) );
+ delayLine_[0].setDelay( baseLength_ * 0.707 * (1.0 + modDepth_ * mods_[0].tick()) );
+ delayLine_[1].setDelay( baseLength_ * 0.5 * (1.0 - modDepth_ * mods_[1].tick()) );
lastOutput_[0] = input * (1.0 - effectMix_);
lastOutput_[0] += effectMix_ * delayLine_[0].tick(input);
lastOutput_[1] = input * (1.0 - effectMix_);
lastOutput_[1] += effectMix_ * delayLine_[1].tick(input);
return Effect::lastOut();
}
-
-StkFloat *Chorus :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Effect::tick( vector, vectorSize );
-}
-
-StkFrames& Chorus :: tick( StkFrames& frames, unsigned int channel )
-{
- return Effect::tick( frames, channel );
-}
diff --git a/src/Clarinet.cpp b/src/Clarinet.cpp
index 1ebc7cc..ff6d847 100644
--- a/src/Clarinet.cpp
+++ b/src/Clarinet.cpp
@@ -18,7 +18,7 @@
- Vibrato Gain = 1
- Breath Pressure = 128
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -33,9 +33,7 @@ Clarinet :: Clarinet(StkFloat lowestFrequency)
reedTable_.setOffset((StkFloat) 0.7);
reedTable_.setSlope((StkFloat) -0.3);
- // Concatenate the STK rawwave path to the rawwave file
- vibrato_ = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), true );
- vibrato_->setFrequency((StkFloat) 5.735);
+ vibrato_.setFrequency((StkFloat) 5.735);
outputGain_ = (StkFloat) 1.0;
noiseGain_ = (StkFloat) 0.2;
vibratoGain_ = (StkFloat) 0.1;
@@ -43,7 +41,6 @@ Clarinet :: Clarinet(StkFloat lowestFrequency)
Clarinet :: ~Clarinet()
{
- delete vibrato_;
}
void Clarinet :: clear()
@@ -102,7 +99,7 @@ void Clarinet :: noteOff(StkFloat amplitude)
#endif
}
-StkFloat Clarinet :: tick()
+StkFloat Clarinet :: computeSample()
{
StkFloat pressureDiff;
StkFloat breathPressure;
@@ -110,7 +107,7 @@ StkFloat Clarinet :: tick()
// Calculate the breath pressure (envelope + noise + vibrato)
breathPressure = envelope_.tick();
breathPressure += breathPressure * noiseGain_ * noise_.tick();
- breathPressure += breathPressure * vibratoGain_ * vibrato_->tick();
+ breathPressure += breathPressure * vibratoGain_ * vibrato_.tick();
// Perform commuted loss filtering.
pressureDiff = -0.95 * filter_.tick(delayLine_.lastOut());
@@ -127,16 +124,6 @@ StkFloat Clarinet :: tick()
return lastOutput_;
}
-StkFloat *Clarinet :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Instrmnt::tick( vector, vectorSize );
-}
-
-StkFrames& Clarinet :: tick( StkFrames& frames, unsigned int channel )
-{
- return Instrmnt::tick( frames, channel );
-}
-
void Clarinet :: controlChange(int number, StkFloat value)
{
StkFloat norm = value * ONE_OVER_128;
@@ -156,7 +143,7 @@ void Clarinet :: controlChange(int number, StkFloat value)
else if (number == __SK_NoiseLevel_) // 4
noiseGain_ = (norm * (StkFloat) 0.4);
else if (number == __SK_ModFrequency_) // 11
- vibrato_->setFrequency((norm * (StkFloat) 12.0));
+ vibrato_.setFrequency((norm * (StkFloat) 12.0));
else if (number == __SK_ModWheel_) // 1
vibratoGain_ = (norm * (StkFloat) 0.5);
else if (number == __SK_AfterTouch_Cont_) // 128
diff --git a/src/Delay.cpp b/src/Delay.cpp
index 0bd2b63..c35a5b3 100644
--- a/src/Delay.cpp
+++ b/src/Delay.cpp
@@ -14,7 +14,7 @@
used in fixed delay-length applications, such
as for reverberation.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -167,9 +167,9 @@ StkFloat Delay :: nextOut(void)
return inputs_[outPoint_];
}
-StkFloat Delay :: tick(StkFloat sample)
+StkFloat Delay :: computeSample( StkFloat input )
{
- inputs_[inPoint_++] = sample;
+ inputs_[inPoint_++] = input;
// Check for end condition
if (inPoint_ == inputs_.size())
@@ -184,9 +184,9 @@ StkFloat Delay :: tick(StkFloat sample)
return outputs_[0];
}
-StkFloat *Delay :: tick(StkFloat *vector, unsigned int vectorSize)
+StkFloat Delay :: tick( StkFloat input )
{
- return Filter::tick( vector, vectorSize );
+ return computeSample( input );
}
StkFrames& Delay :: tick( StkFrames& frames, unsigned int channel )
diff --git a/src/DelayA.cpp b/src/DelayA.cpp
index 046cdf6..83a54e9 100644
--- a/src/DelayA.cpp
+++ b/src/DelayA.cpp
@@ -2,23 +2,20 @@
/*! \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 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.
- 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 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -109,6 +106,11 @@ void DelayA :: setDelay(StkFloat delay)
((StkFloat) 1.0 + alpha_); // coefficient for all pass
}
+StkFloat DelayA :: getDelay(void) const
+{
+ return delay_;
+}
+
StkFloat DelayA :: nextOut(void)
{
if ( doNextOut_ ) {
@@ -121,9 +123,9 @@ StkFloat DelayA :: nextOut(void)
return nextOutput_;
}
-StkFloat DelayA :: tick(StkFloat sample)
+StkFloat DelayA :: computeSample( StkFloat input )
{
- inputs_[inPoint_++] = sample;
+ inputs_[inPoint_++] = input;
// Increment input pointer modulo length.
if (inPoint_ == inputs_.size())
@@ -139,13 +141,3 @@ StkFloat DelayA :: tick(StkFloat sample)
return outputs_[0];
}
-
-StkFloat *DelayA :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Filter::tick( vector, vectorSize );
-}
-
-StkFrames& DelayA :: tick( StkFrames& frames, unsigned int channel )
-{
- return Filter::tick( frames, channel );
-}
diff --git a/src/DelayL.cpp b/src/DelayL.cpp
index 0313271..10b04c5 100644
--- a/src/DelayL.cpp
+++ b/src/DelayL.cpp
@@ -18,7 +18,7 @@
order Lagrange interpolators can typically
improve (minimize) this attenuation characteristic.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -110,9 +110,9 @@ StkFloat DelayL :: nextOut(void)
return nextOutput_;
}
-StkFloat DelayL :: tick(StkFloat sample)
+StkFloat DelayL :: computeSample( StkFloat input )
{
- inputs_[inPoint_++] = sample;
+ inputs_[inPoint_++] = input;
// Increment input pointer modulo length.
if (inPoint_ == inputs_.size())
@@ -128,12 +128,3 @@ StkFloat DelayL :: tick(StkFloat sample)
return outputs_[0];
}
-StkFloat *DelayL :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Filter::tick( vector, vectorSize );
-}
-
-StkFrames& DelayL :: tick( StkFrames& frames, unsigned int channel )
-{
- return Filter::tick( frames, channel );
-}
diff --git a/src/Drummer.cpp b/src/Drummer.cpp
index 444c9ba..641c49a 100644
--- a/src/Drummer.cpp
+++ b/src/Drummer.cpp
@@ -3,7 +3,7 @@
\brief STK drum sample player class.
This class implements a drum sampling
- synthesizer using WvIn objects and one-pole
+ synthesizer using FileWvIn objects and one-pole
filters. The drum rawwave files are sampled
at 22050 Hz, but will be appropriately
interpolated for other sample rates. You can
@@ -11,12 +11,12 @@
of simultaneous voices) via a #define in the
Drummer.h.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
#include "Drummer.h"
-#include
+#include
// Not really General MIDI yet.
unsigned char genMIDIMap[128] =
@@ -55,20 +55,14 @@ char waveNames[DRUM_NUMWAVES][16] =
Drummer :: Drummer() : Instrmnt()
{
- for ( int i=0; i (DRUM_POLYPHONY, -1);
+ soundNumber_ = std::vector (DRUM_POLYPHONY, -1);
}
Drummer :: ~Drummer()
{
- int i;
- for ( i=0; i= 0 ) {
- // Reset this sound.
- waves_[waveIndex]->reset();
- filters_[waveIndex]->setPole( 0.999 - (gain * 0.6) );
- filters_[waveIndex]->setGain( gain );
- }
- else {
- if (nSounding_ == DRUM_POLYPHONY) {
- // If we're already at maximum polyphony, then preempt the oldest voice.
- delete waves_[0];
- filters_[0]->clear();
- OnePole *tempFilt = filters_[0];
- // Re-order the list.
- for ( i=0; i soundOrder_[iWave] )
+ soundOrder_[j] -= 1;
+ }
+ }
+ soundOrder_[iWave] = nSounding_ - 1;
+ soundNumber_[iWave] = noteNumber;
- sounding_[nSounding_-1] = noteNum;
// Concatenate the STK rawwave path to the rawwave file
- waves_[nSounding_-1] = new WvIn( (Stk::rawwavePath() + waveNames[genMIDIMap[noteNum]]).c_str(), true );
- if (Stk::sampleRate() != 22050.0)
- waves_[nSounding_-1]->setRate( 22050.0 / Stk::sampleRate() );
- filters_[nSounding_-1]->setPole( 0.999 - (gain * 0.6) );
- filters_[nSounding_-1]->setGain( gain );
+ waves_[iWave].openFile( (Stk::rawwavePath() + waveNames[ genMIDIMap[ noteNumber ] ]).c_str(), true );
+ if ( Stk::sampleRate() != 22050.0 )
+ waves_[iWave].setRate( 22050.0 / Stk::sampleRate() );
+ filters_[iWave].setPole( 0.999 - (gain * 0.6) );
+ filters_[iWave].setGain( gain );
}
#if defined(_STK_DEBUG_)
errorString_ << "Drummer::noteOn: number sounding = " << nSounding_ << '\n';
- for (i=0; isetGain( amplitude * 0.01 );
+ while ( i < nSounding_ ) filters_[i++].setGain( amplitude * 0.01 );
}
-StkFloat Drummer :: tick()
+StkFloat Drummer :: computeSample()
{
- OnePole *tempFilt;
-
- int j, i = 0;
lastOutput_ = 0.0;
- while (i < nSounding_) {
- if ( waves_[i]->isFinished() ) {
- delete waves_[i];
- tempFilt = filters_[i];
- // Re-order the list.
- for ( j=i; j= 0 ) {
+ if ( waves_[i].isFinished() ) {
+ // Re-order the list.
+ for ( int j=0; j soundOrder_[i] )
+ soundOrder_[j] -= 1;
+ }
+ soundOrder_[i] = -1;
+ nSounding_--;
}
- filters_[j] = tempFilt;
- filters_[j]->clear();
- sounding_[j] = -1;
- nSounding_ -= 1;
- i -= 1;
+ else
+ lastOutput_ += filters_[i].tick( waves_[i].tick() );
}
- else
- lastOutput_ += filters_[i]->tick( waves_[i]->tick() );
- i++;
}
return lastOutput_;
}
-
-StkFloat *Drummer :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Instrmnt::tick( vector, vectorSize );
-}
-
-StkFrames& Drummer :: tick( StkFrames& frames, unsigned int channel )
-{
- return Instrmnt::tick( frames, channel );
-}
diff --git a/src/Echo.cpp b/src/Echo.cpp
index 02e1452..3b169c5 100644
--- a/src/Echo.cpp
+++ b/src/Echo.cpp
@@ -4,7 +4,7 @@
This class implements an echo effect.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -54,20 +54,10 @@ void Echo :: setDelay( unsigned long delay )
delayLine_.setDelay( size );
}
-StkFloat Echo :: tick(StkFloat input)
+StkFloat Echo :: computeSample(StkFloat input)
{
lastOutput_[0] = effectMix_ * delayLine_.tick(input);
lastOutput_[0] += input * (1.0 - effectMix_);
lastOutput_[1] = lastOutput_[0];
return lastOutput_[0];
}
-
-StkFloat *Echo :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Effect::tick( vector, vectorSize );
-}
-
-StkFrames& Echo :: tick( StkFrames& frames, unsigned int channel )
-{
- return Effect::tick( frames, channel );
-}
diff --git a/src/Effect.cpp b/src/Effect.cpp
index f79d2dc..2d1cb44 100644
--- a/src/Effect.cpp
+++ b/src/Effect.cpp
@@ -5,7 +5,7 @@
This class provides common functionality for
STK effects subclasses.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -51,37 +51,34 @@ StkFloat Effect :: lastOutRight() const
return lastOutput_[1];
}
-StkFloat *Effect :: tick(StkFloat *vector, unsigned int vectorSize)
+StkFloat Effect :: tick( StkFloat input )
{
- for (unsigned int i=0; i channels in StkFrames argument!";
+ if ( channel >= frames.channels() ) {
+ errorString_ << "Effect::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
if ( frames.channels() == 1 ) {
for ( unsigned int i=0; i value_) {
@@ -101,13 +121,3 @@ StkFloat Envelope :: tick(void)
lastOutput_ = value_;
return value_;
}
-
-StkFloat *Envelope :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Generator::tick( vector, vectorSize );
-}
-
-StkFrames& Envelope :: tick( StkFrames& frames, unsigned int channel )
-{
- return Generator::tick( frames, channel );
-}
diff --git a/src/FM.cpp b/src/FM.cpp
index 0bcef9f..1ca49d3 100644
--- a/src/FM.cpp
+++ b/src/FM.cpp
@@ -19,7 +19,7 @@
type who should worry about this (making
money) worry away.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -37,9 +37,7 @@ FM :: FM( unsigned int operators )
twozero_.setB2( -1.0 );
twozero_.setGain( 0.0 );
- // Concatenate the STK rawwave path to the rawwave file
- vibrato_ = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), true );
- vibrato_->setFrequency( 6.0 );
+ vibrato_.setFrequency( 6.0 );
unsigned int j;
adsr_.resize( nOperators_ );
@@ -77,8 +75,6 @@ FM :: FM( unsigned int operators )
FM :: ~FM()
{
- delete vibrato_;
-
for (unsigned int i=0; isetFrequency( mSpeed );
+ vibrato_.setFrequency( mSpeed );
}
void FM :: setModulationDepth(StkFloat mDepth)
diff --git a/src/FMVoices.cpp b/src/FMVoices.cpp
index 4e229dc..3e34322 100644
--- a/src/FMVoices.cpp
+++ b/src/FMVoices.cpp
@@ -26,7 +26,7 @@
type who should worry about this (making
money) worry away.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -123,12 +123,12 @@ void FMVoices :: noteOn(StkFloat frequency, StkFloat amplitude)
#endif
}
-StkFloat FMVoices :: tick()
+StkFloat FMVoices :: computeSample()
{
register StkFloat temp, temp2;
temp = gains_[3] * adsr_[3]->tick() * waves_[3]->tick();
- temp2 = vibrato_->tick() * modDepth_ * 0.1;
+ temp2 = vibrato_.tick() * modDepth_ * 0.1;
waves_[0]->setFrequency(baseFrequency_ * (1.0 + temp2) * ratios_[0]);
waves_[1]->setFrequency(baseFrequency_ * (1.0 + temp2) * ratios_[1]);
@@ -148,16 +148,6 @@ StkFloat FMVoices :: tick()
return lastOutput_;
}
-StkFloat *FMVoices :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Instrmnt::tick( vector, vectorSize );
-}
-
-StkFrames& FMVoices :: tick( StkFrames& frames, unsigned int channel )
-{
- return Instrmnt::tick( frames, channel );
-}
-
void FMVoices :: controlChange(int number, StkFloat value)
{
StkFloat norm = value * ONE_OVER_128;
diff --git a/src/FileRead.cpp b/src/FileRead.cpp
new file mode 100644
index 0000000..0ed8ffa
--- /dev/null
+++ b/src/FileRead.cpp
@@ -0,0 +1,721 @@
+/***************************************************/
+/*! \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-, 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 is assumed to be 44100 Hz.
+
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
+*/
+/***************************************************/
+
+#include "FileRead.h"
+#include
+#include
+#include
+
+FileRead :: FileRead()
+ : fd_(0)
+{
+}
+
+FileRead :: FileRead( std::string fileName, bool typeRaw )
+ : fd_(0)
+{
+ open( fileName, typeRaw );
+}
+
+FileRead :: ~FileRead()
+{
+ if ( fd_ )
+ fclose( fd_ );
+}
+
+void FileRead :: close( void )
+{
+ if ( fd_ ) fclose( fd_ );
+ fd_ = 0;
+ wavFile_ = false;
+}
+
+bool FileRead :: isOpen( void )
+{
+ if ( fd_ ) return true;
+ else return false;
+}
+
+void FileRead :: open( std::string fileName, bool typeRaw )
+{
+ // If another file is open, close it.
+ close();
+
+ // Try to open the file.
+ fd_ = fopen( fileName.c_str(), "rb" );
+ if ( !fd_ ) {
+ errorString_ << "FileRead::open: could not open or find file (" << fileName << ")!";
+ handleError( StkError::FILE_NOT_FOUND );
+ }
+
+ // Attempt to determine file type from header (unless RAW).
+ bool result = false;
+ if ( typeRaw )
+ result = getRawInfo( fileName.c_str() );
+ else {
+ char header[12];
+ if ( fread( &header, 4, 3, fd_ ) != 3 ) goto error;
+ if ( !strncmp( header, "RIFF", 4 ) &&
+ !strncmp( &header[8], "WAVE", 4 ) )
+ result = getWavInfo( fileName.c_str() );
+ else if ( !strncmp( header, ".snd", 4 ) )
+ result = getSndInfo( fileName.c_str() );
+ else if ( !strncmp( header, "FORM", 4 ) &&
+ ( !strncmp( &header[8], "AIFF", 4 ) || !strncmp(&header[8], "AIFC", 4) ) )
+ result = getAifInfo( fileName.c_str() );
+ else {
+ if ( fseek( fd_, 126, SEEK_SET ) == -1 ) goto error;
+ if ( fread( &header, 2, 1, fd_ ) != 1 ) goto error;
+ if ( !strncmp( header, "MI", 2 ) ||
+ !strncmp( header, "IM", 2 ) )
+ result = getMatInfo( fileName.c_str() );
+ else {
+ errorString_ << "FileRead::open: file (" << fileName << ") format unknown.";
+ handleError( StkError::FILE_UNKNOWN_FORMAT );
+ }
+ }
+ }
+
+ // If here, we had a file type candidate but something else went wrong.
+ if ( result == false )
+ handleError( StkError::FILE_ERROR );
+
+ // Check for empty files.
+ if ( fileSize_ == 0 ) {
+ errorString_ << "FileRead::open: file (" << fileName << ") data size is zero!";
+ handleError( StkError::FILE_ERROR );
+ }
+
+ return;
+
+ error:
+ errorString_ << "FileRead::open: error reading file (" << fileName << ")!";
+ handleError( StkError::FILE_ERROR );
+}
+
+bool FileRead :: getRawInfo( const char *fileName )
+{
+ // Use the system call "stat" to determine the file length.
+ struct stat filestat;
+ if ( stat(fileName, &filestat) == -1 ) {
+ errorString_ << "FileRead: Could not stat RAW file (" << fileName << ").";
+ return false;
+ }
+
+ // STK rawwave 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.
+ channels_ = 1;
+ fileSize_ = (long) filestat.st_size / 2; // length in 2-byte samples
+ dataOffset_ = 0;
+ fileRate_ = 22050.0;
+ dataType_ = STK_SINT16;
+ byteswap_ = false;
+#ifdef __LITTLE_ENDIAN__
+ byteswap_ = true;
+#endif
+
+ return true;
+}
+
+bool FileRead :: getWavInfo( const char *fileName )
+{
+ // Find "format" chunk ... it must come before the "data" chunk.
+ char id[4];
+ SINT32 chunkSize;
+ if ( fread(&id, 4, 1, fd_) != 1 ) goto error;
+ while ( strncmp(id, "fmt ", 4) ) {
+ if ( fread(&chunkSize, 4, 1, fd_) != 1 ) goto error;
+#ifndef __LITTLE_ENDIAN__
+ swap32((unsigned char *)&chunkSize);
+#endif
+ if ( fseek(fd_, chunkSize, SEEK_CUR) == -1 ) goto error;
+ if ( fread(&id, 4, 1, fd_) != 1 ) goto error;
+ }
+
+ // Check that the data is not compressed.
+ unsigned short format_tag;
+ if ( fread(&chunkSize, 4, 1, fd_) != 1 ) goto error; // Read fmt chunk size.
+ if ( fread(&format_tag, 2, 1, fd_) != 1 ) goto error;
+#ifndef __LITTLE_ENDIAN__
+ swap16((unsigned char *)&format_tag);
+ swap32((unsigned char *)&chunkSize);
+#endif
+ if ( format_tag == 0xFFFE ) { // WAVE_FORMAT_EXTENSIBLE
+ dataOffset_ = ftell(fd_);
+ if ( fseek(fd_, 14, SEEK_CUR) == -1 ) goto error;
+ unsigned short extSize;
+ if ( fread(&extSize, 2, 1, fd_) != 1 ) goto error;
+#ifndef __LITTLE_ENDIAN__
+ swap16((unsigned char *)&extSize);
+#endif
+ if ( extSize == 0 ) goto error;
+ if ( fseek(fd_, 6, SEEK_CUR) == -1 ) goto error;
+ if ( fread(&format_tag, 2, 1, fd_) != 1 ) goto error;
+#ifndef __LITTLE_ENDIAN__
+ swap16((unsigned char *)&format_tag);
+#endif
+ if ( fseek(fd_, dataOffset_, SEEK_SET) == -1 ) goto error;
+ }
+ if (format_tag != 1 && format_tag != 3 ) { // PCM = 1, FLOAT = 3
+ errorString_ << "FileRead: "<< fileName << " contains an unsupported data format type (" << format_tag << ").";
+ return false;
+ }
+
+ // Get number of channels from the header.
+ SINT16 temp;
+ if ( fread(&temp, 2, 1, fd_) != 1 ) goto error;
+#ifndef __LITTLE_ENDIAN__
+ swap16((unsigned char *)&temp);
+#endif
+ channels_ = (unsigned int ) temp;
+
+ // Get file sample rate from the header.
+ SINT32 srate;
+ if ( fread(&srate, 4, 1, fd_) != 1 ) goto error;
+#ifndef __LITTLE_ENDIAN__
+ swap32((unsigned char *)&srate);
+#endif
+ fileRate_ = (StkFloat) srate;
+
+ // Determine the data type.
+ dataType_ = 0;
+ if ( fseek(fd_, 6, SEEK_CUR) == -1 ) goto error; // Locate bits_per_sample info.
+ if ( fread(&temp, 2, 1, fd_) != 1 ) goto error;
+#ifndef __LITTLE_ENDIAN__
+ swap16((unsigned char *)&temp);
+#endif
+ if ( format_tag == 1 ) {
+ if (temp == 8)
+ dataType_ = STK_SINT8;
+ else if (temp == 16)
+ dataType_ = STK_SINT16;
+ else if (temp == 32)
+ dataType_ = STK_SINT32;
+ }
+ else if ( format_tag == 3 ) {
+ if (temp == 32)
+ dataType_ = STK_FLOAT32;
+ else if (temp == 64)
+ dataType_ = STK_FLOAT64;
+ }
+ if ( dataType_ == 0 ) {
+ errorString_ << "FileRead: " << temp << " bits per sample with data format " << format_tag << " are not supported (" << fileName << ").";
+ return false;
+ }
+
+ // Jump over any remaining part of the "fmt" chunk.
+ if ( fseek(fd_, chunkSize-16, SEEK_CUR) == -1 ) goto error;
+
+ // Find "data" chunk ... it must come after the "fmt" chunk.
+ if ( fread(&id, 4, 1, fd_) != 1 ) goto error;
+
+ while ( strncmp(id, "data", 4) ) {
+ if ( fread(&chunkSize, 4, 1, fd_) != 1 ) goto error;
+#ifndef __LITTLE_ENDIAN__
+ swap32((unsigned char *)&chunkSize);
+#endif
+ chunkSize += chunkSize % 2; // chunk sizes must be even
+ if ( fseek(fd_, chunkSize, SEEK_CUR) == -1 ) goto error;
+ if ( fread(&id, 4, 1, fd_) != 1 ) goto error;
+ }
+
+ // Get length of data from the header.
+ SINT32 bytes;
+ if ( fread(&bytes, 4, 1, fd_) != 1 ) goto error;
+#ifndef __LITTLE_ENDIAN__
+ swap32((unsigned char *)&bytes);
+#endif
+ fileSize_ = 8 * bytes / temp / channels_; // sample frames
+
+ dataOffset_ = ftell(fd_);
+ byteswap_ = false;
+#ifndef __LITTLE_ENDIAN__
+ byteswap_ = true;
+#endif
+
+ wavFile_ = true;
+ return true;
+
+ error:
+ errorString_ << "FileRead: error reading WAV file (" << fileName << ").";
+ return false;
+}
+
+bool FileRead :: getSndInfo( const char *fileName )
+{
+ // Determine the data type.
+ UINT32 format;
+ if ( fseek(fd_, 12, SEEK_SET) == -1 ) goto error; // Locate format
+ if ( fread(&format, 4, 1, fd_) != 1 ) goto error;
+#ifdef __LITTLE_ENDIAN__
+ swap32((unsigned char *)&format);
+#endif
+ if (format == 2) dataType_ = STK_SINT8;
+ else if (format == 3) dataType_ = STK_SINT16;
+ else if (format == 4) dataType_ = STK_SINT24;
+ else if (format == 5) dataType_ = STK_SINT32;
+ else if (format == 6) dataType_ = STK_FLOAT32;
+ else if (format == 7) dataType_ = STK_FLOAT64;
+ else {
+ errorString_ << "FileRead: data format in file " << fileName << " is not supported.";
+ return false;
+ }
+
+ // Get file sample rate from the header.
+ UINT32 srate;
+ if ( fread(&srate, 4, 1, fd_) != 1 ) goto error;
+#ifdef __LITTLE_ENDIAN__
+ swap32((unsigned char *)&srate);
+#endif
+ fileRate_ = (StkFloat) srate;
+
+ // Get number of channels from the header.
+ UINT32 chans;
+ if ( fread(&chans, 4, 1, fd_) != 1 ) goto error;
+#ifdef __LITTLE_ENDIAN__
+ swap32((unsigned char *)&chans);
+#endif
+ channels_ = chans;
+
+ if ( fseek(fd_, 4, SEEK_SET) == -1 ) goto error;
+ if ( fread(&dataOffset_, 4, 1, fd_) != 1 ) goto error;
+#ifdef __LITTLE_ENDIAN__
+ swap32((unsigned char *)&dataOffset_);
+#endif
+
+ // Get length of data from the header.
+ if ( fread(&fileSize_, 4, 1, fd_) != 1 ) goto error;
+#ifdef __LITTLE_ENDIAN__
+ swap32((unsigned char *)&fileSize_);
+#endif
+ // Convert to sample frames.
+ if ( dataType_ == STK_SINT8 )
+ fileSize_ /= channels_;
+ if ( dataType_ == STK_SINT16 )
+ fileSize_ /= 2 * channels_;
+ else if ( dataType_ == STK_SINT24 )
+ fileSize_ /= 3 * channels_;
+ else if ( dataType_ == STK_SINT32 || dataType_ == STK_FLOAT32 )
+ fileSize_ /= 4 * channels_;
+ else if ( dataType_ == STK_FLOAT64 )
+ fileSize_ /= 8 * channels_;
+
+ byteswap_ = false;
+#ifdef __LITTLE_ENDIAN__
+ byteswap_ = true;
+#endif
+
+ return true;
+
+ error:
+ errorString_ << "FileRead: Error reading SND file (" << fileName << ").";
+ return false;
+}
+
+bool FileRead :: getAifInfo( const char *fileName )
+{
+ bool aifc = false;
+ char id[4];
+
+ // Determine whether this is AIFF or AIFC.
+ if ( fseek(fd_, 8, SEEK_SET) == -1 ) goto error;
+ if ( fread(&id, 4, 1, fd_) != 1 ) goto error;
+ if ( !strncmp(id, "AIFC", 4) ) aifc = true;
+
+ // Find "common" chunk
+ SINT32 chunkSize;
+ if ( fread(&id, 4, 1, fd_) != 1) goto error;
+ while ( strncmp(id, "COMM", 4) ) {
+ if ( fread(&chunkSize, 4, 1, fd_) != 1 ) goto error;
+#ifdef __LITTLE_ENDIAN__
+ swap32((unsigned char *)&chunkSize);
+#endif
+ chunkSize += chunkSize % 2; // chunk sizes must be even
+ if ( fseek(fd_, chunkSize, SEEK_CUR) == -1 ) goto error;
+ if ( fread(&id, 4, 1, fd_) != 1 ) goto error;
+ }
+
+ // Get number of channels from the header.
+ SINT16 temp;
+ if ( fseek(fd_, 4, SEEK_CUR) == -1 ) goto error; // Jump over chunk size
+ if ( fread(&temp, 2, 1, fd_) != 1 ) goto error;
+#ifdef __LITTLE_ENDIAN__
+ swap16((unsigned char *)&temp);
+#endif
+ channels_ = temp;
+
+ // Get length of data from the header.
+ SINT32 frames;
+ if ( fread(&frames, 4, 1, fd_) != 1 ) goto error;
+#ifdef __LITTLE_ENDIAN__
+ swap32((unsigned char *)&frames);
+#endif
+ fileSize_ = frames; // sample frames
+
+ // Read the number of bits per sample.
+ if ( fread(&temp, 2, 1, fd_) != 1 ) goto error;
+#ifdef __LITTLE_ENDIAN__
+ swap16((unsigned char *)&temp);
+#endif
+
+ // Get file sample rate from the header. For AIFF files, this value
+ // is stored in a 10-byte, IEEE Standard 754 floating point number,
+ // so we need to convert it first.
+ unsigned char srate[10];
+ unsigned char exp;
+ unsigned long mantissa;
+ unsigned long last;
+ if ( fread(&srate, 10, 1, fd_) != 1 ) goto error;
+ mantissa = (unsigned long) *(unsigned long *)(srate+2);
+#ifdef __LITTLE_ENDIAN__
+ swap32((unsigned char *)&mantissa);
+#endif
+ exp = 30 - *(srate+1);
+ last = 0;
+ while (exp--) {
+ last = mantissa;
+ mantissa >>= 1;
+ }
+ if (last & 0x00000001) mantissa++;
+ fileRate_ = (StkFloat) mantissa;
+
+ // Determine the data format.
+ dataType_ = 0;
+ if ( aifc == false ) {
+ if ( temp <= 8 ) dataType_ = STK_SINT8;
+ else if ( temp <= 16 ) dataType_ = STK_SINT16;
+ else if ( temp <= 24 ) dataType_ = STK_SINT24;
+ else if ( temp <= 32 ) dataType_ = STK_SINT32;
+ }
+ else {
+ if ( fread(&id, 4, 1, fd_) != 1 ) goto error;
+ if ( !strncmp(id, "NONE", 4) ) {
+ if ( temp <= 8 ) dataType_ = STK_SINT8;
+ else if ( temp <= 16 ) dataType_ = STK_SINT16;
+ else if ( temp <= 24 ) dataType_ = STK_SINT24;
+ else if ( temp <= 32 ) dataType_ = STK_SINT32;
+ }
+ else if ( (!strncmp(id, "fl32", 4) || !strncmp(id, "FL32", 4)) && temp == 32 ) dataType_ = STK_FLOAT32;
+ else if ( (!strncmp(id, "fl64", 4) || !strncmp(id, "FL64", 4)) && temp == 64 ) dataType_ = STK_FLOAT64;
+ }
+ if ( dataType_ == 0 ) {
+ errorString_ << "FileRead: AIFF/AIFC file (" << fileName << ") has unsupported data type (" << id << ").";
+ return false;
+ }
+
+ // Start at top to find data (SSND) chunk ... chunk order is undefined.
+ if ( fseek(fd_, 12, SEEK_SET) == -1 ) goto error;
+
+ // Find data (SSND) chunk
+ if ( fread(&id, 4, 1, fd_) != 1 ) goto error;
+ while ( strncmp(id, "SSND", 4) ) {
+ if ( fread(&chunkSize, 4, 1, fd_) != 1 ) goto error;
+#ifdef __LITTLE_ENDIAN__
+ swap32((unsigned char *)&chunkSize);
+#endif
+ chunkSize += chunkSize % 2; // chunk sizes must be even
+ if ( fseek(fd_, chunkSize, SEEK_CUR) == -1 ) goto error;
+ if ( fread(&id, 4, 1, fd_) != 1 ) goto error;
+ }
+
+ // Skip over chunk size, offset, and blocksize fields
+ if ( fseek(fd_, 12, SEEK_CUR) == -1 ) goto error;
+
+ dataOffset_ = ftell(fd_);
+ byteswap_ = false;
+#ifdef __LITTLE_ENDIAN__
+ byteswap_ = true;
+#endif
+
+ return true;
+
+ error:
+ errorString_ << "FileRead: Error reading AIFF file (" << fileName << ").";
+ return false;
+}
+
+bool FileRead :: getMatInfo( const char *fileName )
+{
+ // MAT-file formatting information is available at:
+ // http://www.mathworks.com/access/helpdesk/help/pdf_doc/matlab/matfile_format.pdf
+
+ // Verify this is a version 5 MAT-file format.
+ char head[4];
+ if ( fseek(fd_, 0, SEEK_SET) == -1 ) goto error;
+ if ( fread(&head, 4, 1, fd_) != 1 ) goto error;
+ // If any of the first 4 characters of the header = 0, then this is
+ // a Version 4 MAT-file.
+ if ( strstr(head, "0") ) {
+ errorString_ << "FileRead: " << fileName << " appears to be a Version 4 MAT-file, which is not currently supported.";
+ return false;
+ }
+
+ // Determine the endian-ness of the file.
+ char mi[2];
+ byteswap_ = false;
+ // Locate "M" and "I" characters in header.
+ if ( fseek(fd_, 126, SEEK_SET) == -1 ) goto error;
+ if ( fread(&mi, 2, 1, fd_) != 1) goto error;
+#ifdef __LITTLE_ENDIAN__
+ if ( !strncmp(mi, "MI", 2) )
+ byteswap_ = true;
+ else if ( strncmp(mi, "IM", 2) ) goto error;
+#else
+ if ( !strncmp(mi, "IM", 2))
+ byteswap_ = true;
+ else if ( strncmp(mi, "MI", 2) ) goto error;
+#endif
+
+ // Check the data element type
+ SINT32 datatype;
+ if ( fread(&datatype, 4, 1, fd_) != 1 ) goto error;
+ if ( byteswap_ ) swap32((unsigned char *)&datatype);
+ if (datatype != 14) {
+ errorString_ << "FileRead: The file does not contain a single Matlab array (or matrix) data element.";
+ return false;
+ }
+
+ // Determine the array data type.
+ SINT32 tmp;
+ SINT32 size;
+ if ( fseek(fd_, 168, SEEK_SET) == -1 ) goto error;
+ if ( fread(&tmp, 4, 1, fd_) != 1 ) goto error;
+ if (byteswap_) swap32((unsigned char *)&tmp);
+ if (tmp == 1) { // array name > 4 characters
+ if ( fread(&tmp, 4, 1, fd_) != 1 ) goto error; // get array name length
+ if (byteswap_) swap32((unsigned char *)&tmp);
+ size = (SINT32) ceil((float)tmp / 8);
+ if ( fseek(fd_, size*8, SEEK_CUR) == -1 ) goto error; // jump over array name
+ }
+ else { // array name <= 4 characters, compressed data element
+ if ( fseek(fd_, 4, SEEK_CUR) == -1 ) goto error;
+ }
+ if ( fread(&tmp, 4, 1, fd_) != 1 ) goto error;
+ if (byteswap_) swap32((unsigned char *)&tmp);
+ if ( tmp == 1 ) dataType_ = STK_SINT8;
+ else if ( tmp == 3 ) dataType_ = STK_SINT16;
+ else if ( tmp == 5 ) dataType_ = STK_SINT32;
+ else if ( tmp == 7 ) dataType_ = STK_FLOAT32;
+ else if ( tmp == 9 ) dataType_ = STK_FLOAT64;
+ else {
+ errorString_ << "FileRead: The MAT-file array data format (" << tmp << ") is not supported.";
+ return false;
+ }
+
+ // Get number of rows from the header.
+ SINT32 rows;
+ if ( fseek(fd_, 160, SEEK_SET) == -1 ) goto error;
+ if ( fread(&rows, 4, 1, fd_) != 1 ) goto error;
+ if (byteswap_) swap32((unsigned char *)&rows);
+
+ // Get number of columns from the header.
+ SINT32 columns;
+ if ( fread(&columns, 4, 1, fd_) != 1 ) goto error;
+ if (byteswap_) swap32((unsigned char *)&columns);
+
+ // Assume channels = smaller of rows or columns.
+ if (rows < columns) {
+ channels_ = rows;
+ fileSize_ = columns;
+ }
+ else {
+ errorString_ << "FileRead: Transpose the MAT-file array so that audio channels fill matrix rows (not columns).";
+ return false;
+ }
+
+ // Move read pointer to the data in the file.
+ SINT32 headsize;
+ if ( fseek(fd_, 132, SEEK_SET) == -1 ) goto error;
+ if ( fread(&headsize, 4, 1, fd_) != 1 ) goto error; // file size from 132nd byte
+ if (byteswap_) swap32((unsigned char *)&headsize);
+ headsize -= fileSize_ * 8 * channels_;
+ if ( fseek(fd_, headsize, SEEK_CUR) == -1 ) goto error;
+ dataOffset_ = ftell(fd_);
+
+ // Assume MAT-files have 44100 Hz sample rate.
+ fileRate_ = 44100.0;
+
+ return true;
+
+ error:
+ errorString_ << "FileRead: Error reading MAT-file (" << fileName << ").";
+ return false;
+}
+
+void FileRead :: read( StkFrames& buffer, unsigned long startFrame, bool doNormalize )
+{
+ // Make sure we have an open file.
+ if ( fd_ == 0 ) {
+ errorString_ << "FileRead::read: a file is not open!";
+ Stk::handleError( StkError::WARNING );
+ return;
+ }
+
+ // Check the buffer size.
+ unsigned int nFrames = buffer.frames();
+ if ( nFrames == 0 ) {
+ errorString_ << "FileRead::read: StkFrames buffer size is zero ... no data read!";
+ Stk::handleError( StkError::WARNING );
+ return;
+ }
+
+ if ( buffer.channels() != channels_ ) {
+ errorString_ << "FileRead::read: StkFrames argument has incompatible number of channels!";
+ Stk::handleError( StkError::FUNCTION_ARGUMENT );
+ }
+
+ // Check for file end.
+ if ( startFrame + nFrames >= fileSize_ )
+ nFrames = fileSize_ - startFrame;
+
+ long i, nSamples = (long) ( nFrames * channels_ );
+ unsigned long offset = startFrame * channels_;
+
+ // Read samples into StkFrames data buffer.
+ if ( dataType_ == STK_SINT16 ) {
+ SINT16 *buf = (SINT16 *) &buffer[0];
+ if ( fseek( fd_, dataOffset_+(offset*2), SEEK_SET ) == -1 ) goto error;
+ if ( fread( buf, nSamples * 2, 1, fd_ ) != 1 ) goto error;
+ if ( byteswap_ ) {
+ SINT16 *ptr = buf;
+ for ( i=nSamples-1; i>=0; i-- )
+ swap16( (unsigned char *) ptr++ );
+ }
+ if ( doNormalize ) {
+ StkFloat gain = 1.0 / 32768.0;
+ for ( i=nSamples-1; i>=0; i-- )
+ buffer[i] = buf[i] * gain;
+ }
+ else {
+ for ( i=nSamples-1; i>=0; i-- )
+ buffer[i] = buf[i];
+ }
+ }
+ else if ( dataType_ == STK_SINT32 ) {
+ SINT32 *buf = (SINT32 *) &buffer[0];
+ if ( fseek( fd_, dataOffset_+(offset*4 ), SEEK_SET ) == -1 ) goto error;
+ if ( fread( buf, nSamples * 4, 1, fd_ ) != 1 ) goto error;
+ if ( byteswap_ ) {
+ SINT32 *ptr = buf;
+ for ( i=nSamples-1; i>=0; i-- )
+ swap32( (unsigned char *) ptr++ );
+ }
+ if ( doNormalize ) {
+ StkFloat gain = 1.0 / 2147483648.0;
+ for ( i=nSamples-1; i>=0; i-- )
+ buffer[i] = buf[i] * gain;
+ }
+ else {
+ for ( i=nSamples-1; i>=0; i-- )
+ buffer[i] = buf[i];
+ }
+ }
+ else if ( dataType_ == STK_FLOAT32 ) {
+ FLOAT32 *buf = (FLOAT32 *) &buffer[0];
+ if ( fseek( fd_, dataOffset_+(offset*4), SEEK_SET ) == -1 ) goto error;
+ if ( fread( buf, nSamples * 4, 1, fd_ ) != 1 ) goto error;
+ if ( byteswap_ ) {
+ FLOAT32 *ptr = buf;
+ for ( i=nSamples-1; i>=0; i-- )
+ swap32( (unsigned char *) ptr++ );
+ }
+ for ( i=nSamples-1; i>=0; i-- )
+ buffer[i] = buf[i];
+ }
+ else if ( dataType_ == STK_FLOAT64 ) {
+ FLOAT64 *buf = (FLOAT64 *) &buffer[0];
+ if ( fseek( fd_, dataOffset_+(offset*8), SEEK_SET ) == -1 ) goto error;
+ if ( fread( buf, nSamples * 8, 1, fd_ ) != 1 ) goto error;
+ if ( byteswap_ ) {
+ FLOAT64 *ptr = buf;
+ for ( i=nSamples-1; i>=0; i-- )
+ swap64( (unsigned char *) ptr++ );
+ }
+ for ( i=nSamples-1; i>=0; i-- )
+ buffer[i] = buf[i];
+ }
+ else if ( dataType_ == STK_SINT8 && wavFile_ ) { // 8-bit WAV data is unsigned!
+ unsigned char *buf = (unsigned char *) &buffer[0];
+ if ( fseek( fd_, dataOffset_+offset, SEEK_SET ) == -1 ) goto error;
+ if ( fread( buf, nSamples, 1, fd_) != 1 ) goto error;
+ if ( doNormalize ) {
+ StkFloat gain = 1.0 / 128.0;
+ for ( i=nSamples-1; i>=0; i-- )
+ buffer[i] = ( buf[i] - 128 ) * gain;
+ }
+ else {
+ for ( i=nSamples-1; i>=0; i-- )
+ buffer[i] = buf[i] - 128.0;
+ }
+ }
+ else if ( dataType_ == STK_SINT8 ) { // signed 8-bit data
+ char *buf = (char *) &buffer[0];
+ if ( fseek( fd_, dataOffset_+offset, SEEK_SET ) == -1 ) goto error;
+ if ( fread( buf, nSamples, 1, fd_ ) != 1 ) goto error;
+ if ( doNormalize ) {
+ StkFloat gain = 1.0 / 128.0;
+ for ( i=nSamples-1; i>=0; i-- )
+ buffer[i] = buf[i] * gain;
+ }
+ else {
+ for ( i=nSamples-1; i>=0; i-- )
+ buffer[i] = buf[i];
+ }
+ }
+ else if ( dataType_ == STK_SINT24 ) {
+ // 24-bit values are harder to import efficiently since there is
+ // no native 24-bit type. The following routine works but is much
+ // less efficient that that used for the other data types.
+ SINT32 buf;
+ StkFloat gain = 1.0 / 8388608.0;
+ if ( fseek(fd_, dataOffset_+(offset*3), SEEK_SET ) == -1 ) goto error;
+ for ( i=0; i>= 8;
+ if ( byteswap_ )
+ swap32( (unsigned char *) &buf );
+ if ( doNormalize )
+ buffer[i] = buf * gain;
+ else
+ buffer[i] = buf;
+ }
+ }
+
+ buffer.setDataRate( fileRate_ );
+
+ return;
+
+ error:
+ errorString_ << "FileRead: Error reading file data.";
+ handleError( StkError::FILE_ERROR);
+}
+
diff --git a/src/FileWrite.cpp b/src/FileWrite.cpp
new file mode 100644
index 0000000..671c9ab
--- /dev/null
+++ b/src/FileWrite.cpp
@@ -0,0 +1,701 @@
+/***************************************************/
+/*! \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-, 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 - 2005.
+*/
+/***************************************************/
+
+#include "FileWrite.h"
+#include
+
+const FileWrite::FILE_TYPE FileWrite :: FILE_RAW = 1;
+const FileWrite::FILE_TYPE FileWrite :: FILE_WAV = 2;
+const FileWrite::FILE_TYPE FileWrite :: FILE_SND = 3;
+const FileWrite::FILE_TYPE FileWrite :: FILE_AIF = 4;
+const FileWrite::FILE_TYPE FileWrite :: FILE_MAT = 5;
+
+// WAV header structure. See ftp://ftp.isi.edu/in-notes/rfc2361.txt
+// for information regarding format codes.
+struct wavhdr {
+ char riff[4]; // "RIFF"
+ SINT32 file_size; // in bytes
+ char wave[4]; // "WAVE"
+ char fmt[4]; // "fmt "
+ SINT32 chunk_size; // in bytes (16 for PCM)
+ SINT16 format_tag; // 1=PCM, 2=ADPCM, 3=IEEE float, 6=A-Law, 7=Mu-Law
+ SINT16 num_chans; // 1=mono, 2=stereo
+ SINT32 sample_rate;
+ SINT32 bytes_per_sec;
+ SINT16 bytes_per_samp; // 2=16-bit mono, 4=16-bit stereo
+ SINT16 bits_per_samp;
+ char data[4]; // "data"
+ SINT32 data_length; // in bytes
+};
+
+// SND (AU) header structure (NeXT and Sun).
+struct sndhdr {
+ char pref[4];
+ SINT32 hdr_length;
+ SINT32 data_length;
+ SINT32 format;
+ SINT32 sample_rate;
+ SINT32 num_channels;
+ char comment[16];
+};
+
+// AIFF/AIFC header structure ... only the part common to both
+// formats.
+struct aifhdr {
+ char form[4]; // "FORM"
+ SINT32 form_size; // in bytes
+ char aiff[4]; // "AIFF" or "AIFC"
+ char comm[4]; // "COMM"
+ SINT32 comm_size; // "COMM" chunk size (18 for AIFF, 24 for AIFC)
+ SINT16 num_chans; // number of channels
+ unsigned long sample_frames; // sample frames of audio data
+ SINT16 sample_size; // in bits
+ unsigned char srate[10]; // IEEE 754 floating point format
+};
+
+struct aifssnd {
+ char ssnd[4]; // "SSND"
+ SINT32 ssnd_size; // "SSND" chunk size
+ unsigned long offset; // data offset in data block (should be 0)
+ unsigned long block_size; // not used by STK (should be 0)
+};
+
+// MAT-file 5 header structure.
+struct mathdr {
+ char heading[124]; // Header text field
+ SINT16 hff[2]; // Header flag fields
+ SINT32 adf[11]; // Array data format fields
+ // There's more, but it's of variable length
+};
+
+FileWrite :: FileWrite()
+ : fd_( 0 )
+{
+}
+
+FileWrite::FileWrite( std::string fileName, unsigned int nChannels, FILE_TYPE type, Stk::StkFormat format )
+ : fd_( 0 )
+{
+ this->open( fileName, nChannels, type, format );
+}
+
+FileWrite :: ~FileWrite()
+{
+ this->close();
+}
+
+void FileWrite :: close( void )
+{
+ if ( fd_ == 0 ) return;
+
+ if ( fileType_ == FILE_RAW )
+ fclose( fd_ );
+ else if ( fileType_ == FILE_WAV )
+ this->closeWavFile();
+ else if ( fileType_ == FILE_SND )
+ this->closeSndFile();
+ else if ( fileType_ == FILE_AIF )
+ this->closeAifFile();
+ else if ( fileType_ == FILE_MAT )
+ this->closeMatFile();
+
+ fd_ = 0;
+}
+
+bool FileWrite :: isOpen( void )
+{
+ if ( fd_ ) return true;
+ else return false;
+}
+
+void FileWrite :: open( std::string fileName, unsigned int nChannels, FileWrite::FILE_TYPE type, Stk::StkFormat format )
+{
+ // Call close() in case another file is already open.
+ this->close();
+
+ if ( nChannels < 1 ) {
+ errorString_ << "FileWrite::open: then channels argument must be greater than zero!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+
+ channels_ = nChannels;
+ fileType_ = type;
+
+ if ( format != STK_SINT8 && format != STK_SINT16 &&
+ format != STK_SINT32 && format != STK_FLOAT32 &&
+ format != STK_FLOAT64 ) {
+ errorString_ << "FileWrite::open: unknown data type (" << format << ") specified!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+ dataType_ = format;
+
+ bool result = false;
+ if ( fileType_ == FILE_RAW ) {
+ if ( channels_ != 1 ) {
+ errorString_ << "FileWrite::open: STK RAW files are, by definition, always monaural (channels = " << nChannels << " not supported)!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+ result = setRawFile( fileName.c_str() );
+ }
+ else if ( fileType_ == FILE_WAV )
+ result = setWavFile( fileName.c_str() );
+ else if ( fileType_ == FILE_SND )
+ result = setSndFile( fileName.c_str() );
+ else if ( fileType_ == FILE_AIF )
+ result = setAifFile( fileName.c_str() );
+ else if ( fileType_ == FILE_MAT )
+ result = setMatFile( fileName.c_str() );
+ else {
+ errorString_ << "FileWrite::open: unknown file type (" << fileType_ << ") specified!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+
+ if ( result == false )
+ handleError( StkError::FILE_ERROR );
+
+ frameCounter_ = 0;
+}
+
+bool FileWrite :: setRawFile( const char *fileName )
+{
+ char name[8192];
+ strncpy(name, fileName, 8192);
+ if ( strstr(name, ".raw") == NULL) strcat(name, ".raw");
+ fd_ = fopen(name, "wb");
+ if ( !fd_ ) {
+ errorString_ << "FileWrite: could not create RAW file: " << name << '.';
+ return false;
+ }
+
+ if ( dataType_ != STK_SINT16 ) {
+ dataType_ = STK_SINT16;
+ errorString_ << "FileWrite: using 16-bit signed integer data format for file " << name << '.';
+ handleError( StkError::DEBUG_WARNING );
+ }
+
+ byteswap_ = false;
+#ifdef __LITTLE_ENDIAN__
+ byteswap_ = true;
+#endif
+
+ errorString_ << "FileWrite: creating RAW file: " << name;
+ handleError( StkError::STATUS );
+ return true;
+}
+
+bool FileWrite :: setWavFile( const char *fileName )
+{
+ char name[8192];
+ strncpy(name, fileName, 8192);
+ if ( strstr(name, ".wav") == NULL) strcat(name, ".wav");
+ fd_ = fopen(name, "wb");
+ if ( !fd_ ) {
+ errorString_ << "FileWrite: could not create WAV file: " << name;
+ return false;
+ }
+
+ struct wavhdr hdr = {"RIF", 44, "WAV", "fmt", 16, 1, 1,
+ (SINT32) Stk::sampleRate(), 0, 2, 16, "dat", 0};
+ hdr.riff[3] = 'F';
+ hdr.wave[3] = 'E';
+ hdr.fmt[3] = ' ';
+ hdr.data[3] = 'a';
+ hdr.num_chans = (SINT16) channels_;
+ if ( dataType_ == STK_SINT8 )
+ hdr.bits_per_samp = 8;
+ else if ( dataType_ == STK_SINT16 )
+ hdr.bits_per_samp = 16;
+ else if ( dataType_ == STK_SINT32 )
+ hdr.bits_per_samp = 32;
+ else if ( dataType_ == STK_FLOAT32 ) {
+ hdr.format_tag = 3;
+ hdr.bits_per_samp = 32;
+ }
+ else if ( dataType_ == STK_FLOAT64 ) {
+ hdr.format_tag = 3;
+ hdr.bits_per_samp = 64;
+ }
+ hdr.bytes_per_samp = (SINT16) (channels_ * hdr.bits_per_samp / 8);
+ hdr.bytes_per_sec = (SINT32) (hdr.sample_rate * hdr.bytes_per_samp);
+
+ byteswap_ = false;
+#ifndef __LITTLE_ENDIAN__
+ byteswap_ = true;
+ swap32((unsigned char *)&hdr.file_size);
+ swap32((unsigned char *)&hdr.chunk_size);
+ swap16((unsigned char *)&hdr.format_tag);
+ swap16((unsigned char *)&hdr.num_chans);
+ swap32((unsigned char *)&hdr.sample_rate);
+ swap32((unsigned char *)&hdr.bytes_per_sec);
+ swap16((unsigned char *)&hdr.bytes_per_samp);
+ swap16((unsigned char *)&hdr.bits_per_samp);
+#endif
+
+ if ( fwrite(&hdr, 4, 11, fd_) != 11 ) {
+ errorString_ << "FileWrite: could not write WAV header for file " << name << '.';
+ return false;
+ }
+
+ errorString_ << "FileWrite: creating WAV file: " << name;
+ handleError( StkError::STATUS );
+ return true;
+}
+
+void FileWrite :: closeWavFile( void )
+{
+ int bytes_per_sample = 1;
+ if ( dataType_ == STK_SINT16 )
+ bytes_per_sample = 2;
+ else if ( dataType_ == STK_SINT32 || dataType_ == STK_FLOAT32 )
+ bytes_per_sample = 4;
+ else if ( dataType_ == STK_FLOAT64 )
+ bytes_per_sample = 8;
+
+ SINT32 bytes = frameCounter_ * channels_ * bytes_per_sample;
+#ifndef __LITTLE_ENDIAN__
+ swap32((unsigned char *)&bytes);
+#endif
+ fseek(fd_, 40, SEEK_SET); // jump to data length
+ fwrite(&bytes, 4, 1, fd_);
+
+ bytes = frameCounter_ * channels_ * bytes_per_sample + 44;
+#ifndef __LITTLE_ENDIAN__
+ swap32((unsigned char *)&bytes);
+#endif
+ fseek(fd_, 4, SEEK_SET); // jump to file size
+ fwrite(&bytes, 4, 1, fd_);
+ fclose( fd_ );
+}
+
+bool FileWrite :: setSndFile( const char *fileName )
+{
+ char name[8192];
+ strncpy(name, fileName, 8192);
+ if ( strstr(name, ".snd") == NULL) strcat(name, ".snd");
+ fd_ = fopen(name, "wb");
+ if ( !fd_ ) {
+ errorString_ << "FileWrite: could not create SND file: " << name;
+ return false;
+ }
+
+ struct sndhdr hdr = {".sn", 40, 0, 3, (SINT32) Stk::sampleRate(), 1, "Created by STK"};
+ hdr.pref[3] = 'd';
+ hdr.num_channels = channels_;
+ if ( dataType_ == STK_SINT8 )
+ hdr.format = 2;
+ else if ( dataType_ == STK_SINT16 )
+ hdr.format = 3;
+ else if ( dataType_ == STK_SINT32 )
+ hdr.format = 5;
+ else if ( dataType_ == STK_FLOAT32 )
+ hdr.format = 6;
+ else if ( dataType_ == STK_FLOAT64 )
+ hdr.format = 7;
+
+ byteswap_ = false;
+#ifdef __LITTLE_ENDIAN__
+ byteswap_ = true;
+ swap32 ((unsigned char *)&hdr.hdr_length);
+ swap32 ((unsigned char *)&hdr.format);
+ swap32 ((unsigned char *)&hdr.sample_rate);
+ swap32 ((unsigned char *)&hdr.num_channels);
+#endif
+
+ if ( fwrite(&hdr, 4, 10, fd_) != 10 ) {
+ errorString_ << "FileWrite: Could not write SND header for file " << name << '.';
+ return false;
+ }
+
+ errorString_ << "FileWrite: creating SND file: " << name;
+ handleError( StkError::STATUS );
+ return true;
+}
+
+void FileWrite :: closeSndFile( void )
+{
+ int bytes_per_sample = 1;
+ if ( dataType_ == STK_SINT16 )
+ bytes_per_sample = 2;
+ else if ( dataType_ == STK_SINT32 )
+ bytes_per_sample = 4;
+ else if ( dataType_ == STK_FLOAT32 )
+ bytes_per_sample = 4;
+ else if ( dataType_ == STK_FLOAT64 )
+ bytes_per_sample = 8;
+
+ SINT32 bytes = frameCounter_ * bytes_per_sample * channels_;
+#ifdef __LITTLE_ENDIAN__
+ swap32 ((unsigned char *)&bytes);
+#endif
+ fseek(fd_, 8, SEEK_SET); // jump to data size
+ fwrite(&bytes, 4, 1, fd_);
+ fclose(fd_);
+}
+
+bool FileWrite :: setAifFile( const char *fileName )
+{
+ char name[8192];
+ strncpy(name, fileName, 8192);
+ if ( strstr(name, ".aif") == NULL) strcat(name, ".aif");
+ fd_ = fopen(name, "wb");
+ if ( !fd_ ) {
+ errorString_ << "FileWrite: could not create AIF file: " << name;
+ return false;
+ }
+
+ // Common parts of AIFF/AIFC header.
+ struct aifhdr hdr = {"FOR", 46, "AIF", "COM", 18, 0, 0, 16, "0"};
+ struct aifssnd ssnd = {"SSN", 8, 0, 0};
+ hdr.form[3] = 'M';
+ hdr.aiff[3] = 'F';
+ hdr.comm[3] = 'M';
+ ssnd.ssnd[3] = 'D';
+ hdr.num_chans = channels_;
+ if ( dataType_ == STK_SINT8 )
+ hdr.sample_size = 8;
+ else if ( dataType_ == STK_SINT16 )
+ hdr.sample_size = 16;
+ else if ( dataType_ == STK_SINT32 )
+ hdr.sample_size = 32;
+ else if ( dataType_ == STK_FLOAT32 ) {
+ hdr.aiff[3] = 'C';
+ hdr.sample_size = 32;
+ hdr.comm_size = 24;
+ }
+ else if ( dataType_ == STK_FLOAT64 ) {
+ hdr.aiff[3] = 'C';
+ hdr.sample_size = 64;
+ hdr.comm_size = 24;
+ }
+
+ // For AIFF files, the sample rate is stored in a 10-byte,
+ // IEEE Standard 754 floating point number, so we need to
+ // convert to that.
+ SINT16 i;
+ unsigned long exp;
+ unsigned long rate = (unsigned long) Stk::sampleRate();
+ memset(hdr.srate, 0, 10);
+ exp = rate;
+ for (i=0; i<32; i++) {
+ exp >>= 1;
+ if (!exp) break;
+ }
+ i += 16383;
+#ifdef __LITTLE_ENDIAN__
+ swap16((unsigned char *)&i);
+#endif
+ *(SINT16 *)(hdr.srate) = (SINT16) i;
+
+ for (i=32; i; i--) {
+ if (rate & 0x80000000) break;
+ rate <<= 1;
+ }
+
+#ifdef __LITTLE_ENDIAN__
+ swap32((unsigned char *)&rate);
+#endif
+ *(unsigned long *)(hdr.srate+2) = (unsigned long) rate;
+
+ byteswap_ = false;
+#ifdef __LITTLE_ENDIAN__
+ byteswap_ = true;
+ swap32((unsigned char *)&hdr.form_size);
+ swap32((unsigned char *)&hdr.comm_size);
+ swap16((unsigned char *)&hdr.num_chans);
+ swap16((unsigned char *)&hdr.sample_size);
+ swap32((unsigned char *)&ssnd.ssnd_size);
+ swap32((unsigned char *)&ssnd.offset);
+ swap32((unsigned char *)&ssnd.block_size);
+#endif
+
+ // The structure boundaries don't allow a single write of 54 bytes.
+ if ( fwrite(&hdr, 4, 5, fd_) != 5 ) goto error;
+ if ( fwrite(&hdr.num_chans, 2, 1, fd_) != 1 ) goto error;
+ if ( fwrite(&hdr.sample_frames, 4, 1, fd_) != 1 ) goto error;
+ if ( fwrite(&hdr.sample_size, 2, 1, fd_) != 1 ) goto error;
+ if ( fwrite(&hdr.srate, 10, 1, fd_) != 1 ) goto error;
+
+ if ( dataType_ == STK_FLOAT32 ) {
+ char type[4] = {'f','l','3','2'};
+ char zeroes[2] = { 0, 0 };
+ if ( fwrite(&type, 4, 1, fd_) != 1 ) goto error;
+ if ( fwrite(&zeroes, 2, 1, fd_) != 1 ) goto error;
+ }
+ else if ( dataType_ == STK_FLOAT64 ) {
+ char type[4] = {'f','l','6','4'};
+ char zeroes[2] = { 0, 0 };
+ if ( fwrite(&type, 4, 1, fd_) != 1 ) goto error;
+ if ( fwrite(&zeroes, 2, 1, fd_) != 1 ) goto error;
+ }
+
+ if ( fwrite(&ssnd, 4, 4, fd_) != 4 ) goto error;
+
+ errorString_ << "FileWrite: creating AIF file: " << name;
+ handleError( StkError::STATUS );
+ return true;
+
+ error:
+ errorString_ << "FileWrite: could not write AIF header for file: " << name;
+ return false;
+}
+
+void FileWrite :: closeAifFile( void )
+{
+ unsigned long frames = (unsigned long) frameCounter_;
+#ifdef __LITTLE_ENDIAN__
+ swap32((unsigned char *)&frames);
+#endif
+ fseek(fd_, 22, SEEK_SET); // jump to "COMM" sample_frames
+ fwrite(&frames, 4, 1, fd_);
+
+ int bytes_per_sample = 1;
+ if ( dataType_ == STK_SINT16 )
+ bytes_per_sample = 2;
+ else if ( dataType_ == STK_SINT32 || dataType_ == STK_FLOAT32 )
+ bytes_per_sample = 4;
+ else if ( dataType_ == STK_FLOAT64 )
+ bytes_per_sample = 8;
+
+ unsigned long bytes = frameCounter_ * bytes_per_sample * channels_ + 46;
+ if ( dataType_ == STK_FLOAT32 || dataType_ == STK_FLOAT64 ) bytes += 6;
+#ifdef __LITTLE_ENDIAN__
+ swap32((unsigned char *)&bytes);
+#endif
+ fseek(fd_, 4, SEEK_SET); // jump to file size
+ fwrite(&bytes, 4, 1, fd_);
+
+ bytes = frameCounter_ * bytes_per_sample * channels_ + 8;
+ if ( dataType_ == STK_FLOAT32 || dataType_ == STK_FLOAT64 ) bytes += 6;
+#ifdef __LITTLE_ENDIAN__
+ swap32((unsigned char *)&bytes);
+#endif
+ if ( dataType_ == STK_FLOAT32 || dataType_ == STK_FLOAT64 )
+ fseek(fd_, 48, SEEK_SET); // jump to "SSND" chunk size
+ else
+ fseek(fd_, 42, SEEK_SET); // jump to "SSND" chunk size
+ fwrite(&bytes, 4, 1, fd_);
+
+ fclose( fd_ );
+}
+
+bool FileWrite :: setMatFile( const char *fileName )
+{
+ char name[8192];
+ strncpy(name, fileName, 8192);
+ if ( strstr(name, ".mat") == NULL) strcat(name, ".mat");
+ fd_ = fopen(name, "w+b");
+ if ( !fd_ ) {
+ errorString_ << "FileWrite: could not create MAT file: " << name;
+ return false;
+ }
+
+ if ( dataType_ != STK_FLOAT64 ) {
+ dataType_ = STK_FLOAT64;
+ errorString_ << "FileWrite: using 64-bit floating-point data format for file " << name << '.';
+ handleError( StkError::DEBUG_WARNING );
+ }
+
+ struct mathdr hdr;
+ strcpy(hdr.heading,"MATLAB 5.0 MAT-file, Generated using the Synthesis ToolKit in C++ (STK). By Perry R. Cook and Gary P. Scavone.");
+
+ int i;
+ for (i=strlen(hdr.heading);i<124;i++) hdr.heading[i] = ' ';
+
+ // Header Flag Fields
+ hdr.hff[0] = (SINT16) 0x0100; // Version field
+ hdr.hff[1] = (SINT16) 'M'; // Endian indicator field ("MI")
+ hdr.hff[1] <<= 8;
+ hdr.hff[1] += 'I';
+
+ hdr.adf[0] = (SINT32) 14; // Matlab array data type value
+ hdr.adf[1] = (SINT32) 0; // Size of file after this point to end (in bytes)
+ // Don't know size yet.
+
+ // Numeric Array Subelements (4):
+ // 1. Array Flags
+ hdr.adf[2] = (SINT32) 6; // Matlab 32-bit unsigned integer data type value
+ hdr.adf[3] = (SINT32) 8; // 8 bytes of data to follow
+ hdr.adf[4] = (SINT32) 6; // Double-precision array, no array flags set
+ hdr.adf[5] = (SINT32) 0; // 4 bytes undefined
+ // 2. Array Dimensions
+ hdr.adf[6] = (SINT32) 5; // Matlab 32-bit signed integer data type value
+ hdr.adf[7] = (SINT32) 8; // 8 bytes of data to follow (2D array)
+ hdr.adf[8] = (SINT32) channels_; // This is the number of rows
+ hdr.adf[9] = (SINT32) 0; // This is the number of columns
+
+ // 3. Array Name
+ // We'll use fileName for the matlab array name (as well as the file name).
+ // If fileName is 4 characters or less, we have to use a compressed data element
+ // format for the array name data element. Otherwise, the array name must
+ // be formatted in 8-byte increments (up to 31 characters + NULL).
+ SINT32 namelength = (SINT32) strlen(fileName);
+ if (strstr(fileName, ".mat")) namelength -= 4;
+ if (namelength > 31) namelength = 31; // Truncate name to 31 characters.
+ char arrayName[64];
+ strncpy(arrayName, fileName, namelength);
+ arrayName[namelength] = '\0';
+ if (namelength > 4) {
+ hdr.adf[10] = (SINT32) 1; // Matlab 8-bit signed integer data type value
+ }
+ else { // Compressed data element format
+ hdr.adf[10] = namelength;
+ hdr.adf[10] <<= 16;
+ hdr.adf[10] += 1;
+ }
+ SINT32 headsize = 40; // Number of bytes in data element so far.
+
+ // Write the fixed portion of the header
+ if ( fwrite(&hdr, 172, 1, fd_) != 1 ) goto error;
+
+ // Write MATLAB array name
+ SINT32 tmp;
+ if (namelength > 4) {
+ if ( fwrite(&namelength, 4, 1, fd_) != 1) goto error;
+ if ( fwrite(arrayName, namelength, 1, fd_) != 1 ) goto error;
+ tmp = (SINT32) ceil((float)namelength / 8);
+ if ( fseek(fd_, tmp*8-namelength, SEEK_CUR) == -1 ) goto error;
+ headsize += tmp * 8;
+ }
+ else { // Compressed data element format
+ if ( fwrite(arrayName, namelength, 1, fd_) != 1 ) goto error;
+ tmp = 4 - namelength;
+ if ( fseek(fd_, tmp, SEEK_CUR) == -1 ) goto error;
+ }
+
+ // Finish writing known header information
+ tmp = 9; // Matlab IEEE 754 double data type
+ if ( fwrite(&tmp, 4, 1, fd_) != 1 ) goto error;
+ tmp = 0; // Size of real part subelement in bytes (8 per sample)
+ if ( fwrite(&tmp, 4, 1, fd_) != 1 ) goto error;
+ headsize += 8; // Total number of bytes in data element so far
+
+ if ( fseek(fd_, 132, SEEK_SET) == -1 ) goto error;
+ if ( fwrite(&headsize, 4, 1, fd_) != 1 ) goto error; // Write header size ... will update at end
+ if ( fseek(fd_, 0, SEEK_END) == -1 ) goto error;
+
+ byteswap_ = false;
+ errorString_ << "FileWrite: creating MAT-file (" << name << ") containing MATLAB array: " << arrayName;
+ handleError( StkError::STATUS );
+
+ return true;
+
+ error:
+ errorString_ << "FileWrite: could not write MAT-file header for file " << name << '.';
+ return false;
+}
+
+void FileWrite :: closeMatFile( void )
+{
+ fseek(fd_, 164, SEEK_SET); // jump to number of columns
+ fwrite(&frameCounter_, 4, 1, fd_);
+
+ SINT32 headsize, temp;
+ fseek(fd_, 132, SEEK_SET); // jump to header size
+ fread(&headsize, 4, 1, fd_);
+ temp = headsize;
+ headsize += (SINT32) (frameCounter_ * 8 * channels_);
+ fseek(fd_, 132, SEEK_SET);
+ // Write file size (minus some header info)
+ fwrite(&headsize, 4, 1, fd_);
+
+ fseek(fd_, temp+132, SEEK_SET); // jumpt to data size (in bytes)
+ temp = frameCounter_ * 8 * channels_;
+ fwrite(&temp, 4, 1, fd_);
+
+ fclose(fd_);
+}
+
+void FileWrite :: write( StkFrames& buffer )
+{
+ if ( fd_ == 0 ) {
+ errorString_ << "FileWrite::write(): a file has not yet been opened!";
+ handleError( StkError::WARNING );
+ return;
+ }
+
+ if ( buffer.channels() != channels_ ) {
+ errorString_ << "FileWrite::write(): number of channels in the StkFrames argument does not match that specified to open() function!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ return;
+ }
+
+ unsigned long nSamples = buffer.size();
+ if ( dataType_ == STK_SINT16 ) {
+ SINT16 sample;
+ for ( unsigned long k=0; k
+
+FileWvIn :: FileWvIn( unsigned long chunkThreshold, unsigned long chunkSize )
+ : finished_(true), interpolate_(false), time_(0.0),
+ chunkThreshold_(chunkThreshold), chunkSize_(chunkSize)
+{
+}
+
+FileWvIn :: FileWvIn( std::string fileName, bool raw, bool doNormalize,
+ unsigned long chunkThreshold, unsigned long chunkSize )
+ : finished_(true), interpolate_(false), time_(0.0),
+ chunkThreshold_(chunkThreshold), chunkSize_(chunkSize)
+{
+ openFile( fileName, raw, doNormalize );
+}
+
+FileWvIn :: ~FileWvIn()
+{
+ this->closeFile();
+}
+
+void FileWvIn :: closeFile( void )
+{
+ if ( file_.isOpen() ) file_.close();
+ finished_ = true;
+}
+
+void FileWvIn :: openFile( std::string fileName, bool raw, bool doNormalize )
+{
+ // Call close() in case another file is already open.
+ this->closeFile();
+
+ // Attempt to open the file ... an error might be thrown here.
+ file_.open( fileName, raw );
+
+ // Determine whether chunking or not.
+ if ( file_.fileSize() > chunkThreshold_ ) {
+ chunking_ = true;
+ chunkPointer_ = 0;
+ data_.resize( chunkSize_, file_.channels() );
+ if ( doNormalize ) normalizing_ = true;
+ else normalizing_ = false;
+ }
+ else {
+ chunking_ = false;
+ data_.resize( (size_t) file_.fileSize(), file_.channels() );
+ }
+
+ // Load all or part of the data.
+ file_.read( data_, 0, doNormalize );
+
+ // Resize our lastOutputs container.
+ lastOutputs_.resize( 1, file_.channels() );
+
+ // Set default rate based on file sampling rate.
+ this->setRate( data_.dataRate() / Stk::sampleRate() );
+
+ if ( doNormalize & !chunking_ ) this->normalize();
+
+ this->reset();
+}
+
+void FileWvIn :: reset(void)
+{
+ time_ = (StkFloat) 0.0;
+ for ( unsigned int i=0; inormalize( 1.0 );
+}
+
+// Normalize all channels equally by the greatest magnitude in all of the data.
+void FileWvIn :: normalize( StkFloat peak )
+{
+ // When chunking, the "normalization" scaling is performed by FileRead.
+ if ( chunking_ ) return;
+
+ size_t i;
+ StkFloat max = 0.0;
+
+ for ( i=0; i max )
+ max = (StkFloat) fabs((double) data_[i]);
+ }
+
+ if (max > 0.0) {
+ max = 1.0 / max;
+ max *= peak;
+ for ( i=0; i file_.fileSize() - 1.0 ) {
+ time_ = file_.fileSize() - 1.0;
+ for ( unsigned int i=0; i (StkFloat) ( file_.fileSize() - 1.0 ) ) {
+ for ( unsigned int i=0; i (StkFloat) ( chunkPointer_ + chunkSize_ - 1 ) ) ) {
+
+ while ( time_ < (StkFloat) chunkPointer_ ) { // negative rate
+ chunkPointer_ -= chunkSize_ - 1; // overlap chunks by one frame
+ if ( chunkPointer_ < 0 ) chunkPointer_ = 0;
+ }
+ while ( time_ > (StkFloat) ( chunkPointer_ + chunkSize_ - 1 ) ) { // positive rate
+ chunkPointer_ += chunkSize_ - 1; // overlap chunks by one frame
+ if ( chunkPointer_ + chunkSize_ > file_.fileSize() ) // at end of file
+ chunkPointer_ = file_.fileSize() - chunkSize_;
+ }
+
+ // Load more data.
+ file_.read( data_, chunkPointer_, normalizing_ );
+ }
+
+ // Adjust index for the current buffer.
+ tyme -= chunkPointer_;
+ }
+
+ if ( interpolate_ ) {
+ for ( unsigned int i=0; iopenFile( fileName, nChannels, type, format );
+}
+
+FileWvOut :: ~FileWvOut()
+{
+ this->closeFile();
+}
+
+void FileWvOut :: closeFile( void )
+{
+ if ( file_.isOpen() ) {
+
+ // Output any remaining samples in the buffer before closing.
+ if ( bufferIndex_ > 0 ) {
+ data_.resize( bufferIndex_, data_.channels() );
+ file_.write( data_ );
+ }
+
+ file_.close();
+ frameCounter_ = 0;
+ }
+}
+
+void FileWvOut :: openFile( std::string fileName,
+ unsigned int nChannels,
+ FileWrite::FILE_TYPE type,
+ Stk::StkFormat format )
+{
+ closeFile();
+
+ if ( nChannels < 1 ) {
+ errorString_ << "FileWvOut::openFile: the channels argument must be greater than zero!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+
+ // An StkError can be thrown by the FileWrite class here.
+ file_.open( fileName, nChannels, type, format );
+
+ // Allocate new memory if necessary.
+ data_.resize( bufferFrames_, nChannels );
+
+ bufferIndex_ = 0;
+ iData_ = 0;
+}
+
+void FileWvOut :: incrementFrame( void )
+{
+ frameCounter_++;
+ bufferIndex_++;
+
+ if ( bufferIndex_ == bufferFrames_ ) {
+ file_.write( data_ );
+ bufferIndex_ = 0;
+ iData_ = 0;
+ }
+}
+
+void FileWvOut :: computeSample( const StkFloat sample )
+{
+ if ( !file_.isOpen() ) {
+ errorString_ << "FileWvOut::computeSample(): no file open!";
+ handleError( StkError::WARNING );
+ return;
+ }
+
+ unsigned int nChannels = data_.channels();
+ StkFloat input = sample;
+ clipTest( input );
+ for ( unsigned int j=0; jincrementFrame();
+}
+
+void FileWvOut :: computeFrames( const StkFrames& frames )
+{
+ if ( !file_.isOpen() ) {
+ errorString_ << "FileWvOut::computeFrames(): no file open!";
+ handleError( StkError::WARNING );
+ return;
+ }
+
+ if ( data_.channels() != frames.channels() ) {
+ errorString_ << "FileWvOut::computeFrames(): incompatible channel value in StkFrames argument!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+
+ unsigned int j, nChannels = data_.channels();
+ if ( nChannels == 1 || frames.interleaved() ) {
+
+ unsigned int iFrames = 0;
+ for ( unsigned int i=0; iincrementFrame();
+ }
+ }
+ else { // non-interleaved frames
+
+ unsigned long hop = frames.frames();
+ unsigned int index;
+ for ( unsigned int i=0; iincrementFrame();
+ }
+ }
+}
+
diff --git a/src/Filter.cpp b/src/Filter.cpp
index 097fc68..70a3388 100644
--- a/src/Filter.cpp
+++ b/src/Filter.cpp
@@ -2,7 +2,7 @@
/*! \class Filter
\brief STK filter class.
- This class implements a generic structure which
+ This class implements a generic structure that
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
@@ -23,7 +23,7 @@
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 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -76,7 +76,7 @@ void Filter :: clear(void)
outputs_[i] = 0.0;
}
-void Filter :: setCoefficients( std::vector &bCoefficients, std::vector &aCoefficients )
+void Filter :: setCoefficients( std::vector &bCoefficients, std::vector &aCoefficients, bool clearState )
{
// Check the arguments.
if ( bCoefficients.size() == 0 || aCoefficients.size() == 0 ) {
@@ -107,7 +107,7 @@ void Filter :: setCoefficients( std::vector &bCoefficients, std::vecto
for ( unsigned int i=0; iclear();
+ if ( clearState ) this->clear();
// Scale coefficients by a[0] if necessary
if ( a_[0] != 1.0 ) {
@@ -117,7 +117,7 @@ void Filter :: setCoefficients( std::vector &bCoefficients, std::vecto
}
}
-void Filter :: setNumerator( std::vector &bCoefficients )
+void Filter :: setNumerator( std::vector &bCoefficients, bool clearState )
{
// Check the argument.
if ( bCoefficients.size() == 0 ) {
@@ -134,10 +134,10 @@ void Filter :: setNumerator( std::vector &bCoefficients )
for ( unsigned int i=0; iclear();
+ if ( clearState ) this->clear();
}
-void Filter :: setDenominator( std::vector &aCoefficients )
+void Filter :: setDenominator( std::vector &aCoefficients, bool clearState )
{
// Check the argument.
if ( aCoefficients.size() == 0 ) {
@@ -159,7 +159,7 @@ void Filter :: setDenominator( std::vector &aCoefficients )
for ( unsigned int i=0; iclear();
+ if ( clearState ) this->clear();
// Scale coefficients by a[0] if necessary
if ( a_[0] != 1.0 ) {
@@ -184,12 +184,12 @@ StkFloat Filter :: lastOut(void) const
return outputs_[0];
}
-StkFloat Filter :: tick(StkFloat sample)
+StkFloat Filter :: tick( StkFloat input )
{
unsigned int i;
outputs_[0] = 0.0;
- inputs_[0] = gain_ * sample;
+ inputs_[0] = gain_ * input;
for (i=b_.size()-1; i>0; i--) {
outputs_[0] += b_[i] * inputs_[i];
inputs_[i] = inputs_[i-1];
@@ -204,18 +204,11 @@ StkFloat Filter :: tick(StkFloat sample)
return outputs_[0];
}
-StkFloat *Filter :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- for (unsigned int i=0; i channels in StkFrames argument!";
+ if ( channel >= frames.channels() ) {
+ errorString_ << "Filter::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
@@ -225,16 +218,16 @@ StkFrames& Filter :: tick( StkFrames& frames, unsigned int channel )
}
else if ( frames.interleaved() ) {
unsigned int hop = frames.channels();
- unsigned int index = channel - 1;
+ unsigned int index = channel;
for ( unsigned int i=0; isetFrequency( 5.925 );
+ vibrato_.setFrequency( 5.925 );
this->clear();
filter_.setPole( 0.7 - ((StkFloat) 0.1 * 22050.0 / Stk::sampleRate() ) );
filter_.setGain( -1.0 );
+
+ dcBlock_.setBlockZero();
+
adsr_.setAllTimes( 0.005, 0.01, 0.8, 0.010);
endReflection_ = 0.5;
jetReflection_ = 0.5;
@@ -56,7 +57,6 @@ Flute :: Flute(StkFloat lowestFrequency)
Flute :: ~Flute()
{
- delete vibrato_;
}
void Flute :: clear()
@@ -141,18 +141,18 @@ void Flute :: setJetDelay(StkFloat aRatio)
jetDelay_.setDelay(temp * aRatio); // Scaled by ratio.
}
-StkFloat Flute :: tick()
+StkFloat Flute :: computeSample()
{
StkFloat pressureDiff;
StkFloat breathPressure;
// Calculate the breath pressure (envelope + noise + vibrato)
breathPressure = maxPressure_ * adsr_.tick();
- breathPressure += breathPressure * noiseGain_ * noise_.tick();
- breathPressure += breathPressure * vibratoGain_ * vibrato_->tick();
+ breathPressure += breathPressure * ( noiseGain_ * noise_.tick() + vibratoGain_ * vibrato_.tick() );
+ //breathPressure += breathPressure * vibratoGain_ * vibrato_.tick();
StkFloat temp = filter_.tick( boreDelay_.lastOut() );
- temp = dcBlock_.tick(temp); // Block DC on reflection.
+ temp = dcBlock_.tick( temp ); // Block DC on reflection.
pressureDiff = breathPressure - (jetReflection_ * temp);
pressureDiff = jetDelay_.tick( pressureDiff );
@@ -163,16 +163,6 @@ StkFloat Flute :: tick()
return lastOutput_;
}
-StkFloat *Flute :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Instrmnt::tick( vector, vectorSize );
-}
-
-StkFrames& Flute :: tick( StkFrames& frames, unsigned int channel )
-{
- return Instrmnt::tick( frames, channel );
-}
-
void Flute :: controlChange(int number, StkFloat value)
{
StkFloat norm = value * ONE_OVER_128;
@@ -192,7 +182,7 @@ void Flute :: controlChange(int number, StkFloat value)
else if (number == __SK_NoiseLevel_) // 4
noiseGain_ = ( norm * 0.4);
else if (number == __SK_ModFrequency_) // 11
- vibrato_->setFrequency( norm * 12.0);
+ vibrato_.setFrequency( norm * 12.0);
else if (number == __SK_ModWheel_) // 1
vibratoGain_ = ( norm * 0.4 );
else if (number == __SK_AfterTouch_Cont_) // 128
diff --git a/src/FormSwep.cpp b/src/FormSwep.cpp
index 6ffebe0..0ed89f3 100644
--- a/src/FormSwep.cpp
+++ b/src/FormSwep.cpp
@@ -8,7 +8,7 @@
It provides methods for controlling the sweep
rate and target frequency.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -87,12 +87,12 @@ void FormSwep :: setSweepTime(StkFloat time)
if ( sweepRate_ < 0.0 ) sweepRate_ = 0.0;
}
-StkFloat FormSwep :: tick(StkFloat sample)
+StkFloat FormSwep :: computeSample( StkFloat input )
{
if (dirty_) {
sweepState_ += sweepRate_;
if ( sweepState_ >= 1.0 ) {
- sweepState_ = (StkFloat) 1.0;
+ sweepState_ = 1.0;
dirty_ = false;
radius_ = targetRadius_;
frequency_ = targetFrequency_;
@@ -106,15 +106,6 @@ StkFloat FormSwep :: tick(StkFloat sample)
BiQuad::setResonance( frequency_, radius_, true );
}
- return BiQuad::tick( sample );
+ return BiQuad::computeSample( input );
}
-StkFloat *FormSwep :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Filter::tick( vector, vectorSize );
-}
-
-StkFrames& FormSwep :: tick( StkFrames& frames, unsigned int channel )
-{
- return Filter::tick( frames, channel );
-}
diff --git a/src/Function.cpp b/src/Function.cpp
index 7447bf8..ef6ce95 100644
--- a/src/Function.cpp
+++ b/src/Function.cpp
@@ -6,7 +6,7 @@
implement tables or other types of input to output function
mappings.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -21,37 +21,34 @@ Function :: ~Function()
{
}
-StkFloat *Function :: tick(StkFloat *vector, unsigned int vectorSize)
+StkFloat Function :: tick( StkFloat input )
{
- for (unsigned int i=0; i channels in StkFrames argument!";
+ if ( channel >= frames.channels() ) {
+ errorString_ << "Function::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
if ( frames.channels() == 1 ) {
for ( unsigned int i=0; i channels in StkFrames argument!";
+ if ( channel >= frames.channels() ) {
+ errorString_ << "Generator::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
if ( frames.channels() == 1 ) {
for ( unsigned int i=0; isetGrainParameters(); // use default values
+ this->setRandomFactor();
+ gStretch_ = 0;
+ stretchCounter_ = 0;
+ gain_ = 1.0;
+}
+
+Granulate :: Granulate( unsigned int nVoices, std::string fileName, bool typeRaw )
+{
+ this->setGrainParameters(); // use default values
+ this->setRandomFactor();
+ gStretch_ = 0;
+ stretchCounter_ = 0;
+ this->openFile( fileName, typeRaw );
+ this->setVoices( nVoices );
+}
+
+Granulate :: ~Granulate()
+{
+}
+
+void Granulate :: setStretch( unsigned int stretchFactor )
+{
+ if ( stretchFactor <= 1 )
+ gStretch_ = 0;
+ else if ( gStretch_ >= 1000 )
+ gStretch_ = 1000;
+ else
+ gStretch_ = stretchFactor - 1;
+}
+
+void Granulate :: setGrainParameters( unsigned int duration, unsigned int rampPercent,
+ int offset, unsigned int delay )
+{
+ gDuration_ = duration;
+ if ( gDuration_ == 0 ) {
+ gDuration_ = 1;
+ errorString_ << "Granulate::setGrainParameters: duration argument cannot be zero ... setting to 1 millisecond.";
+ handleError( StkError::WARNING );
+ }
+
+ gRampPercent_ = rampPercent;
+ if ( gRampPercent_ > 100 ) {
+ gRampPercent_ = 100;
+ errorString_ << "Granulate::setGrainParameters: rampPercent argument cannot be greater than 100 ... setting to 100.";
+ handleError( StkError::WARNING );
+ }
+
+ gOffset_ = offset;
+ gDelay_ = delay;
+}
+
+void Granulate :: setRandomFactor( StkFloat randomness )
+{
+ if ( randomness < 0.0 ) gRandomFactor_ = 0.0;
+ else if ( randomness > 1.0 ) gRandomFactor_ = 0.97;
+
+ gRandomFactor_ = 0.97 * randomness;
+};
+
+void Granulate :: openFile( std::string fileName, bool typeRaw )
+{
+ // Attempt to load the soundfile data.
+ FileRead file( fileName, typeRaw );
+ if ( file.channels() != 1 ) {
+ errorString_ << "Granulate::openFile: this class currently only supports monophonic soundfiles.";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+
+ data_.resize( file.fileSize(), file.channels() );
+ file.read( data_ );
+
+ this->reset();
+
+#if defined(_STK_DEBUG_)
+ errorString_ << "Granulate::openFile: file = " << fileName << ", file frames = " << file.fileSize() << '.';
+ handleError( StkError::DEBUG_WARNING );
+#endif
+
+}
+
+void Granulate :: reset()
+{
+ gPointer_ = 0;
+
+ // Reset grain parameters.
+ unsigned int count, nVoices = grains_.size();
+ for ( unsigned int i=0; ifinished ) {
+ ((InetWvIn *) info->object)->receive();
+ }
+
+ return 0;
+}
+
+InetWvIn :: InetWvIn( unsigned long bufferFrames, unsigned int nBuffers )
+ :soket_(0), buffer_(0), bufferFrames_(bufferFrames), bufferBytes_(0), nBuffers_(nBuffers), connected_(false)
+{
+ threadInfo_.finished = false;
+ threadInfo_.object = (void *) this;
+
+ // Start the input thread.
+ if ( !thread_.start( &inputThread, &threadInfo_ ) ) {
+ errorString_ << "InetWvIn(): unable to start input thread in constructor!";
+ handleError( StkError::PROCESS_THREAD );
+ }
+}
+
+InetWvIn :: ~InetWvIn()
+{
+ // Close down the thread.
+ connected_ = false;
+ threadInfo_.finished = true;
+
+ if ( soket_ ) delete soket_;
+ if ( buffer_ ) delete [] buffer_;
+}
+
+void InetWvIn :: listen( int port, unsigned int nChannels,
+ Stk::StkFormat format, Socket::ProtocolType protocol )
+{
+ mutex_.lock();
+
+ if ( connected_ ) delete soket_;
+
+ if ( nChannels < 1 ) {
+ errorString_ << "InetWvIn()::listen(): the channel argument (" << nChannels << ") must be greater than zero.";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+
+ if ( format == STK_SINT16 ) dataBytes_ = 2;
+ else if ( format == STK_SINT32 || format == STK_FLOAT32 ) dataBytes_ = 4;
+ else if ( format == STK_FLOAT64 ) dataBytes_ = 8;
+ else if ( format == STK_SINT8 ) dataBytes_ = 1;
+ else {
+ errorString_ << "InetWvIn(): unknown data type specified (" << format << ").";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+ dataType_ = format;
+
+ unsigned long bufferBytes = bufferFrames_ * nBuffers_ * nChannels * dataBytes_;
+ if ( bufferBytes > bufferBytes_ ) {
+ if ( buffer_) delete [] buffer_;
+ buffer_ = (char *) new char[ bufferBytes ];
+ bufferBytes_ = bufferBytes;
+ }
+
+ data_.resize( bufferFrames_, nChannels );
+ lastOutputs_.resize( 1, nChannels, 0.0 );
+
+ bufferCounter_ = 0;
+ writePoint_ = 0;
+ readPoint_ = 0;
+ bytesFilled_ = 0;
+
+ if ( protocol == Socket::PROTO_TCP ) {
+ TcpServer *socket = new TcpServer( port );
+ errorString_ << "InetWvIn:listen(): waiting for TCP connection on port " << socket->port() << " ... ";
+ handleError( StkError::STATUS );
+ fd_ = socket->accept();
+ if ( fd_ < 0) {
+ errorString_ << "InetWvIn::listen(): Error accepting TCP connection request!";
+ handleError( StkError::PROCESS_SOCKET );
+ }
+ errorString_ << "InetWvIn::listen(): TCP socket connection made!";
+ handleError( StkError::STATUS );
+ soket_ = (Socket *) socket;
+ }
+ else {
+ soket_ = new UdpSocket( port );
+ fd_ = soket_->id();
+ }
+
+ connected_ = true;
+
+ mutex_.unlock();
+}
+
+void InetWvIn :: receive( void )
+{
+ if ( !connected_ ) {
+ Stk::sleep(100);
+ return;
+ }
+
+ fd_set mask;
+ FD_ZERO( &mask );
+ FD_SET( fd_, &mask );
+
+ // The select function will block until data is available for reading.
+ select( fd_+1, &mask, (fd_set *)0, (fd_set *)0, NULL );
+
+ if ( FD_ISSET( fd_, &mask ) ) {
+ mutex_.lock();
+ unsigned long unfilled = bufferBytes_ - bytesFilled_;
+ if ( unfilled > 0 ) {
+ // There's room in our buffer for more data.
+ unsigned long endPoint = writePoint_ + unfilled;
+ if ( endPoint > bufferBytes_ ) unfilled -= endPoint - bufferBytes_;
+ int i = soket_->readBuffer( fd_, (void *)&buffer_[writePoint_], unfilled, 0 );
+ //int i = Socket::readBuffer( fd_, (void *)&buffer_[writePoint_], unfilled, 0 );
+ if ( i <= 0 ) {
+ errorString_ << "InetWvIn::receive(): the remote InetWvIn socket has closed.";
+ handleError( StkError::STATUS );
+ connected_ = false;
+ mutex_.unlock();
+ return;
+ }
+ bytesFilled_ += i;
+ writePoint_ += i;
+ if ( writePoint_ == bufferBytes_ )
+ writePoint_ = 0;
+ mutex_.unlock();
+ }
+ else {
+ // Sleep 10 milliseconds AFTER unlocking mutex.
+ mutex_.unlock();
+ Stk::sleep( 10 );
+ }
+ }
+}
+
+int InetWvIn :: readData( void )
+{
+ // We have two potential courses of action should this method
+ // be called and the input buffer isn't sufficiently filled.
+ // One solution is to fill the data buffer with zeros and return.
+ // The other solution is to wait until the necessary data exists.
+ // I chose the latter, as it works for both streamed files
+ // (non-realtime data transport) and realtime playback (given
+ // adequate network bandwidth and speed).
+
+ // Wait until data is ready.
+ unsigned long bytes = data_.size() * dataBytes_;
+ while ( connected_ && bytesFilled_ < bytes )
+ Stk::sleep( 10 );
+
+ if ( !connected_ && bytesFilled_ == 0 ) return 0;
+ bytes = ( bytesFilled_ < bytes ) ? bytesFilled_ : bytes;
+
+ // Copy samples from buffer to data.
+ StkFloat gain;
+ long samples = bytes / dataBytes_;
+ mutex_.lock();
+ if ( dataType_ == STK_SINT16 ) {
+ gain = 1.0 / 32767.0;
+ SINT16 *buf = (SINT16 *) (buffer_+readPoint_);
+ for (int i=0; i 0 || bufferCounter_ > 0 )
+ return true;
+ else
+ return connected_;
+}
+
+void InetWvIn :: computeFrame( void )
+{
+ // If no connection and we've output all samples in the queue, return.
+ if ( !connected_ && bytesFilled_ == 0 && bufferCounter_ == 0 ) return;
+
+ if ( bufferCounter_ == 0 )
+ bufferCounter_ = readData();
+
+ unsigned int nChannels = lastOutputs_.channels();
+ long temp = (bufferFrames_ - bufferCounter_) * nChannels;
+ for ( unsigned int i=0; iisValid( soket_->id() ) )
+ disconnect();
+
+ if ( nChannels == 0 ) {
+ errorString_ << "InetWvOut::connect: the channel argument (" << nChannels << ") must be greater than zero!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+
+ if ( format == STK_SINT8 ) dataBytes_ = 1;
+ else if ( format == STK_SINT16 ) dataBytes_ = 2;
+ else if ( format == STK_SINT32 || format == STK_FLOAT32 ) dataBytes_ = 4;
+ else if ( format == STK_FLOAT64 ) dataBytes_ = 8;
+ else {
+ errorString_ << "InetWvOut::connect: unknown data type specified (" << format << ").";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+ dataType_ = format;
+
+ if ( protocol == Socket::PROTO_TCP ) {
+ soket_ = new TcpClient( port, hostname );
+ }
+ else {
+ // For UDP sockets, the sending and receiving sockets cannot have
+ // the same port number. Since the port argument corresponds to
+ // the destination port, we will associate this socket instance
+ // with a different port number (arbitrarily determined as port -
+ // 1).
+ UdpSocket *socket = new UdpSocket( port - 1 );
+ socket->setDestination( port, hostname );
+ soket_ = (Socket *) socket;
+ }
+
+ // Allocate new memory if necessary.
+ data_.resize( bufferFrames_, nChannels );
+ unsigned long bufferBytes = dataBytes_ * bufferFrames_ * nChannels;
+ if ( bufferBytes > bufferBytes_ ) {
+ if ( buffer_) delete [] buffer_;
+ buffer_ = (char *) new char[ bufferBytes ];
+ bufferBytes_ = bufferBytes;
+ }
+ frameCounter_ = 0;
+ bufferIndex_ = 0;
+ iData_ = 0;
+}
+
+void InetWvOut :: disconnect(void)
+{
+ if ( soket_ ) {
+ writeData( bufferIndex_ );
+ soket_->close( soket_->id() );
+ delete soket_;
+ soket_ = 0;
+ }
+}
+
+void InetWvOut :: writeData( unsigned long frames )
+{
+ unsigned long samples = frames * data_.channels();
+ if ( dataType_ == STK_SINT8 ) {
+ signed char *ptr = (signed char *) buffer_;
+ for ( unsigned long k=0; kclipTest( data_[k] );
+ *ptr++ = (signed char) (data_[k] * 127.0);
+ }
+ }
+ else if ( dataType_ == STK_SINT16 ) {
+ SINT16 *ptr = (SINT16 *) buffer_;
+ for ( unsigned long k=0; kclipTest( data_[k] );
+ *ptr = (SINT16) (data_[k] * 32767.0);
+#ifdef __LITTLE_ENDIAN__
+ swap16 ((unsigned char *)ptr);
+#endif
+ ptr++;
+ }
+ }
+ else if ( dataType_ == STK_SINT32 ) {
+ SINT32 *ptr = (SINT32 *) buffer_;
+ for ( unsigned long k=0; kclipTest( data_[k] );
+ *ptr = (SINT32) (data_[k] * 2147483647.0);
+#ifdef __LITTLE_ENDIAN__
+ swap32 ((unsigned char *)ptr);
+#endif
+ ptr++;
+ }
+ }
+ else if ( dataType_ == STK_FLOAT32 ) {
+ FLOAT32 *ptr = (FLOAT32 *) buffer_;
+ for ( unsigned long k=0; kclipTest( data_[k] );
+ *ptr = (FLOAT32) data_[k];
+#ifdef __LITTLE_ENDIAN__
+ swap32 ((unsigned char *)ptr);
+#endif
+ ptr++;
+ }
+ }
+ else if ( dataType_ == STK_FLOAT64 ) {
+ FLOAT64 *ptr = (FLOAT64 *) buffer_;
+ for ( unsigned long k=0; kclipTest( data_[k] );
+ *ptr = (FLOAT64) data_[k];
+#ifdef __LITTLE_ENDIAN__
+ swap64 ((unsigned char *)ptr);
+#endif
+ ptr++;
+ }
+ }
+
+ long bytes = dataBytes_ * samples;
+ if ( soket_->writeBuffer( (const void *)buffer_, bytes, 0 ) < 0 ) {
+ errorString_ << "InetWvOut: connection to socket server failed!";
+ handleError( StkError::PROCESS_SOCKET );
+ }
+}
+
+void InetWvOut :: incrementFrame( void )
+{
+ frameCounter_++;
+ bufferIndex_++;
+
+ if ( bufferIndex_ == bufferFrames_ ) {
+ writeData( bufferFrames_ );
+ bufferIndex_ = 0;
+ iData_ = 0;
+ }
+}
+
+void InetWvOut :: computeSample( const StkFloat sample )
+{
+ if ( !soket_ || !soket_->isValid( soket_->id() ) ) return;
+
+ unsigned int nChannels = data_.channels();
+ StkFloat input = sample;
+ clipTest( input );
+ for ( unsigned int j=0; jincrementFrame();
+}
+
+void InetWvOut :: computeFrames( const StkFrames& frames )
+{
+ if ( !soket_ || !soket_->isValid( soket_->id() ) ) return;
+
+ if ( data_.channels() != frames.channels() ) {
+ errorString_ << "InetWvOut::computeFrames(): incompatible channel value in StkFrames argument!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+
+ unsigned int j, nChannels = data_.channels();
+ if ( nChannels == 1 || frames.interleaved() ) {
+
+ unsigned int iFrames = 0;
+ for ( unsigned int i=0; iincrementFrame();
+ }
+ }
+ else { // non-interleaved frames
+
+ unsigned long hop = frames.frames();
+ unsigned int index;
+ for ( unsigned int i=0; iincrementFrame();
+ }
+ }
+}
diff --git a/src/Instrmnt.cpp b/src/Instrmnt.cpp
index b4e377c..667ba81 100644
--- a/src/Instrmnt.cpp
+++ b/src/Instrmnt.cpp
@@ -5,7 +5,7 @@
This class provides a common interface for
all STK instruments.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -41,18 +41,15 @@ StkFloat Instrmnt :: lastOutRight(void) const
return 0.5 * lastOutput_;
}
-StkFloat *Instrmnt :: tick(StkFloat *vector, unsigned int vectorSize)
+StkFloat Instrmnt :: tick( void )
{
- for (unsigned int i=0; i channels in StkFrames argument!";
+ if ( channel >= frames.channels() ) {
+ errorString_ << "Instrmnt::tick(): channel and StkFrames arguments are incompatible!";
handleError( StkError::FUNCTION_ARGUMENT );
}
@@ -62,16 +59,16 @@ StkFrames& Instrmnt :: tick( StkFrames& frames, unsigned int channel )
}
else if ( frames.interleaved() ) {
unsigned int hop = frames.channels();
- unsigned int index = channel - 1;
+ unsigned int index = channel;
for ( unsigned int i=0; isetRate( rate );
}
-StkFloat Mandolin :: tick()
+StkFloat Mandolin :: computeSample()
{
StkFloat temp = 0.0;
if ( !waveDone_ ) {
@@ -150,16 +150,6 @@ StkFloat Mandolin :: tick()
return lastOutput_;
}
-StkFloat *Mandolin :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Instrmnt::tick( vector, vectorSize );
-}
-
-StkFrames& Mandolin :: tick( StkFrames& frames, unsigned int channel )
-{
- return Instrmnt::tick( frames, channel );
-}
-
void Mandolin :: controlChange(int number, StkFloat value)
{
StkFloat norm = value * ONE_OVER_128;
diff --git a/src/Mesh2D.cpp b/src/Mesh2D.cpp
index 4de75ee..43c04af 100644
--- a/src/Mesh2D.cpp
+++ b/src/Mesh2D.cpp
@@ -241,7 +241,7 @@ void Mesh2D :: noteOff(StkFloat amplitude)
#endif
}
-StkFloat Mesh2D :: tick(StkFloat input)
+StkFloat Mesh2D :: inputTick( StkFloat input )
{
if ( counter_ & 1 ) {
vxp1_[xInput_][yInput_] += input;
@@ -258,7 +258,7 @@ StkFloat Mesh2D :: tick(StkFloat input)
return lastOutput_;
}
-StkFloat Mesh2D :: tick()
+StkFloat Mesh2D :: computeSample()
{
lastOutput_ = ((counter_ & 1) ? this->tick1() : this->tick0());
counter_++;
@@ -362,16 +362,6 @@ StkFloat Mesh2D :: tick1()
return outsamp;
}
-StkFloat *Mesh2D :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Instrmnt::tick( vector, vectorSize );
-}
-
-StkFrames& Mesh2D :: tick( StkFrames& frames, unsigned int channel )
-{
- return Instrmnt::tick( frames, channel );
-}
-
void Mesh2D :: controlChange(int number, StkFloat value)
{
StkFloat norm = value * ONE_OVER_128;
diff --git a/src/Messager.cpp b/src/Messager.cpp
index 6563c51..f946444 100644
--- a/src/Messager.cpp
+++ b/src/Messager.cpp
@@ -28,7 +28,7 @@
This class is primarily for use in STK example programs but it is
generic enough to work in many other contexts.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -264,7 +264,7 @@ bool Messager :: startSocketInput( int port )
// Create the socket server.
try {
- data_.socket = new Socket( port );
+ data_.socket = new TcpServer( port );
}
catch ( StkError& ) {
return false;
@@ -290,14 +290,9 @@ bool Messager :: startSocketInput( int port )
return true;
}
-#if (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOS__))
- #include
- #include
+#if (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__))
#include
#include
- #include
- #include
- #include
#endif
THREAD_RETURN THREAD_TYPE socketHandler(void *ptr)
diff --git a/src/MidiFileIn.cpp b/src/MidiFileIn.cpp
index b1d5304..1387e2a 100644
--- a/src/MidiFileIn.cpp
+++ b/src/MidiFileIn.cpp
@@ -21,7 +21,7 @@
MidiFileIn :: MidiFileIn( std::string fileName )
{
// Attempt to open the file.
- file_.open( fileName.c_str(), std::ios::in );
+ file_.open( fileName.c_str(), std::ios::in | std::ios::binary );
if ( !file_ ) {
errorString_ << "MidiFileIn: error opening or finding file (" << fileName << ").";
handleError( StkError::FILE_NOT_FOUND );
@@ -90,7 +90,8 @@ MidiFileIn :: MidiFileIn( std::string fileName )
// code, we can initialize the "tick time" using a default tempo of
// 120 beats per minute. We will then check for tempo meta-events
// afterward.
- for ( unsigned int i=0; i *event, uns
file_.seekg( position, std::ios_base::beg );
break;
- case 0xF0 || 0xF7: // The start or continuation of a Sysex event
+ case 0xF0:
+ case 0xF7: // The start or continuation of a Sysex event
trackStatus_[track] = 0;
event->push_back( c );
position = file_.tellg();
@@ -278,7 +280,8 @@ unsigned long MidiFileIn :: getNextEvent( std::vector *event, uns
}
// Read the rest of the event into the event vector.
- for ( unsigned long i=0; ipush_back( c );
}
diff --git a/src/Modal.cpp b/src/Modal.cpp
index 2f4b4fc..341b15b 100644
--- a/src/Modal.cpp
+++ b/src/Modal.cpp
@@ -7,7 +7,7 @@
(non-sweeping BiQuad filters), where N is set
during instantiation.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -32,11 +32,8 @@ Modal :: Modal(unsigned int modes)
filters_[i]->setEqualGainZeroes();
}
- // Concatenate the STK rawwave path to the rawwave file
- vibrato_ = new WaveLoop( Stk::rawwavePath() + "sinewave.raw", true );
-
// Set some default values.
- vibrato_->setFrequency( 6.0 );
+ vibrato_.setFrequency( 6.0 );
vibratoGain_ = 0.0;
directGain_ = 0.0;
masterGain_ = 1.0;
@@ -50,8 +47,6 @@ Modal :: Modal(unsigned int modes)
Modal :: ~Modal()
{
- delete vibrato_;
-
for (unsigned int i=0; itick() * envelope_.tick() );
@@ -203,20 +198,10 @@ StkFloat Modal :: tick()
if (vibratoGain_ != 0.0) {
// Calculate AM and apply to master out
- temp = 1.0 + (vibrato_->tick() * vibratoGain_);
+ temp = 1.0 + (vibrato_.tick() * vibratoGain_);
temp2 = temp * temp2;
}
lastOutput_ = temp2;
return lastOutput_;
}
-
-StkFloat *Modal :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Instrmnt::tick( vector, vectorSize );
-}
-
-StkFrames& Modal :: tick( StkFrames& frames, unsigned int channel )
-{
- return Instrmnt::tick( frames, channel );
-}
diff --git a/src/ModalBar.cpp b/src/ModalBar.cpp
index e5825ee..304618a 100644
--- a/src/ModalBar.cpp
+++ b/src/ModalBar.cpp
@@ -9,9 +9,9 @@
Control Change Numbers:
- Stick Hardness = 2
- Stick Position = 4
- - Vibrato Gain = 1
+ - Vibrato Gain = 8
- Vibrato Frequency = 11
- - Direct Stick Mix = 8
+ - Direct Stick Mix = 1
- Volume = 128
- Modal Presets = 16
- Marimba = 0
@@ -24,19 +24,19 @@
- Two Fixed = 7
- Clump = 8
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
#include "ModalBar.h"
#include "SKINI.msg"
-#include
+#include
ModalBar :: ModalBar()
: Modal()
{
// Concatenate the STK rawwave path to the rawwave file
- wave_ = new WvIn( (Stk::rawwavePath() + "marmstk1.raw").c_str(), true );
+ wave_ = new FileWvIn( (Stk::rawwavePath() + "marmstk1.raw").c_str(), true );
wave_->setRate( 0.5 * 22050.0 / Stk::sampleRate() );
// Set the resonances for preset 0 (marimba).
@@ -177,11 +177,11 @@ void ModalBar :: controlChange(int number, StkFloat value)
else if (number == __SK_ProphesyRibbon_) // 16
this->setPreset((int) value);
else if (number == __SK_Balance_) // 8
- directGain_ = norm;
- else if (number == __SK_ModWheel_) // 1
vibratoGain_ = norm * 0.3;
+ else if (number == __SK_ModWheel_) // 1
+ directGain_ = norm;
else if (number == __SK_ModFrequency_) // 11
- vibrato_->setFrequency( norm * 12.0 );
+ vibrato_.setFrequency( norm * 12.0 );
else if (number == __SK_AfterTouch_Cont_) // 128
envelope_.setTarget( norm );
else {
diff --git a/src/Modulate.cpp b/src/Modulate.cpp
index b21e115..fc342dd 100644
--- a/src/Modulate.cpp
+++ b/src/Modulate.cpp
@@ -6,7 +6,7 @@
modulations to give a nice, natural human
modulation function.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -14,9 +14,7 @@
Modulate :: Modulate()
{
- // Concatenate the STK rawwave path to the rawwave file
- vibrato_ = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), true );
- vibrato_->setFrequency( 6.0 );
+ vibrato_.setFrequency( 6.0 );
vibratoGain_ = 0.04;
noise_.setRate( 330 );
@@ -28,7 +26,6 @@ Modulate :: Modulate()
Modulate :: ~Modulate()
{
- delete vibrato_;
}
void Modulate :: reset()
@@ -38,7 +35,7 @@ void Modulate :: reset()
void Modulate :: setVibratoRate(StkFloat rate)
{
- vibrato_->setFrequency( rate );
+ vibrato_.setFrequency( rate );
}
void Modulate :: setVibratoGain(StkFloat gain)
@@ -52,21 +49,11 @@ void Modulate :: setRandomGain(StkFloat gain)
filter_.setGain( randomGain_ );
}
-StkFloat Modulate :: tick()
+StkFloat Modulate :: computeSample()
{
// Compute periodic and random modulations.
- lastOutput_ = vibratoGain_ * vibrato_->tick();
+ lastOutput_ = vibratoGain_ * vibrato_.tick();
lastOutput_ += filter_.tick( noise_.tick() );
return lastOutput_;
}
-StkFloat *Modulate :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Generator::tick( vector, vectorSize );
-}
-
-StkFrames& Modulate :: tick( StkFrames& frames, unsigned int channel )
-{
- return Generator::tick( frames, channel );
-}
-
diff --git a/src/Moog.cpp b/src/Moog.cpp
index 275df78..23155b7 100644
--- a/src/Moog.cpp
+++ b/src/Moog.cpp
@@ -14,7 +14,7 @@
- Vibrato Gain = 1
- Gain = 128
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -24,7 +24,7 @@
Moog :: Moog()
{
// Concatenate the STK rawwave path to the rawwave file
- attacks_.push_back( new WvIn( (Stk::rawwavePath() + "mandpluk.raw").c_str(), true ) );
+ attacks_.push_back( new FileWvIn( (Stk::rawwavePath() + "mandpluk.raw").c_str(), true ) );
loops_.push_back ( new WaveLoop( (Stk::rawwavePath() + "impuls20.raw").c_str(), true ) );
loops_.push_back ( new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), true ) ); // vibrato
loops_[1]->setFrequency( 6.122 );
@@ -92,7 +92,7 @@ void Moog :: setModulationDepth(StkFloat mDepth)
modDepth_ = mDepth * 0.5;
}
-StkFloat Moog :: tick()
+StkFloat Moog :: computeSample()
{
StkFloat temp;
@@ -110,16 +110,6 @@ StkFloat Moog :: tick()
return lastOutput_ * 3.0;
}
-StkFloat *Moog :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Instrmnt::tick( vector, vectorSize );
-}
-
-StkFrames& Moog :: tick( StkFrames& frames, unsigned int channel )
-{
- return Instrmnt::tick( frames, channel );
-}
-
void Moog :: controlChange(int number, StkFloat value)
{
StkFloat norm = value * ONE_OVER_128;
diff --git a/src/Mutex.cpp b/src/Mutex.cpp
index 0ea57cc..0f4055e 100644
--- a/src/Mutex.cpp
+++ b/src/Mutex.cpp
@@ -7,7 +7,7 @@
systems, the pthread library is used. Under
Windows, critical sections are used.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
diff --git a/src/NRev.cpp b/src/NRev.cpp
index 09e52ce..f8eb5e5 100644
--- a/src/NRev.cpp
+++ b/src/NRev.cpp
@@ -12,7 +12,7 @@
filters in parallel with corresponding right
and left outputs.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -69,7 +69,7 @@ void NRev :: setT60( StkFloat T60 )
combCoefficient_[i] = pow(10.0, (-3.0 * combDelays_[i].getDelay() / (T60 * Stk::sampleRate())));
}
-StkFloat NRev :: tick(StkFloat input)
+StkFloat NRev :: computeSample(StkFloat input)
{
StkFloat temp, temp0, temp1, temp2, temp3;
int i;
@@ -112,15 +112,4 @@ StkFloat NRev :: tick(StkFloat input)
lastOutput_[1] += temp;
return Effect::lastOut();
-
-}
-
-StkFloat *NRev :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Effect::tick( vector, vectorSize );
-}
-
-StkFrames& NRev :: tick( StkFrames& frames, unsigned int channel )
-{
- return Effect::tick( frames, channel );
}
diff --git a/src/Noise.cpp b/src/Noise.cpp
index ed31026..0248ea5 100644
--- a/src/Noise.cpp
+++ b/src/Noise.cpp
@@ -6,7 +6,7 @@
C rand() function. The quality of the rand()
function varies from one OS to another.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -40,20 +40,10 @@ void Noise :: setSeed( unsigned int seed )
srand( seed );
}
-StkFloat Noise :: tick()
+StkFloat Noise :: computeSample()
{
lastOutput_ = (StkFloat) (2.0 * rand() / (RAND_MAX + 1.0) );
lastOutput_ -= 1.0;
return lastOutput_;
}
-StkFloat *Noise :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Generator::tick( vector, vectorSize );
-}
-
-StkFrames& Noise :: tick( StkFrames& frames, unsigned int channel )
-{
- return Generator::tick( frames, channel );
-}
-
diff --git a/src/OnePole.cpp b/src/OnePole.cpp
index 04360b8..368ddb9 100644
--- a/src/OnePole.cpp
+++ b/src/OnePole.cpp
@@ -8,7 +8,7 @@
the real axis of the z-plane while maintaining
a constant peak filter gain.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -82,20 +82,15 @@ StkFloat OnePole :: lastOut(void) const
return Filter::lastOut();
}
-StkFloat OnePole :: tick(StkFloat sample)
+StkFloat OnePole :: tick( StkFloat input )
{
- inputs_[0] = gain_ * sample;
+ inputs_[0] = gain_ * input;
outputs_[0] = b_[0] * inputs_[0] - a_[1] * outputs_[1];
outputs_[1] = outputs_[0];
return outputs_[0];
}
-StkFloat *OnePole :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Filter::tick( vector, vectorSize );
-}
-
StkFrames& OnePole :: tick( StkFrames& frames, unsigned int channel )
{
return Filter::tick( frames, channel );
diff --git a/src/OneZero.cpp b/src/OneZero.cpp
index a1cf028..d19f8e4 100644
--- a/src/OneZero.cpp
+++ b/src/OneZero.cpp
@@ -8,7 +8,7 @@
along the real axis of the z-plane while
maintaining a constant filter gain.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -81,20 +81,15 @@ StkFloat OneZero :: lastOut(void) const
return Filter::lastOut();
}
-StkFloat OneZero :: tick(StkFloat sample)
+StkFloat OneZero :: tick( StkFloat input )
{
- inputs_[0] = gain_ * sample;
+ inputs_[0] = gain_ * input;
outputs_[0] = b_[1] * inputs_[1] + b_[0] * inputs_[0];
inputs_[1] = inputs_[0];
return outputs_[0];
}
-StkFloat *OneZero :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Filter::tick( vector, vectorSize );
-}
-
StkFrames& OneZero :: tick( StkFrames& frames, unsigned int channel )
{
return Filter::tick( frames, channel );
diff --git a/src/PRCRev.cpp b/src/PRCRev.cpp
index 9d6590e..4dffade 100644
--- a/src/PRCRev.cpp
+++ b/src/PRCRev.cpp
@@ -10,7 +10,7 @@
two series allpass units and two parallel comb
filters.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -68,7 +68,7 @@ void PRCRev :: setT60( StkFloat T60 )
combCoefficient_[1] = pow(10.0, (-3.0 * combDelays_[1].getDelay() / (T60 * Stk::sampleRate())));
}
-StkFloat PRCRev :: tick(StkFloat input)
+StkFloat PRCRev :: computeSample(StkFloat input)
{
StkFloat temp, temp0, temp1, temp2, temp3;
@@ -94,15 +94,5 @@ StkFloat PRCRev :: tick(StkFloat input)
lastOutput_[1] += temp;
return Effect::lastOut();
-
}
-StkFloat *PRCRev :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Effect::tick( vector, vectorSize );
-}
-
-StkFrames& PRCRev :: tick( StkFrames& frames, unsigned int channel )
-{
- return Effect::tick( frames, channel );
-}
diff --git a/src/PercFlut.cpp b/src/PercFlut.cpp
index 943e976..e4014ea 100644
--- a/src/PercFlut.cpp
+++ b/src/PercFlut.cpp
@@ -22,7 +22,7 @@
type who should worry about this (making
money) worry away.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -78,11 +78,11 @@ void PercFlut :: noteOn(StkFloat frequency, StkFloat amplitude)
#endif
}
-StkFloat PercFlut :: tick()
+StkFloat PercFlut :: computeSample()
{
register StkFloat temp;
- temp = vibrato_->tick() * modDepth_ * 0.2;
+ temp = vibrato_.tick() * modDepth_ * 0.2;
waves_[0]->setFrequency(baseFrequency_ * (1.0 + temp) * ratios_[0]);
waves_[1]->setFrequency(baseFrequency_ * (1.0 + temp) * ratios_[1]);
waves_[2]->setFrequency(baseFrequency_ * (1.0 + temp) * ratios_[2]);
@@ -104,13 +104,3 @@ StkFloat PercFlut :: tick()
lastOutput_ = temp * 0.5;
return lastOutput_;
}
-
-StkFloat *PercFlut :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Instrmnt::tick( vector, vectorSize );
-}
-
-StkFrames& PercFlut :: tick( StkFrames& frames, unsigned int channel )
-{
- return Instrmnt::tick( frames, channel );
-}
diff --git a/src/Phonemes.cpp b/src/Phonemes.cpp
index 78d2f40..372275b 100644
--- a/src/Phonemes.cpp
+++ b/src/Phonemes.cpp
@@ -6,7 +6,7 @@
set of 32 static phoneme formant parameters
and provide access to those values.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
diff --git a/src/PitShift.cpp b/src/PitShift.cpp
index 16614fc..248286f 100644
--- a/src/PitShift.cpp
+++ b/src/PitShift.cpp
@@ -5,12 +5,12 @@
This class implements a simple pitch shifter
using delay lines.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
#include "PitShift.h"
-#include
+#include
const int maxDelay = 5024;
@@ -55,7 +55,7 @@ void PitShift :: setShift(StkFloat shift)
}
}
-StkFloat PitShift :: tick(StkFloat input)
+StkFloat PitShift :: computeSample(StkFloat input)
{
// Calculate the two delay length values, keeping them within the
// range 12 to maxDelay-12.
@@ -83,15 +83,6 @@ StkFloat PitShift :: tick(StkFloat input)
lastOutput_[0] *= effectMix_;
lastOutput_[0] += (1.0 - effectMix_) * input;
lastOutput_[1] = lastOutput_[0];
+
return lastOutput_[0];
}
-
-StkFloat *PitShift :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Effect::tick( vector, vectorSize );
-}
-
-StkFrames& PitShift :: tick( StkFrames& frames, unsigned int channel )
-{
- return Effect::tick( frames, channel );
-}
diff --git a/src/PluckTwo.cpp b/src/PluckTwo.cpp
index 5fde12a..1f5b51b 100644
--- a/src/PluckTwo.cpp
+++ b/src/PluckTwo.cpp
@@ -14,7 +14,7 @@
use possibly subject to patents held by
Stanford University, Yamaha, and others.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
diff --git a/src/Plucked.cpp b/src/Plucked.cpp
index 23ab2fb..6d3f9a0 100644
--- a/src/Plucked.cpp
+++ b/src/Plucked.cpp
@@ -13,7 +13,7 @@
Stanford, bearing the names of Karplus and/or
Strong.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -112,20 +112,10 @@ void Plucked :: noteOff(StkFloat amplitude)
#endif
}
-StkFloat Plucked :: tick()
+StkFloat Plucked :: computeSample()
{
// Here's the whole inner loop of the instrument!!
lastOutput_ = delayLine_.tick( loopFilter_.tick( delayLine_.lastOut() * loopGain_ ) );
lastOutput_ *= 3.0;
return lastOutput_;
}
-
-StkFloat *Plucked :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Instrmnt::tick( vector, vectorSize );
-}
-
-StkFrames& Plucked :: tick( StkFrames& frames, unsigned int channel )
-{
- return Instrmnt::tick( frames, channel );
-}
diff --git a/src/PoleZero.cpp b/src/PoleZero.cpp
index 0b6fbad..b633e43 100644
--- a/src/PoleZero.cpp
+++ b/src/PoleZero.cpp
@@ -8,7 +8,7 @@
filter with a given coefficient. Another
method is provided to create a DC blocking filter.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -79,9 +79,9 @@ StkFloat PoleZero :: lastOut(void) const
return Filter::lastOut();
}
-StkFloat PoleZero :: tick(StkFloat sample)
+StkFloat PoleZero :: tick( StkFloat input )
{
- inputs_[0] = gain_ * sample;
+ inputs_[0] = gain_ * input;
outputs_[0] = b_[0] * inputs_[0] + b_[1] * inputs_[1] - a_[1] * outputs_[1];
inputs_[1] = inputs_[0];
outputs_[1] = outputs_[0];
@@ -89,11 +89,6 @@ StkFloat PoleZero :: tick(StkFloat sample)
return outputs_[0];
}
-StkFloat *PoleZero :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Filter::tick( vector, vectorSize );
-}
-
StkFrames& PoleZero :: tick( StkFrames& frames, unsigned int channel )
{
return Filter::tick( frames, channel );
diff --git a/src/ReedTable.cpp b/src/ReedTable.cpp
index add3079..bcefc41 100644
--- a/src/ReedTable.cpp
+++ b/src/ReedTable.cpp
@@ -13,7 +13,7 @@
Smith (1986), Hirschman, Cook, Scavone, and
others for more information.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -39,7 +39,7 @@ void ReedTable :: setSlope(StkFloat slope)
slope_ = slope;
}
-StkFloat ReedTable :: tick(StkFloat input)
+StkFloat ReedTable :: computeSample(StkFloat input)
{
// The input is differential pressure across the reed.
lastOutput_ = offset_ + (slope_ * input);
@@ -55,12 +55,3 @@ StkFloat ReedTable :: tick(StkFloat input)
return lastOutput_;
}
-StkFloat *ReedTable :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Function::tick( vector, vectorSize );
-}
-
-StkFrames& ReedTable :: tick( StkFrames& frames, unsigned int channel )
-{
- return Function::tick( frames, channel );
-}
diff --git a/src/Resonate.cpp b/src/Resonate.cpp
index 2dbc9b3..1d2110e 100644
--- a/src/Resonate.cpp
+++ b/src/Resonate.cpp
@@ -13,7 +13,7 @@
- Zero Radii = 1
- Envelope Gain = 128
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -112,23 +112,13 @@ void Resonate :: setEqualGainZeroes()
filter_.setEqualGainZeroes();
}
-StkFloat Resonate :: tick()
+StkFloat Resonate :: computeSample()
{
lastOutput_ = filter_.tick( noise_.tick() );
lastOutput_ *= adsr_.tick();
return lastOutput_;
}
-StkFloat *Resonate :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Instrmnt::tick( vector, vectorSize );
-}
-
-StkFrames& Resonate :: tick( StkFrames& frames, unsigned int channel )
-{
- return Instrmnt::tick( frames, channel );
-}
-
void Resonate :: controlChange(int number, StkFloat value)
{
StkFloat norm = value * ONE_OVER_128;
diff --git a/src/Rhodey.cpp b/src/Rhodey.cpp
index 83fe381..664d8e5 100644
--- a/src/Rhodey.cpp
+++ b/src/Rhodey.cpp
@@ -26,7 +26,7 @@
type who should worry about this (making
money) worry away.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -56,14 +56,14 @@ Rhodey :: Rhodey()
adsr_[3]->setAllTimes( 0.001, 0.25, 0.0, 0.04);
twozero_.setGain( 1.0 );
-}
+}
Rhodey :: ~Rhodey()
{
}
void Rhodey :: setFrequency(StkFloat frequency)
-{
+{
baseFrequency_ = frequency * 2.0;
for (unsigned int i=0; itick() * waves_[2]->tick();
// Calculate amplitude modulation and apply it to output.
- temp2 = vibrato_->tick() * modDepth_;
+ temp2 = vibrato_.tick() * modDepth_;
temp = temp * (1.0 + temp2);
lastOutput_ = temp * 0.5;
return lastOutput_;
}
-
-StkFloat *Rhodey :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Instrmnt::tick( vector, vectorSize );
-}
-
-StkFrames& Rhodey :: tick( StkFrames& frames, unsigned int channel )
-{
- return Instrmnt::tick( frames, channel );
-}
diff --git a/src/RtAudio.cpp b/src/RtAudio.cpp
index a1c7ec5..1f6a597 100644
--- a/src/RtAudio.cpp
+++ b/src/RtAudio.cpp
@@ -10,7 +10,7 @@
RtAudio WWW site: http://music.mcgill.ca/~gary/rtaudio/
RtAudio: realtime audio i/o C++ classes
- Copyright (c) 2001-2004 Gary P. Scavone
+ Copyright (c) 2001-2005 Gary P. Scavone
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files
@@ -37,7 +37,13 @@
*/
/************************************************************************/
-// RtAudio: Version 3.0.2, pre-release for STK 4.2.0
+// RtAudio: Version 3.0.2 (14 October 2005)
+
+// Modified by Robin Davies, 1 October 2005
+// - Improvements to DirectX pointer chasing.
+// - Backdoor RtDsStatistics hook provides DirectX performance information.
+// - Bug fix for non-power-of-two Asio granularity used by Edirol PCR-A30.
+// - Auto-call CoInitialize for DSOUND and ASIO platforms.
#include "RtAudio.h"
#include
@@ -325,7 +331,7 @@ void RtApi :: openStream( int outputDevice, int outputChannels,
if ( i == defaultDevice ) continue;
device = i;
}
- if (devices_[device].probed == false) {
+ if ( devices_[device].probed == false ) {
// If the device wasn't successfully probed before, try it
// (again) now.
clearDeviceInfo(&devices_[device]);
@@ -355,25 +361,25 @@ void RtApi :: openStream( int outputDevice, int outputChannels,
else
device = inputDevice - 1;
- for (int i=-1; i= 0 ) {
if ( i == defaultDevice ) continue;
device = i;
}
- if (devices_[device].probed == false) {
+ if ( devices_[device].probed == false ) {
// If the device wasn't successfully probed before, try it
// (again) now.
clearDeviceInfo(&devices_[device]);
probeDeviceInfo(&devices_[device]);
}
if ( devices_[device].probed )
- result = probeDeviceOpen(device, mode, channels, sampleRate,
- format, bufferSize, numberOfBuffers);
- if (result == SUCCESS) break;
+ result = probeDeviceOpen( device, mode, channels, sampleRate,
+ format, bufferSize, numberOfBuffers );
+ if ( result == SUCCESS ) break;
errorMessages.append( " " );
errorMessages.append( message_ );
errorMessages.append( "\n" );
- if ( outputDevice > 0 ) break;
+ if ( inputDevice > 0 ) break;
}
}
@@ -1960,13 +1966,13 @@ void RtApiCore :: probeDeviceInfo( RtApiDevice *info )
info->probed = true;
}
-OSStatus callbackHandler(AudioDeviceID inDevice,
- const AudioTimeStamp* inNow,
- const AudioBufferList* inInputData,
- const AudioTimeStamp* inInputTime,
- AudioBufferList* outOutputData,
- const AudioTimeStamp* inOutputTime,
- void* infoPointer)
+OSStatus callbackHandler( AudioDeviceID inDevice,
+ const AudioTimeStamp* inNow,
+ const AudioBufferList* inInputData,
+ const AudioTimeStamp* inInputTime,
+ AudioBufferList* outOutputData,
+ const AudioTimeStamp* inOutputTime,
+ void* infoPointer )
{
CallbackInfo *info = (CallbackInfo *) infoPointer;
@@ -1982,11 +1988,11 @@ OSStatus callbackHandler(AudioDeviceID inDevice,
return kAudioHardwareNoError;
}
-OSStatus deviceListener(AudioDeviceID inDevice,
- UInt32 channel,
- Boolean isInput,
- AudioDevicePropertyID propertyID,
- void* handlePointer)
+OSStatus deviceListener( AudioDeviceID inDevice,
+ UInt32 channel,
+ Boolean isInput,
+ AudioDevicePropertyID propertyID,
+ void* handlePointer )
{
CoreHandle *handle = (CoreHandle *) handlePointer;
if ( propertyID == kAudioDeviceProcessorOverload ) {
@@ -2577,6 +2583,7 @@ void RtApiCore :: callbackEvent( AudioDeviceID deviceId, void *inData, void *out
}
}
+ id = *( (AudioDeviceID *) devices_[stream_.device[1]].apiDeviceId );
if ( stream_.mode == INPUT || ( stream_.mode == DUPLEX && deviceId == id ) ) {
if (stream_.doConvertBuffer[1]) {
@@ -4649,8 +4656,34 @@ struct AsioHandle {
:stopStream(false), bufferInfos(0) {}
};
+static const char*GetAsioErrorString(ASIOError result)
+{
+ struct Messages
+ {
+ ASIOError value;
+ const char*message;
+ };
+ static Messages m[] =
+ {
+ { ASE_NotPresent, "Hardware input or output is not present or available." },
+ { ASE_HWMalfunction, "Hardware is malfunctioning." },
+ { ASE_InvalidParameter, "Invalid input parameter." },
+ { ASE_InvalidMode, "Invalid mode." },
+ { ASE_SPNotAdvancing, "Sample position not advancing." },
+ { ASE_NoClock, "Sample clock or rate cannot be determined or is not present." },
+ { ASE_NoMemory, "Not enough memory to complete the request." }
+ };
+
+ for (int i = 0; i < sizeof(m)/sizeof(m[0]); ++i)
+ {
+ if (m[i].value == result) return m[i].message;
+ }
+ return "Unknown error.";
+}
+
RtApiAsio :: RtApiAsio()
{
+ this->coInitialized = false;
this->initialize();
if (nDevices_ <= 0) {
@@ -4662,10 +4695,26 @@ RtApiAsio :: RtApiAsio()
RtApiAsio :: ~RtApiAsio()
{
if ( stream_.mode != UNINITIALIZED ) closeStream();
+ if ( coInitialized )
+ {
+ CoUninitialize();
+ }
+
}
void RtApiAsio :: initialize(void)
{
+
+ // ASIO cannot run on a multi-threaded appartment. You can call CoInitialize beforehand, but it must be
+ // for appartment threading (in which case, CoInitilialize will return S_FALSE here).
+ coInitialized = false;
+ HRESULT hr = CoInitialize(NULL);
+ if (FAILED(hr))
+ {
+ sprintf(message_,"RtApiAsio: ASIO requires a single-threaded appartment. Call CoInitializeEx(0,COINIT_APARTMENTTHREADED)");
+ }
+ coInitialized = true;
+
nDevices_ = drivers.asioGetNumDev();
if (nDevices_ <= 0) return;
@@ -4709,16 +4758,8 @@ void RtApiAsio :: probeDeviceInfo(RtApiDevice *info)
ASIOError result = ASIOInit( &driverInfo );
if ( result != ASE_OK ) {
- char details[32];
- if ( result == ASE_HWMalfunction )
- sprintf(details, "hardware malfunction");
- else if ( result == ASE_NoMemory )
- sprintf(details, "no memory");
- else if ( result == ASE_NotPresent )
- sprintf(details, "driver/hardware not present");
- else
- sprintf(details, "unspecified");
- sprintf(message_, "RtApiAsio: error (%s) initializing driver (%s).", details, info->name.c_str());
+ sprintf(message_, "RtApiAsio: error (%s) initializing driver (%s).",
+ GetAsioErrorString(result), info->name.c_str());
error(RtError::DEBUG_WARNING);
return;
}
@@ -4728,7 +4769,9 @@ void RtApiAsio :: probeDeviceInfo(RtApiDevice *info)
result = ASIOGetChannels( &inputChannels, &outputChannels );
if ( result != ASE_OK ) {
drivers.removeCurrentDriver();
- sprintf(message_, "RtApiAsio: error getting input/output channel count (%s).", info->name.c_str());
+ sprintf(message_, "RtApiAsio: error (%s) getting input/output channel count (%s).",
+ GetAsioErrorString(result),
+ info->name.c_str());
error(RtError::DEBUG_WARNING);
return;
}
@@ -4771,7 +4814,9 @@ void RtApiAsio :: probeDeviceInfo(RtApiDevice *info)
result = ASIOGetChannelInfo( &channelInfo );
if ( result != ASE_OK ) {
drivers.removeCurrentDriver();
- sprintf(message_, "RtApiAsio: error getting driver (%s) channel information.", info->name.c_str());
+ sprintf(message_, "RtApiAsio: error (%s) getting driver (%s) channel information.",
+ GetAsioErrorString(result),
+ info->name.c_str());
error(RtError::DEBUG_WARNING);
return;
}
@@ -4915,23 +4960,16 @@ bool RtApiAsio :: probeDeviceOpen(int device, StreamMode mode, int channels,
ASIOError result;
if ( mode != INPUT || stream_.mode != OUTPUT ) {
if ( !drivers.loadDriver( (char *)devices_[device].name.c_str() ) ) {
- sprintf(message_, "RtApiAsio: error loading driver (%s).", devices_[device].name.c_str());
+ sprintf(message_, "RtApiAsio: error loading driver (%s).",
+ devices_[device].name.c_str());
error(RtError::DEBUG_WARNING);
return FAILURE;
}
result = ASIOInit( &driverInfo );
if ( result != ASE_OK ) {
- char details[32];
- if ( result == ASE_HWMalfunction )
- sprintf(details, "hardware malfunction");
- else if ( result == ASE_NoMemory )
- sprintf(details, "no memory");
- else if ( result == ASE_NotPresent )
- sprintf(details, "driver/hardware not present");
- else
- sprintf(details, "unspecified");
- sprintf(message_, "RtApiAsio: error (%s) initializing driver (%s).", details, devices_[device].name.c_str());
+ sprintf(message_, "RtApiAsio: error (%s) initializing driver (%s).",
+ GetAsioErrorString(result), devices_[device].name.c_str());
error(RtError::DEBUG_WARNING);
return FAILURE;
}
@@ -4942,8 +4980,9 @@ bool RtApiAsio :: probeDeviceOpen(int device, StreamMode mode, int channels,
result = ASIOGetChannels( &inputChannels, &outputChannels );
if ( result != ASE_OK ) {
drivers.removeCurrentDriver();
- sprintf(message_, "RtApiAsio: error getting input/output channel count (%s).",
- devices_[device].name.c_str());
+ sprintf(message_, "RtApiAsio: error (%s) getting input/output channel count (%s).",
+ GetAsioErrorString(result),
+ devices_[device].name.c_str());
error(RtError::DEBUG_WARNING);
return FAILURE;
}
@@ -5029,8 +5068,9 @@ bool RtApiAsio :: probeDeviceOpen(int device, StreamMode mode, int channels,
result = ASIOGetBufferSize( &minSize, &maxSize, &preferSize, &granularity );
if ( result != ASE_OK ) {
drivers.removeCurrentDriver();
- sprintf(message_, "RtApiAsio: driver (%s) error getting buffer size.",
- devices_[device].name.c_str());
+ sprintf(message_, "RtApiAsio: error (%s) on driver (%s) error getting buffer size.",
+ GetAsioErrorString(result),
+ devices_[device].name.c_str());
error(RtError::DEBUG_WARNING);
return FAILURE;
}
@@ -5044,8 +5084,14 @@ bool RtApiAsio :: probeDeviceOpen(int device, StreamMode mode, int channels,
if ( *bufferSize < minSize ) *bufferSize = minSize;
else if ( *bufferSize > maxSize ) *bufferSize = maxSize;
else *bufferSize = preferSize;
+ } else if (granularity != 0)
+ {
+ // to an even multiple of granularity, rounding up.
+ *bufferSize = (*bufferSize + granularity-1)/granularity*granularity;
}
+
+
if ( mode == INPUT && stream_.mode == OUTPUT && stream_.bufferSize != *bufferSize )
std::cerr << "Possible input/output buffersize discrepancy!" << std::endl;
@@ -5111,8 +5157,9 @@ bool RtApiAsio :: probeDeviceOpen(int device, StreamMode mode, int channels,
asioCallbacks.bufferSwitchTimeInfo = NULL;
result = ASIOCreateBuffers( handle->bufferInfos, nChannels, stream_.bufferSize, &asioCallbacks);
if ( result != ASE_OK ) {
- sprintf(message_, "RtApiAsio: driver (%s) error creating buffers.",
- devices_[device].name.c_str());
+ sprintf(message_, "RtApiAsio: eror (%s) on driver (%s) error creating buffers.",
+ GetAsioErrorString(result),
+ devices_[device].name.c_str());
goto error;
}
@@ -5138,8 +5185,9 @@ bool RtApiAsio :: probeDeviceOpen(int device, StreamMode mode, int channels,
if (stream_.userBuffer) free(stream_.userBuffer);
stream_.userBuffer = (char *) calloc(buffer_bytes, 1);
if (stream_.userBuffer == NULL) {
- sprintf(message_, "RtApiAsio: error allocating user buffer memory (%s).",
- devices_[device].name.c_str());
+ sprintf(message_, "RtApiAsio: error (%s) allocating user buffer memory (%s).",
+ GetAsioErrorString(result),
+ devices_[device].name.c_str());
goto error;
}
}
@@ -5163,7 +5211,8 @@ bool RtApiAsio :: probeDeviceOpen(int device, StreamMode mode, int channels,
if (stream_.deviceBuffer) free(stream_.deviceBuffer);
stream_.deviceBuffer = (char *) calloc(buffer_bytes, 1);
if (stream_.deviceBuffer == NULL) {
- sprintf(message_, "RtApiAsio: error allocating device buffer memory (%s).",
+ sprintf(message_, "RtApiAsio: error (%s) allocating device buffer memory (%s).",
+ GetAsioErrorString(result),
devices_[device].name.c_str());
goto error;
}
@@ -5509,7 +5558,63 @@ void RtApiAsio :: callbackEvent(long bufferIndex)
#if defined(__WINDOWS_DS__) // Windows DirectSound API
+
#include
+#include
+
+#define MINIMUM_DEVICE_BUFFER_SIZE 32768
+
+
+#ifdef _MSC_VER // if Microsoft Visual C++
+#pragma comment(lib,"winmm.lib") // then, auto-link winmm.lib. Otherwise, it has to be added manually.
+#endif
+
+
+static inline DWORD dsPointerDifference(DWORD laterPointer,DWORD earlierPointer,DWORD bufferSize)
+{
+ if (laterPointer > earlierPointer)
+ {
+ return laterPointer-earlierPointer;
+ } else
+ {
+ return laterPointer-earlierPointer+bufferSize;
+ }
+}
+
+static inline DWORD dsPointerBetween(DWORD pointer, DWORD laterPointer,DWORD earlierPointer, DWORD bufferSize)
+{
+ if (pointer > bufferSize) pointer -= bufferSize;
+ if (laterPointer < earlierPointer)
+ {
+ laterPointer += bufferSize;
+ }
+ if (pointer < earlierPointer)
+ {
+ pointer += bufferSize;
+ }
+ return pointer >= earlierPointer && pointer < laterPointer;
+}
+
+
+#undef GENERATE_DEBUG_LOG // Define this to generate a debug timing log file in c:/rtaudiolog.txt"
+#ifdef GENERATE_DEBUG_LOG
+
+#include "mmsystem.h"
+#include "fstream"
+
+struct TTickRecord
+{
+ DWORD currentReadPointer, safeReadPointer;
+ DWORD currentWritePointer, safeWritePointer;
+ DWORD readTime, writeTime;
+ DWORD nextWritePointer, nextReadPointer;
+};
+
+int currentDebugLogEntry = 0;
+std::vector debugLog(2000);
+
+
+#endif
// A structure to hold various information related to the DirectSound
// API implementation.
@@ -5517,8 +5622,33 @@ struct DsHandle {
void *object;
void *buffer;
UINT bufferPointer;
+ DWORD dsBufferSize;
+ DWORD dsPointerLeadTime; // the number of bytes ahead of the safe pointer to lead by.
};
+
+RtApiDs::RtDsStatistics RtApiDs::statistics;
+
+// Provides a backdoor hook to monitor for DirectSound read overruns and write underruns.
+RtApiDs::RtDsStatistics RtApiDs::getDsStatistics()
+{
+ RtDsStatistics s = statistics;
+ // update the calculated fields.
+
+
+ if (s.inputFrameSize != 0)
+ {
+ s.latency += s.readDeviceSafeLeadBytes*1.0/s.inputFrameSize / s.sampleRate;
+ }
+ if (s.outputFrameSize != 0)
+ {
+ s.latency +=
+ (s.writeDeviceSafeLeadBytes+ s.writeDeviceBufferLeadBytes)*1.0/s.outputFrameSize / s.sampleRate;
+ }
+ return s;
+}
+
+
// Declarations for utility functions, callbacks, and structures
// specific to the DirectSound implementation.
static bool CALLBACK deviceCountCallback(LPGUID lpguid,
@@ -5554,6 +5684,14 @@ struct enum_info {
RtApiDs :: RtApiDs()
{
+ // Dsound will run both-threaded. If CoInitialize fails, then just accept whatever the mainline
+ // chose for a threading model.
+ coInitialized = false;
+ HRESULT hr = CoInitialize(NULL);
+ if (!FAILED(hr)) {
+ coInitialized = true;
+ }
+
this->initialize();
if (nDevices_ <= 0) {
@@ -5564,6 +5702,10 @@ RtApiDs :: RtApiDs()
RtApiDs :: ~RtApiDs()
{
+ if (coInitialized)
+ {
+ CoUninitialize(); // balanced call.
+ }
if ( stream_.mode != UNINITIALIZED ) closeStream();
}
@@ -5931,11 +6073,32 @@ bool RtApiDs :: probeDeviceOpen( int device, StreamMode mode, int channels,
waveFormat.nBlockAlign = waveFormat.nChannels * waveFormat.wBitsPerSample / 8;
waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;
+ // Determine the device buffer size. By default, 32k,
+ // but we will grow it to make allowances for very large softare buffer sizes.
+ DWORD dsBufferSize = 0;
+ DWORD dsPointerLeadTime = 0;
+
+ buffer_size = MINIMUM_DEVICE_BUFFER_SIZE; // sound cards will always *knock wood* support this
+
+
+ // poisonously large buffer lead time? Then increase the device buffer size accordingly.
+ while (dsPointerLeadTime *2U > (DWORD)buffer_size)
+ {
+ buffer_size *= 2;
+ }
+
+
+
enum_info dsinfo;
void *ohandle = 0, *bhandle = 0;
strncpy( dsinfo.name, devices_[device].name.c_str(), 64 );
dsinfo.isValid = false;
if ( mode == OUTPUT ) {
+ dsPointerLeadTime = (numberOfBuffers) *
+ (*bufferSize) *
+ (waveFormat.wBitsPerSample / 8)
+ *channels;
+
if ( devices_[device].maxOutputChannels < channels ) {
sprintf(message_, "RtApiDs: requested channels (%d) > than supported (%d) by device (%s).",
@@ -6010,7 +6173,7 @@ bool RtApiDs :: probeDeviceOpen( int device, StreamMode mode, int channels,
}
// Setup the secondary DS buffer description.
- buffer_size = channels * *bufferSize * nBuffers * waveFormat.wBitsPerSample / 8;
+ dsBufferSize = (DWORD)buffer_size;
ZeroMemory(&bufferDescription, sizeof(DSBUFFERDESC));
bufferDescription.dwSize = sizeof(DSBUFFERDESC);
bufferDescription.dwFlags = ( DSBCAPS_STICKYFOCUS |
@@ -6109,7 +6272,7 @@ bool RtApiDs :: probeDeviceOpen( int device, StreamMode mode, int channels,
}
// Setup the secondary DS buffer description.
- buffer_size = channels * *bufferSize * nBuffers * waveFormat.wBitsPerSample / 8;
+ dsBufferSize = buffer_size;
ZeroMemory(&bufferDescription, sizeof(DSCBUFFERDESC));
bufferDescription.dwSize = sizeof(DSCBUFFERDESC);
bufferDescription.dwFlags = 0;
@@ -6163,7 +6326,7 @@ bool RtApiDs :: probeDeviceOpen( int device, StreamMode mode, int channels,
else
stream_.deviceFormat[mode] = RTAUDIO_SINT16;
stream_.nUserChannels[mode] = channels;
- *bufferSize = buffer_size / (channels * nBuffers * waveFormat.wBitsPerSample / 8);
+
stream_.bufferSize = *bufferSize;
// Set flags for buffer conversion
@@ -6235,6 +6398,8 @@ bool RtApiDs :: probeDeviceOpen( int device, StreamMode mode, int channels,
handles = (DsHandle *) stream_.apiHandle;
handles[mode].object = ohandle;
handles[mode].buffer = bhandle;
+ handles[mode].dsBufferSize = dsBufferSize;
+ handles[mode].dsPointerLeadTime = dsPointerLeadTime;
stream_.device[mode] = device;
stream_.state = STREAM_STOPPED;
@@ -6430,11 +6595,41 @@ void RtApiDs :: startStream()
verifyStream();
if (stream_.state == STREAM_RUNNING) return;
+
+ // increase scheduler frequency on lesser windows (a side-effect of increasing timer accuracy.
+ // on greater windows (Win2K or later), this is already in effect.
+
MUTEX_LOCK(&stream_.mutex);
- HRESULT result;
+
DsHandle *handles = (DsHandle *) stream_.apiHandle;
+
+ timeBeginPeriod(1);
+
+
+ memset(&statistics,0,sizeof(statistics));
+ statistics.sampleRate = stream_.sampleRate;
+ statistics.writeDeviceBufferLeadBytes = handles[0].dsPointerLeadTime ;
+
+ buffersRolling = false;
+ duplexPrerollBytes = 0;
+
+ if (stream_.mode == DUPLEX)
+ {
+ // 0.5 seconds of silence in DUPLEX mode while the devices spin up and synchronize.
+ duplexPrerollBytes = (int)(0.5*stream_.sampleRate*formatBytes( stream_.deviceFormat[1])*stream_.nDeviceChannels[1]);
+ }
+
+#ifdef GENERATE_DEBUG_LOG
+ currentDebugLogEntry = 0;
+#endif
+
+ HRESULT result;
if (stream_.mode == OUTPUT || stream_.mode == DUPLEX) {
+ statistics.outputFrameSize = formatBytes( stream_.deviceFormat[0])
+ *stream_.nDeviceChannels[0];
+
+
LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) handles[0].buffer;
result = buffer->Play(0, 0, DSBPLAY_LOOPING );
if ( FAILED(result) ) {
@@ -6445,6 +6640,9 @@ void RtApiDs :: startStream()
}
if (stream_.mode == INPUT || stream_.mode == DUPLEX) {
+ statistics.inputFrameSize = formatBytes( stream_.deviceFormat[1])
+ *stream_.nDeviceChannels[1];
+
LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) handles[1].buffer;
result = buffer->Start(DSCBSTART_LOOPING );
if ( FAILED(result) ) {
@@ -6463,11 +6661,31 @@ void RtApiDs :: stopStream()
verifyStream();
if (stream_.state == STREAM_STOPPED) return;
+
// Change the state before the lock to improve shutdown response
// when using a callback.
stream_.state = STREAM_STOPPED;
MUTEX_LOCK(&stream_.mutex);
+
+ timeEndPeriod(1); // revert to normal scheduler frequency on lesser windows.
+
+#ifdef GENERATE_DEBUG_LOG
+ // write the timing log to a .TSV file for analysis in Excel.
+ unlink("c:/rtaudiolog.txt");
+ std::ofstream os("c:/rtaudiolog.txt");
+ os << "writeTime\treadDelay\tnextWritePointer\tnextReadPointer\tcurrentWritePointer\tsafeWritePointer\tcurrentReadPointer\tsafeReadPointer" << std::endl;
+ for (int i = 0; i < currentDebugLogEntry ; ++i)
+ {
+ TTickRecord &r = debugLog[i];
+ os
+ << r.writeTime-debugLog[0].writeTime << "\t" << (r.readTime-r.writeTime) << "\t"
+ << r.nextWritePointer % BUFFER_SIZE << "\t" << r.nextReadPointer % BUFFER_SIZE
+ << "\t" << r.currentWritePointer % BUFFER_SIZE << "\t" << r.safeWritePointer % BUFFER_SIZE
+ << "\t" << r.currentReadPointer % BUFFER_SIZE << "\t" << r.safeReadPointer % BUFFER_SIZE << std::endl;
+ }
+#endif
+
// There is no specific DirectSound API call to "drain" a buffer
// before stopping. We can hack this for playback by writing zeroes
// for another bufferSize * nBuffers frames. For capture, the
@@ -6483,12 +6701,13 @@ void RtApiDs :: stopStream()
if (stream_.mode == OUTPUT || stream_.mode == DUPLEX) {
DWORD currentPos, safePos;
- long buffer_bytes = stream_.bufferSize * stream_.nDeviceChannels[0];
- buffer_bytes *= formatBytes(stream_.deviceFormat[0]);
+ long buffer_bytes = stream_.bufferSize * stream_.nDeviceChannels[0]
+ * formatBytes(stream_.deviceFormat[0]);
+
LPDIRECTSOUNDBUFFER dsBuffer = (LPDIRECTSOUNDBUFFER) handles[0].buffer;
- UINT nextWritePos = handles[0].bufferPointer;
- dsBufferSize = buffer_bytes * stream_.nBuffers;
+ long nextWritePos = handles[0].bufferPointer;
+ dsBufferSize = handles[0].dsBufferSize;
// Write zeroes for nBuffer counts.
for (int i=0; iStop();
if ( FAILED(result) ) {
@@ -6615,8 +6836,7 @@ void RtApiDs :: abortStream()
error(RtError::DRIVER_ERROR);
}
- dsBufferSize = stream_.bufferSize * stream_.nDeviceChannels[0];
- dsBufferSize *= formatBytes(stream_.deviceFormat[0]) * stream_.nBuffers;
+ dsBufferSize = handles[0].dsBufferSize;
// Lock the buffer and clear it so that if we start to play again,
// we won't have old data playing.
@@ -6654,8 +6874,7 @@ void RtApiDs :: abortStream()
error(RtError::DRIVER_ERROR);
}
- dsBufferSize = stream_.bufferSize * stream_.nDeviceChannels[1];
- dsBufferSize *= formatBytes(stream_.deviceFormat[1]) * stream_.nBuffers;
+ dsBufferSize = handles[1].dsBufferSize;
// Lock the buffer and clear it so that if we start to play again,
// we won't have old data playing.
@@ -6702,8 +6921,7 @@ int RtApiDs :: streamWillBlock()
LPDIRECTSOUNDBUFFER dsBuffer = (LPDIRECTSOUNDBUFFER) handles[0].buffer;
UINT nextWritePos = handles[0].bufferPointer;
channels = stream_.nDeviceChannels[0];
- DWORD dsBufferSize = stream_.bufferSize * channels;
- dsBufferSize *= formatBytes(stream_.deviceFormat[0]) * stream_.nBuffers;
+ DWORD dsBufferSize = handles[0].dsBufferSize;
// Find out where the read and "safe write" pointers are.
result = dsBuffer->GetCurrentPosition(¤tPos, &safePos);
@@ -6713,18 +6931,23 @@ int RtApiDs :: streamWillBlock()
error(RtError::DRIVER_ERROR);
}
- if ( currentPos < nextWritePos ) currentPos += dsBufferSize; // unwrap offset
- frames = currentPos - nextWritePos;
+ DWORD leadPos = safePos + handles[0].dsPointerLeadTime;
+ if (leadPos > dsBufferSize) {
+ leadPos -= dsBufferSize;
+ }
+ if ( leadPos < nextWritePos ) leadPos += dsBufferSize; // unwrap offset
+
+ frames = (leadPos - nextWritePos);
frames /= channels * formatBytes(stream_.deviceFormat[0]);
}
- if (stream_.mode == INPUT || stream_.mode == DUPLEX) {
+ if (stream_.mode == INPUT ) {
+ // note that we don't block on DUPLEX input anymore. We run lockstep with the write pointer instead.
LPDIRECTSOUNDCAPTUREBUFFER dsBuffer = (LPDIRECTSOUNDCAPTUREBUFFER) handles[1].buffer;
UINT nextReadPos = handles[1].bufferPointer;
channels = stream_.nDeviceChannels[1];
- DWORD dsBufferSize = stream_.bufferSize * channels;
- dsBufferSize *= formatBytes(stream_.deviceFormat[1]) * stream_.nBuffers;
+ DWORD dsBufferSize = handles[1].dsBufferSize;
// Find out where the write and "safe read" pointers are.
result = dsBuffer->GetCurrentPosition(¤tPos, &safePos);
@@ -6734,18 +6957,10 @@ int RtApiDs :: streamWillBlock()
error(RtError::DRIVER_ERROR);
}
- if ( safePos < nextReadPos ) safePos += dsBufferSize; // unwrap offset
+ if ( safePos < (DWORD)nextReadPos ) safePos += dsBufferSize; // unwrap offset
- if (stream_.mode == DUPLEX ) {
- // Take largest value of the two.
- int temp = safePos - nextReadPos;
- temp /= channels * formatBytes(stream_.deviceFormat[1]);
- frames = ( temp > frames ) ? temp : frames;
- }
- else {
- frames = safePos - nextReadPos;
- frames /= channels * formatBytes(stream_.deviceFormat[1]);
- }
+ frames = (int)(safePos - nextReadPos);
+ frames /= channels * formatBytes(stream_.deviceFormat[1]);
}
frames = stream_.bufferSize - frames;
@@ -6778,15 +6993,91 @@ void RtApiDs :: tickStream()
}
HRESULT result;
- DWORD currentPos, safePos;
+ DWORD currentWritePos, safeWritePos;
+ DWORD currentReadPos, safeReadPos;
+ DWORD leadPos;
+ UINT nextWritePos;
+
+#ifdef GENERATE_DEBUG_LOG
+ DWORD writeTime, readTime;
+#endif
LPVOID buffer1 = NULL;
LPVOID buffer2 = NULL;
DWORD bufferSize1 = 0;
DWORD bufferSize2 = 0;
+
char *buffer;
long buffer_bytes;
DsHandle *handles = (DsHandle *) stream_.apiHandle;
+
+ if (stream_.mode == DUPLEX && !buffersRolling)
+ {
+ assert(handles[0].dsBufferSize == handles[1].dsBufferSize);
+
+ // it takes a while for the devices to get rolling. As a result, there's
+ // no guarantee that the capture and write device pointers will move in lockstep.
+ // Wait here for both devices to start rolling, and then set our buffer pointers accordingly.
+ // e.g. Crystal Drivers: the capture buffer starts up 5700 to 9600 bytes later than the write
+ // buffer.
+
+ // Stub: a serious risk of having a pre-emptive scheduling round take place between
+ // the two GetCurrentPosition calls... but I'm really not sure how to solve the problem.
+ // Temporarily boost to Realtime priority, maybe; but I'm not sure what priority the
+ // directsound service threads run at. We *should* be roughly within a ms or so of correct.
+
+ LPDIRECTSOUNDBUFFER dsWriteBuffer = (LPDIRECTSOUNDBUFFER) handles[0].buffer;
+ LPDIRECTSOUNDCAPTUREBUFFER dsCaptureBuffer = (LPDIRECTSOUNDCAPTUREBUFFER) handles[1].buffer;
+
+
+ DWORD initialWritePos, initialSafeWritePos;
+ DWORD initialReadPos, initialSafeReadPos;;
+
+
+ result = dsWriteBuffer->GetCurrentPosition(&initialWritePos, &initialSafeWritePos);
+ if ( FAILED(result) ) {
+ sprintf(message_, "RtApiDs: Unable to get current position (%s): %s.",
+ devices_[stream_.device[0]].name.c_str(), getErrorString(result));
+ error(RtError::DRIVER_ERROR);
+ }
+ result = dsCaptureBuffer->GetCurrentPosition(&initialReadPos, &initialSafeReadPos);
+ if ( FAILED(result) ) {
+ sprintf(message_, "RtApiDs: Unable to get current capture position (%s): %s.",
+ devices_[stream_.device[1]].name.c_str(), getErrorString(result));
+ error(RtError::DRIVER_ERROR);
+ }
+ while (true)
+ {
+ result = dsWriteBuffer->GetCurrentPosition(¤tWritePos, &safeWritePos);
+ if ( FAILED(result) ) {
+ sprintf(message_, "RtApiDs: Unable to get current position (%s): %s.",
+ devices_[stream_.device[0]].name.c_str(), getErrorString(result));
+ error(RtError::DRIVER_ERROR);
+ }
+ result = dsCaptureBuffer->GetCurrentPosition(¤tReadPos, &safeReadPos);
+ if ( FAILED(result) ) {
+ sprintf(message_, "RtApiDs: Unable to get current capture position (%s): %s.",
+ devices_[stream_.device[1]].name.c_str(), getErrorString(result));
+ error(RtError::DRIVER_ERROR);
+ }
+ if (safeWritePos != initialSafeWritePos && safeReadPos != initialSafeReadPos)
+ {
+ break;
+ }
+ Sleep(1);
+ }
+
+ assert(handles[0].dsBufferSize == handles[1].dsBufferSize);
+
+ UINT writeBufferLead = (safeWritePos-safeReadPos + handles[0].dsBufferSize) % handles[0].dsBufferSize;
+ buffersRolling = true;
+ handles[0].bufferPointer = (safeWritePos + handles[0].dsPointerLeadTime);
+ handles[1].bufferPointer = safeReadPos;
+
+ }
+
if (stream_.mode == OUTPUT || stream_.mode == DUPLEX) {
+
+ LPDIRECTSOUNDBUFFER dsBuffer = (LPDIRECTSOUNDBUFFER) handles[0].buffer;
// Setup parameters and do buffer conversion if necessary.
if (stream_.doConvertBuffer[0]) {
@@ -6809,23 +7100,33 @@ void RtApiDs :: tickStream()
if ( stream_.deviceFormat[0] == RTAUDIO_SINT8 )
for ( int i=0; iGetCurrentPosition(¤tPos, &safePos);
- if ( FAILED(result) ) {
- sprintf(message_, "RtApiDs: Unable to get current position (%s): %s.",
- devices_[stream_.device[0]].name.c_str(), getErrorString(result));
- error(RtError::DRIVER_ERROR);
- }
+ DWORD endWrite;
+ while (true)
+ {
+ // Find out where the read and "safe write" pointers are.
+ result = dsBuffer->GetCurrentPosition(¤tWritePos, &safeWritePos);
+ if ( FAILED(result) ) {
+ sprintf(message_, "RtApiDs: Unable to get current position (%s): %s.",
+ devices_[stream_.device[0]].name.c_str(), getErrorString(result));
+ error(RtError::DRIVER_ERROR);
+ }
- if ( currentPos < nextWritePos ) currentPos += dsBufferSize; // unwrap offset
- DWORD endWrite = nextWritePos + buffer_bytes;
+ leadPos = safeWritePos + handles[0].dsPointerLeadTime;
+ if (leadPos > dsBufferSize) {
+ leadPos -= dsBufferSize;
+ }
+ if ( leadPos < nextWritePos ) leadPos += dsBufferSize; // unwrap offset
+
+
+ endWrite = nextWritePos + buffer_bytes;
// Check whether the entire write region is behind the play pointer.
- while ( currentPos < endWrite ) {
+
+ if ( leadPos >= endWrite ) break;
+
// If we are here, then we must wait until the play pointer gets
// beyond the write region. The approach here is to use the
// Sleep() function to suspend operation until safePos catches
@@ -6835,21 +7136,38 @@ void RtApiDs :: tickStream()
// A "fudgefactor" less than 1 is used because it was found
// that sleeping too long was MUCH worse than sleeping for
// several shorter periods.
- double millis = (endWrite - currentPos) * 900.0;
- millis /= ( formatBytes(stream_.deviceFormat[0]) * stream_.sampleRate);
+ double millis = (endWrite - leadPos) * 900.0;
+ millis /= ( formatBytes(stream_.deviceFormat[0]) *stream_.nDeviceChannels[0]* stream_.sampleRate);
if ( millis < 1.0 ) millis = 1.0;
- Sleep( (DWORD) millis );
-
- // Wake up, find out where we are now
- result = dsBuffer->GetCurrentPosition( ¤tPos, &safePos );
- if ( FAILED(result) ) {
- sprintf(message_, "RtApiDs: Unable to get current position (%s): %s.",
- devices_[stream_.device[0]].name.c_str(), getErrorString(result));
- error(RtError::DRIVER_ERROR);
+ if (millis > 50.0) {
+ static int nOverruns = 0;
+ ++nOverruns;
}
- if ( currentPos < nextWritePos ) currentPos += dsBufferSize; // unwrap offset
+ Sleep( (DWORD) millis );
+ // Sleep( (DWORD) 2);
+ }
+#ifdef GENERATE_DEBUG_LOG
+ writeTime = timeGetTime();
+#endif
+ if (statistics.writeDeviceSafeLeadBytes < dsPointerDifference(safeWritePos,currentWritePos,handles[0].dsBufferSize))
+ {
+ statistics.writeDeviceSafeLeadBytes = dsPointerDifference(safeWritePos,currentWritePos,handles[0].dsBufferSize);
}
+ if (
+ dsPointerBetween(nextWritePos,safeWritePos,currentWritePos,dsBufferSize)
+ || dsPointerBetween(endWrite,safeWritePos,currentWritePos,dsBufferSize)
+ )
+ {
+ // we've strayed into the forbidden zone.
+ // resync the read pointer.
+ ++statistics.numberOfWriteUnderruns;
+ nextWritePos = safeWritePos + handles[0].dsPointerLeadTime-buffer_bytes+dsBufferSize;
+ while (nextWritePos >= dsBufferSize) nextWritePos-= dsBufferSize;
+ handles[0].bufferPointer = nextWritePos;
+ endWrite = nextWritePos + buffer_bytes;
+ }
+
// Lock free space in the buffer
result = dsBuffer->Lock (nextWritePos, buffer_bytes, &buffer1,
&bufferSize1, &buffer2, &bufferSize2, 0);
@@ -6887,39 +7205,93 @@ void RtApiDs :: tickStream()
buffer_bytes = stream_.bufferSize * stream_.nUserChannels[1];
buffer_bytes *= formatBytes(stream_.userFormat);
}
-
LPDIRECTSOUNDCAPTUREBUFFER dsBuffer = (LPDIRECTSOUNDCAPTUREBUFFER) handles[1].buffer;
- UINT nextReadPos = handles[1].bufferPointer;
- DWORD dsBufferSize = buffer_bytes * stream_.nBuffers;
+ long nextReadPos = handles[1].bufferPointer;
+ DWORD dsBufferSize = handles[1].dsBufferSize;
// Find out where the write and "safe read" pointers are.
- result = dsBuffer->GetCurrentPosition(¤tPos, &safePos);
+ result = dsBuffer->GetCurrentPosition(¤tReadPos, &safeReadPos);
if ( FAILED(result) ) {
sprintf(message_, "RtApiDs: Unable to get current capture position (%s): %s.",
devices_[stream_.device[1]].name.c_str(), getErrorString(result));
error(RtError::DRIVER_ERROR);
}
- if ( safePos < nextReadPos ) safePos += dsBufferSize; // unwrap offset
+ if ( safeReadPos < (DWORD)nextReadPos ) safeReadPos += dsBufferSize; // unwrap offset
DWORD endRead = nextReadPos + buffer_bytes;
- // Check whether the entire write region is behind the play pointer.
- while ( safePos < endRead ) {
- // See comments for playback.
- double millis = (endRead - safePos) * 900.0;
- millis /= ( formatBytes(stream_.deviceFormat[1]) * stream_.sampleRate);
- if ( millis < 1.0 ) millis = 1.0;
- Sleep( (DWORD) millis );
+ // Handling depends on whether we are INPUT or DUPLEX.
+ // If we're in INPUT mode then waiting is a good thing. If we're in DUPLEX mode,
+ // then a wait here will drag the write pointers into the forbidden zone.
+ //
+ // In DUPLEX mode, rather than wait, we will back off the read pointer until
+ // it's in a safe position. This causes dropouts, but it seems to be the only
+ // practical way to sync up the read and write pointers reliably, given the
+ // the very complex relationship between phase and increment of the read and write
+ // pointers.
+ //
+ // In order to minimize audible dropouts in DUPLEX mode, we will provide a pre-roll
+ // period of 0.5 seconds
+ // in which we return zeros from the read buffer while the pointers sync up.
- // Wake up, find out where we are now
- result = dsBuffer->GetCurrentPosition( ¤tPos, &safePos );
- if ( FAILED(result) ) {
- sprintf(message_, "RtApiDs: Unable to get current capture position (%s): %s.",
- devices_[stream_.device[1]].name.c_str(), getErrorString(result));
- error(RtError::DRIVER_ERROR);
+ if (stream_.mode == DUPLEX)
+ {
+ if (safeReadPos < endRead)
+ {
+ if (duplexPrerollBytes <= 0)
+ {
+ // pre-roll time over. Be more agressive.
+ int adjustment = endRead-safeReadPos;
+
+ ++statistics.numberOfReadOverruns;
+ // Two cases:
+ // large adjustments: we've probably run out of CPU cycles, so just resync exactly,
+ // and perform fine adjustments later.
+ // small adjustments: back off by twice as much.
+ if (adjustment >= 2*buffer_bytes)
+ {
+ nextReadPos = safeReadPos-2*buffer_bytes;
+ } else
+ {
+ nextReadPos = safeReadPos-buffer_bytes-adjustment;
+ }
+ statistics.readDeviceSafeLeadBytes = currentReadPos-nextReadPos;
+ if (statistics.readDeviceSafeLeadBytes < 0) statistics.readDeviceSafeLeadBytes += dsBufferSize;
+
+ if (nextReadPos < 0) nextReadPos += dsBufferSize;
+
+ } else {
+ // in pre=roll time. Just do it.
+ nextReadPos = safeReadPos-buffer_bytes;
+ while (nextReadPos < 0) nextReadPos += dsBufferSize;
+ }
+ endRead = nextReadPos + buffer_bytes;
}
+ } else {
+ while ( safeReadPos < endRead ) {
+ // See comments for playback.
+ double millis = (endRead - safeReadPos) * 900.0;
+ millis /= ( formatBytes(stream_.deviceFormat[1]) * stream_.nDeviceChannels[1] * stream_.sampleRate);
+ if ( millis < 1.0 ) millis = 1.0;
+ Sleep( (DWORD) millis );
+
+ // Wake up, find out where we are now
+ result = dsBuffer->GetCurrentPosition( ¤tReadPos, &safeReadPos );
+ if ( FAILED(result) ) {
+ sprintf(message_, "RtApiDs: Unable to get current capture position (%s): %s.",
+ devices_[stream_.device[1]].name.c_str(), getErrorString(result));
+ error(RtError::DRIVER_ERROR);
+ }
- if ( safePos < nextReadPos ) safePos += dsBufferSize; // unwrap offset
+ if ( safeReadPos < (DWORD)nextReadPos ) safeReadPos += dsBufferSize; // unwrap offset
+ }
+ }
+#ifdef GENERATE_DEBUG_LOG
+ readTime = timeGetTime();
+#endif
+ if (statistics.readDeviceSafeLeadBytes < dsPointerDifference(currentReadPos,nextReadPos ,dsBufferSize))
+ {
+ statistics.readDeviceSafeLeadBytes = dsPointerDifference(currentReadPos,nextReadPos ,dsBufferSize);
}
// Lock free space in the buffer
@@ -6931,9 +7303,16 @@ void RtApiDs :: tickStream()
error(RtError::DRIVER_ERROR);
}
- // Copy our buffer into the DS buffer
- CopyMemory(buffer, buffer1, bufferSize1);
- if (buffer2 != NULL) CopyMemory(buffer+bufferSize1, buffer2, bufferSize2);
+ if (duplexPrerollBytes <= 0)
+ {
+ // Copy our buffer into the DS buffer
+ CopyMemory(buffer, buffer1, bufferSize1);
+ if (buffer2 != NULL) CopyMemory(buffer+bufferSize1, buffer2, bufferSize2);
+ } else {
+ memset(buffer,0,bufferSize1);
+ if (buffer2 != NULL) memset(buffer+bufferSize1,0,bufferSize2);
+ duplexPrerollBytes -= bufferSize1 + bufferSize2;
+ }
// Update our buffer offset and unlock sound buffer
nextReadPos = (nextReadPos + bufferSize1 + bufferSize2) % dsBufferSize;
@@ -6945,6 +7324,7 @@ void RtApiDs :: tickStream()
}
handles[1].bufferPointer = nextReadPos;
+
// No byte swapping necessary in DirectSound implementation.
// If necessary, convert 8-bit data from unsigned to signed.
@@ -6955,13 +7335,27 @@ void RtApiDs :: tickStream()
if (stream_.doConvertBuffer[1])
convertBuffer( stream_.userBuffer, stream_.deviceBuffer, stream_.convertInfo[1] );
}
+#ifdef GENERATE_DEBUG_LOG
+ if (currentDebugLogEntry < debugLog.size())
+ {
+ TTickRecord &r = debugLog[currentDebugLogEntry++];
+ r.currentReadPointer = currentReadPos;
+ r.safeReadPointer = safeReadPos;
+ r.currentWritePointer = currentWritePos;
+ r.safeWritePointer = safeWritePos;
+ r.readTime = readTime;
+ r.writeTime = writeTime;
+ r.nextReadPointer = handles[1].bufferPointer;
+ r.nextWritePointer = handles[0].bufferPointer;
+ }
+#endif
+
MUTEX_UNLOCK(&stream_.mutex);
if (stream_.callbackInfo.usingCallback && stopStream)
this->stopStream();
}
-
// Definitions for utility functions and callbacks
// specific to the DirectSound implementation.
@@ -7079,52 +7473,52 @@ static char* getErrorString(int code)
switch (code) {
case DSERR_ALLOCATED:
- return "Direct Sound already allocated";
+ return "Already allocated.";
case DSERR_CONTROLUNAVAIL:
- return "Direct Sound control unavailable";
+ return "Control unavailable.";
case DSERR_INVALIDPARAM:
- return "Direct Sound invalid parameter";
+ return "Invalid parameter.";
case DSERR_INVALIDCALL:
- return "Direct Sound invalid call";
+ return "Invalid call.";
case DSERR_GENERIC:
- return "Direct Sound generic error";
+ return "Generic error.";
case DSERR_PRIOLEVELNEEDED:
- return "Direct Sound Priority level needed";
+ return "Priority level needed";
case DSERR_OUTOFMEMORY:
- return "Direct Sound out of memory";
+ return "Out of memory";
case DSERR_BADFORMAT:
- return "Direct Sound bad format";
+ return "The sample rate or the channel format is not supported.";
case DSERR_UNSUPPORTED:
- return "Direct Sound unsupported error";
+ return "Not supported.";
case DSERR_NODRIVER:
- return "Direct Sound no driver error";
+ return "No driver.";
case DSERR_ALREADYINITIALIZED:
- return "Direct Sound already initialized";
+ return "Already initialized.";
case DSERR_NOAGGREGATION:
- return "Direct Sound no aggregation";
+ return "No aggregation.";
case DSERR_BUFFERLOST:
- return "Direct Sound buffer lost";
+ return "Buffer lost.";
case DSERR_OTHERAPPHASPRIO:
- return "Direct Sound other app has priority";
+ return "Another application already has priority.";
case DSERR_UNINITIALIZED:
- return "Direct Sound uninitialized";
+ return "Uninitialized.";
default:
- return "Direct Sound unknown error";
+ return "DirectSound unknown error";
}
}
diff --git a/src/RtDuplex.cpp b/src/RtDuplex.cpp
index 02b64ec..5751ced 100644
--- a/src/RtDuplex.cpp
+++ b/src/RtDuplex.cpp
@@ -24,7 +24,7 @@
methods, which take/return pointers to
multi-channel sample frames.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
diff --git a/src/RtMidi.cpp b/src/RtMidi.cpp
index 6c0f9b2..d82c9f1 100644
--- a/src/RtMidi.cpp
+++ b/src/RtMidi.cpp
@@ -8,7 +8,7 @@
RtMidi WWW site: http://music.mcgill.ca/~gary/rtmidi/
RtMidi: realtime MIDI i/o C++ classes
- Copyright (c) 2003-2004 Gary P. Scavone
+ Copyright (c) 2003-2005 Gary P. Scavone
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files
@@ -35,7 +35,7 @@
*/
/**********************************************************************/
-// RtMidi: Version 1.0.2, 21 September 2004
+// RtMidi: Version 1.0.4, 14 October 2005
#include "RtMidi.h"
#include
@@ -270,6 +270,14 @@ void midiInputCallback( const MIDIPacketList *list, void *procRef, void *srcRef
else size = 3;
}
else if ( status == 0xF3 ) size = 2;
+ else if ( status == 0xF8 ) {
+ size = 1;
+ if ( data->ignoreFlags & 0x02 ) {
+ // A MIDI timing tick message and we're ignoring it.
+ size = 0;
+ iByte += 3;
+ }
+ }
else if ( status == 0xFE && (data->ignoreFlags & 0x04) ) {
// A MIDI active sensing message and we're ignoring it.
size = 0;
@@ -620,8 +628,10 @@ void RtMidiOut :: sendMessage( std::vector *message )
#if defined(__LINUX_ALSASEQ__)
// The ALSA Sequencer API is based on the use of a callback function for
-// MIDI input. We convert the system specific time stamps to delta
-// time values.
+// MIDI input.
+//
+// Thanks to Pedro Lopez-Cabanillas for help with the ALSA sequencer
+// time stamps and other assorted fixes!!!
#include
#include
@@ -640,6 +650,7 @@ struct AlsaMidiData {
unsigned char *buffer;
pthread_t thread;
unsigned long long lastTime;
+ int queue_id; // an input queue is needed to get timestamped events
};
#define PORT_TYPE( pinfo, bits ) ((snd_seq_port_info_get_capability(pinfo) & (bits)) == (bits))
@@ -656,11 +667,10 @@ extern "C" void *alsaMidiHandler( void *ptr )
long nBytes;
unsigned long long time, lastTime;
- unsigned char lastStatus = 0;
+ bool continueSysex = false;
RtMidiIn::MidiMessage message;
snd_seq_event_t *ev;
- struct timeval tv;
int result;
apiData->bufferSize = 32;
result = snd_midi_event_new( 0, &apiData->coder );
@@ -669,13 +679,14 @@ extern "C" void *alsaMidiHandler( void *ptr )
std::cerr << "\nRtMidiIn::alsaMidiHandler: error initializing MIDI event parser!\n\n";
return 0;
}
- unsigned char *buffer = (unsigned char *) malloc(apiData->bufferSize);
+ unsigned char *buffer = (unsigned char *) malloc( apiData->bufferSize );
if ( buffer == NULL ) {
data->doInput = false;
std::cerr << "\nRtMidiIn::alsaMidiHandler: error initializing buffer memory!\n\n";
return 0;
}
snd_midi_event_init( apiData->coder );
+ snd_midi_event_no_status( apiData->coder, 1 ); // suppress running status messages
while ( data->doInput ) {
@@ -699,7 +710,7 @@ extern "C" void *alsaMidiHandler( void *ptr )
// This is a bit weird, but we now have to decode an ALSA MIDI
// event (back) into MIDI bytes. We'll ignore non-MIDI types.
message.bytes.clear();
- switch (ev->type) {
+ switch ( ev->type ) {
case SND_SEQ_EVENT_PORT_SUBSCRIBED:
#if defined(__RTMIDI_DEBUG__)
@@ -715,6 +726,9 @@ extern "C" void *alsaMidiHandler( void *ptr )
case SND_SEQ_EVENT_QFRAME: // MIDI time code
if ( data->ignoreFlags & 0x02 ) break;
+ case SND_SEQ_EVENT_TICK: // MIDI timing tick
+ if ( data->ignoreFlags & 0x02 ) break;
+
case SND_SEQ_EVENT_SENSING: // Active sensing
if ( data->ignoreFlags & 0x04 ) break;
@@ -722,8 +736,8 @@ extern "C" void *alsaMidiHandler( void *ptr )
if ( (data->ignoreFlags & 0x01) ) break;
if ( ev->data.ext.len > apiData->bufferSize ) {
apiData->bufferSize = ev->data.ext.len;
- free(buffer);
- buffer = (unsigned char *) malloc(apiData->bufferSize);
+ free( buffer );
+ buffer = (unsigned char *) malloc( apiData->bufferSize );
if ( buffer == NULL ) {
data->doInput = false;
std::cerr << "\nRtMidiIn::alsaMidiHandler: error resizing buffer memory!\n\n";
@@ -739,25 +753,41 @@ extern "C" void *alsaMidiHandler( void *ptr )
#endif
break;
}
- message.bytes.assign( buffer, &buffer[nBytes] );
- // Save last status byte in case of running status.
- if ( message.bytes[0] & 0x80 ) lastStatus = message.bytes[0];
- else if ( lastStatus ) message.bytes.insert( message.bytes.begin(), lastStatus );
- // I found the ALSA sequencer documentation to be very inadequate,
- // especially regarding timestamps. So, I ignore the event
- // timestamp and use system time to determine ours.
+ // The ALSA sequencer has a maximum buffer size for MIDI sysex
+ // events of 256 bytes. If a device sends sysex messages larger
+ // than this, they are segmented into 256 byte chunks. So,
+ // we'll watch for this and concatenate sysex chunks into a
+ // single sysex message if necessary.
+ if ( !continueSysex )
+ message.bytes.assign( buffer, &buffer[nBytes] );
+ else
+ message.bytes.insert( message.bytes.end(), buffer, &buffer[nBytes] );
+
+ if ( ev->type == SND_SEQ_EVENT_SYSEX && message.bytes.back() == 0xF7 )
+ continueSysex = false;
+ else {
+ continueSysex = true;
+ break;
+ }
+
+ // Calculate the time stamp:
message.timeStamp = 0.0;
- (void)gettimeofday(&tv, (struct timezone *)NULL);
- time = (tv.tv_sec * 1000000) + tv.tv_usec;
+
+ // Method 1: Use the system time.
+ //(void)gettimeofday(&tv, (struct timezone *)NULL);
+ //time = (tv.tv_sec * 1000000) + tv.tv_usec;
+
+ // Method 2: Use the ALSA sequencer event time data.
+ // (thanks to Pedro Lopez-Cabanillas!).
+ time = ( ev->time.time.tv_sec * 1000000 ) + ( ev->time.time.tv_nsec/1000 );
lastTime = time;
time -= apiData->lastTime;
apiData->lastTime = lastTime;
if ( data->firstMessage == true )
data->firstMessage = false;
- else {
+ else
message.timeStamp = time * 0.000001;
- }
}
snd_seq_free_event(ev);
@@ -776,6 +806,7 @@ extern "C" void *alsaMidiHandler( void *ptr )
}
}
+ if ( buffer ) free( buffer );
snd_midi_event_free( apiData->coder );
apiData->coder = 0;
return 0;
@@ -785,7 +816,7 @@ void RtMidiIn :: initialize( void )
{
// Set up the ALSA sequencer client.
snd_seq_t *seq;
- int result = snd_seq_open(&seq, "default", SND_SEQ_OPEN_INPUT, 0);
+ int result = snd_seq_open(&seq, "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK);
if ( result < 0 ) {
errorString_ = "RtMidiIn::initialize: error creating ALSA sequencer input client object.";
error( RtError::DRIVER_ERROR );
@@ -800,6 +831,16 @@ void RtMidiIn :: initialize( void )
data->vport = -1;
apiData_ = (void *) data;
inputData_.apiData = (void *) data;
+
+ // Create the input queue
+ data->queue_id = snd_seq_alloc_named_queue(seq, "RtMidi Queue");
+ // Set arbitrary tempo (mm=100) and resolution (240)
+ snd_seq_queue_tempo_t *qtempo;
+ snd_seq_queue_tempo_alloca(&qtempo);
+ snd_seq_queue_tempo_set_tempo(qtempo, 600000);
+ snd_seq_queue_tempo_set_ppq(qtempo, 240);
+ snd_seq_set_queue_tempo(data->seq, data->queue_id, qtempo);
+ snd_seq_drain_output(data->seq);
}
// This function is used to count or get the pinfo structure for a given port number.
@@ -859,9 +900,21 @@ void RtMidiIn :: openPort( unsigned int portNumber )
sender.port = snd_seq_port_info_get_port( pinfo );
receiver.client = snd_seq_client_id( data->seq );
if ( data->vport < 0 ) {
- data->vport = snd_seq_create_simple_port( data->seq, "RtMidi Input",
- SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE,
- SND_SEQ_PORT_TYPE_MIDI_GENERIC );
+ snd_seq_port_info_set_client( pinfo, 0 );
+ snd_seq_port_info_set_port( pinfo, 0 );
+ snd_seq_port_info_set_capability( pinfo,
+ SND_SEQ_PORT_CAP_WRITE |
+ SND_SEQ_PORT_CAP_SUBS_WRITE );
+ snd_seq_port_info_set_type( pinfo,
+ SND_SEQ_PORT_TYPE_MIDI_GENERIC |
+ SND_SEQ_PORT_TYPE_APPLICATION );
+ snd_seq_port_info_set_midi_channels(pinfo, 16);
+ snd_seq_port_info_set_timestamping(pinfo, 1);
+ snd_seq_port_info_set_timestamp_real(pinfo, 1);
+ snd_seq_port_info_set_timestamp_queue(pinfo, data->queue_id);
+ snd_seq_port_info_set_name(pinfo, "RtMidi Input");
+ data->vport = snd_seq_create_port(data->seq, pinfo);
+
if ( data->vport < 0 ) {
errorString_ = "RtMidiIn::openPort: ALSA error creating input port.";
error( RtError::DRIVER_ERROR );
@@ -874,19 +927,20 @@ void RtMidiIn :: openPort( unsigned int portNumber )
snd_seq_port_subscribe_malloc( &data->subscription );
snd_seq_port_subscribe_set_sender(data->subscription, &sender);
snd_seq_port_subscribe_set_dest(data->subscription, &receiver);
- snd_seq_port_subscribe_set_time_update(data->subscription, 1);
- snd_seq_port_subscribe_set_time_real(data->subscription, 1);
if ( snd_seq_subscribe_port(data->seq, data->subscription) ) {
errorString_ = "RtMidiIn::openPort: ALSA error making port connection.";
error( RtError::DRIVER_ERROR );
}
if ( inputData_.doInput == false ) {
+ // Start the input queue
+ snd_seq_start_queue( data->seq, data->queue_id, NULL );
+ snd_seq_drain_output( data->seq );
// Start our MIDI input thread.
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
- pthread_attr_setschedpolicy(&attr, SCHED_RR);
+ pthread_attr_setschedpolicy(&attr, SCHED_OTHER);
inputData_.doInput = true;
int err = pthread_create(&data->thread, &attr, alsaMidiHandler, &inputData_);
@@ -907,9 +961,20 @@ void RtMidiIn :: openVirtualPort()
{
AlsaMidiData *data = static_cast (apiData_);
if ( data->vport < 0 ) {
- data->vport = snd_seq_create_simple_port( data->seq, "RtMidi Input",
- SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE,
- SND_SEQ_PORT_TYPE_MIDI_GENERIC );
+ snd_seq_port_info_t *pinfo;
+ snd_seq_port_info_alloca( &pinfo );
+ snd_seq_port_info_set_capability( pinfo,
+ SND_SEQ_PORT_CAP_WRITE |
+ SND_SEQ_PORT_CAP_SUBS_WRITE );
+ snd_seq_port_info_set_type( pinfo,
+ SND_SEQ_PORT_TYPE_MIDI_GENERIC |
+ SND_SEQ_PORT_TYPE_APPLICATION );
+ snd_seq_port_info_set_midi_channels(pinfo, 16);
+ snd_seq_port_info_set_timestamping(pinfo, 1);
+ snd_seq_port_info_set_timestamp_real(pinfo, 1);
+ snd_seq_port_info_set_timestamp_queue(pinfo, data->queue_id);
+ snd_seq_port_info_set_name(pinfo, "RtMidi Input");
+ data->vport = snd_seq_create_port(data->seq, pinfo);
if ( data->vport < 0 ) {
errorString_ = "RtMidiIn::openVirtualPort: ALSA error creating virtual port.";
@@ -918,11 +983,14 @@ void RtMidiIn :: openVirtualPort()
}
if ( inputData_.doInput == false ) {
+ // Start the input queue
+ snd_seq_start_queue( data->seq, data->queue_id, NULL );
+ snd_seq_drain_output( data->seq );
// Start our MIDI input thread.
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
- pthread_attr_setschedpolicy(&attr, SCHED_RR);
+ pthread_attr_setschedpolicy(&attr, SCHED_OTHER);
inputData_.doInput = true;
int err = pthread_create(&data->thread, &attr, alsaMidiHandler, &inputData_);
@@ -943,6 +1011,9 @@ void RtMidiIn :: closePort( void )
AlsaMidiData *data = static_cast (apiData_);
snd_seq_unsubscribe_port( data->seq, data->subscription );
snd_seq_port_subscribe_free( data->subscription );
+ // Stop the input queue
+ snd_seq_stop_queue( data->seq, data->queue_id, NULL );
+ snd_seq_drain_output( data->seq );
connected_ = false;
}
}
@@ -961,6 +1032,7 @@ RtMidiIn :: ~RtMidiIn()
// Cleanup.
if ( data->vport >= 0 ) snd_seq_delete_port( data->seq, data->vport );
+ snd_seq_free_queue( data->seq, data->queue_id );
snd_seq_close( data->seq );
delete data;
}
@@ -1316,6 +1388,12 @@ extern "C" void *irixMidiHandler( void *ptr )
}
}
else if ( status == 0xF3 ) size = 2;
+ else if ( status == 0xF8 ) {
+ if ( !(data->ignoreFlags & 0x02) ) {
+ // A MIDI timing tick message and we're not ignoring it.
+ size = 1;
+ }
+ }
else if ( status == 0xFE ) { // MIDI active sensing
if ( !(data->ignoreFlags & 0x04) )
size = 1;
@@ -1657,6 +1735,10 @@ static void CALLBACK midiInputCallback( HMIDIOUT hmin,
nBytes = 3;
}
else if ( status == 0xF3 ) nBytes = 2;
+ else if ( status == 0xF8 && (data->ignoreFlags & 0x02) ) {
+ // A MIDI timing tick message and we're ignoring it.
+ return;
+ }
else if ( status == 0xFE && (data->ignoreFlags & 0x04) ) {
// A MIDI active sensing message and we're ignoring it.
return;
diff --git a/src/RtWvIn.cpp b/src/RtWvIn.cpp
index 658f0d2..c3776ef 100644
--- a/src/RtWvIn.cpp
+++ b/src/RtWvIn.cpp
@@ -2,68 +2,63 @@
/*! \class RtWvIn
\brief STK realtime audio (blocking) input class.
- This class provides a simplified interface to
- RtAudio for realtime audio input. It is a
- protected subclass of WvIn.
+ This class provides a simplified interface to RtAudio for realtime
+ audio input. It is a protected subclass of WvIn. Because this
+ class makes use of RtAudio's blocking output routines, its
+ performance is less robust on systems where the audio API is
+ callback-based (Macintosh CoreAudio and Windows ASIO).
- RtWvIn supports multi-channel data in
- interleaved format. It is important to
- distinguish the tick() methods, which return
- samples produced by averaging across sample
- frames, from the tickFrame() methods, which
- return pointers to multi-channel sample frames.
- For single-channel data, these methods return
- equivalent values.
+ RtWvIn supports multi-channel data in interleaved format. It is
+ important to distinguish the tick() methods, which return samples
+ produced by averaging across sample frames, from the tickFrame()
+ methods, which return references or pointers to multi-channel
+ sample frames.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
#include "RtWvIn.h"
-RtWvIn :: RtWvIn(int nChannels, StkFloat sampleRate, int device, int bufferFrames, int nBuffers )
+RtWvIn :: RtWvIn( unsigned int nChannels, StkFloat sampleRate, int device, int bufferFrames, int nBuffers )
+ : stopped_( true ), bufferIndex_( 0 )
{
- channels_ = nChannels;
int size = bufferFrames;
RtAudioFormat format = ( sizeof(StkFloat) == 8 ) ? RTAUDIO_FLOAT64 : RTAUDIO_FLOAT32;
- audio_ = 0;
+ adc_ = 0;
try {
- audio_ = new RtAudio();
+ adc_ = new RtAudio();
}
catch (RtError &error) {
handleError( error.getMessageString(), StkError::AUDIO_SYSTEM );
}
- // Now open a stream and get the buffer pointer.
+ // Allocate the adc and get the buffer pointer.
try {
- audio_->openStream(0, 0, device, channels_, format,
- (int)sampleRate, &size, nBuffers);
- data_ = (StkFloat *) audio_->getStreamBuffer();
+ adc_->openStream( 0, 0, device, (int)nChannels, format,
+ (int)sampleRate, &size, nBuffers );
+ buffer_ = (StkFloat *) adc_->getStreamBuffer();
}
catch (RtError &error) {
handleError( error.getMessageString(), StkError::AUDIO_SYSTEM );
}
- bufferSize_ = size;
- lastOutputs_ = (StkFloat *) new StkFloat[channels_];
- for (unsigned int i=0; istopStream();
- delete audio_;
- data_ = 0; // RtAudio deletes the buffer itself.
+ if ( !stopped_ ) adc_->stopStream();
+ adc_->closeStream();
+ delete adc_;
}
void RtWvIn :: start()
{
if ( stopped_ ) {
- audio_->startStream();
+ adc_->startStream();
stopped_ = false;
}
}
@@ -71,68 +66,29 @@ void RtWvIn :: start()
void RtWvIn :: stop()
{
if ( !stopped_ ) {
- audio_->stopStream();
+ adc_->stopStream();
stopped_ = true;
}
}
-StkFloat RtWvIn :: lastOut(void) const
+void RtWvIn :: computeFrame( void )
{
- return WvIn::lastOut();
-}
+ if ( stopped_ ) this->start();
-StkFloat RtWvIn :: tick(void)
-{
- this->tickFrame();
- return lastOut();
-}
-
-StkFloat *RtWvIn :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return WvIn::tick( vector, vectorSize );
-}
-
-StkFrames& RtWvIn :: tick( StkFrames& frames, unsigned int channel )
-{
- return WvIn::tick( frames, channel );
-}
-
-const StkFloat *RtWvIn :: lastFrame() const
-{
- return lastOutputs_;
-}
-
-const StkFloat *RtWvIn :: tickFrame(void)
-{
- if ( stopped_ )
- this->start();
-
- if (counter_ == 0) {
+ if ( bufferIndex_ == 0) {
try {
- audio_->tickStream();
+ adc_->tickStream();
}
catch (RtError &error) {
handleError( error.getMessageString(), StkError::AUDIO_SYSTEM );
}
}
- long temp = counter_ * channels_;
- for (unsigned int i=0; i= (long) bufferSize_)
- counter_ = 0;
-
- return lastOutputs_;
-}
-
-StkFloat *RtWvIn :: tickFrame(StkFloat *frameVector, unsigned int frames)
-{
- return WvIn::tickFrame( frameVector, frames );
-}
-
-StkFrames& RtWvIn :: tickFrame( StkFrames& frames )
-{
- return WvIn::tickFrame( frames );
+ bufferIndex_++;
+ if ( bufferIndex_ >= bufferFrames_ )
+ bufferIndex_ = 0;
}
diff --git a/src/RtWvOut.cpp b/src/RtWvOut.cpp
index 6dbd3c8..6fb2998 100644
--- a/src/RtWvOut.cpp
+++ b/src/RtWvOut.cpp
@@ -2,35 +2,34 @@
/*! \class RtWvOut
\brief STK realtime audio (blocking) output class.
- This class provides a simplified interface to
- RtAudio for realtime audio output. It is a
- protected subclass of WvOut.
+ This class provides a simplified interface to RtAudio for realtime
+ audio output. It is a subclass of WvOut. Because this class
+ makes use of RtAudio's blocking output routines, its performance
+ is less robust on systems where the audio API is callback-based
+ (Macintosh CoreAudio and Windows ASIO).
- RtWvOut supports multi-channel data in
- interleaved format. It is important to
- distinguish the tick() methods, which output
- single samples to all channels in a sample
- frame, from the tickFrame() method, which
- takes a pointer to multi-channel sample
+ RtWvOut supports multi-channel data in interleaved format. It is
+ important to distinguish the tick() methods, which output single
+ samples to all channels in a sample frame, from the tickFrame()
+ method, which take a pointer or reference to multi-channel sample
frame data.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
#include "RtWvOut.h"
-#include
RtWvOut :: RtWvOut( unsigned int nChannels, StkFloat sampleRate, int device, int bufferFrames, int nBuffers )
+ : stopped_( true ), nChannels_(nChannels), bufferIndex_( 0 ), iBuffer_( 0 )
{
- // We'll let RtAudio deal with channel and srate limitations.
- channels_ = nChannels;
- bufferSize_ = bufferFrames;
+ // We'll let RtAudio deal with channel and sample rate limitations.
+ int size = bufferFrames;
RtAudioFormat format = ( sizeof(StkFloat) == 8 ) ? RTAUDIO_FLOAT64 : RTAUDIO_FLOAT32;
- audio_ = 0;
+ dac_ = 0;
try {
- audio_ = new RtAudio();
+ dac_ = new RtAudio();
}
catch (RtError &error) {
handleError( error.getMessageString(), StkError::AUDIO_SYSTEM );
@@ -38,28 +37,28 @@ RtWvOut :: RtWvOut( unsigned int nChannels, StkFloat sampleRate, int device, int
// Now open a stream and get the buffer pointer.
try {
- audio_->openStream(device, (int)channels_, 0, 0, format,
- (int)sampleRate, &bufferSize_, nBuffers);
- dataPtr_ = (StkFloat *) audio_->getStreamBuffer();
+ dac_->openStream( device, (int)nChannels, 0, 0, format,
+ (int)sampleRate, &size, nBuffers );
+ buffer_ = (StkFloat *) dac_->getStreamBuffer();
}
catch (RtError &error) {
handleError( error.getMessageString(), StkError::AUDIO_SYSTEM );
}
- stopped_ = true;
+ bufferFrames_ = size;
}
RtWvOut :: ~RtWvOut()
{
- if ( !stopped_ )
- audio_->stopStream();
- delete audio_;
+ if ( !stopped_ ) dac_->stopStream();
+ dac_->closeStream();
+ delete dac_;
}
void RtWvOut :: start()
{
if ( stopped_ ) {
- audio_->startStream();
+ dac_->startStream();
stopped_ = false;
}
}
@@ -67,162 +66,80 @@ void RtWvOut :: start()
void RtWvOut :: stop()
{
if ( !stopped_ ) {
- audio_->stopStream();
+ dac_->stopStream();
stopped_ = true;
}
}
-unsigned long RtWvOut :: getFrames( void ) const
+void RtWvOut :: incrementFrame( void )
{
- return totalCount_;
-}
+ frameCounter_++;
+ bufferIndex_++;
-StkFloat RtWvOut :: getTime( void ) const
-{
- return (StkFloat) totalCount_ / Stk::sampleRate();
-}
-
-void RtWvOut :: tick( const StkFloat sample )
-{
- if ( stopped_ )
- start();
-
- StkFloat input = sample;
- this->clipTest( input );
- for ( unsigned int j=0; j= (unsigned int )bufferSize_ ) {
+ if ( bufferIndex_ == bufferFrames_ ) {
try {
- audio_->tickStream();
+ dac_->tickStream();
}
catch (RtError &error) {
handleError( error.getMessageString(), StkError::AUDIO_SYSTEM );
}
- counter_ = 0;
+ bufferIndex_ = 0;
+ iBuffer_ = 0;
}
}
-void RtWvOut :: tick( const StkFloat *vector, unsigned int vectorSize )
+void RtWvOut :: computeSample( const StkFloat sample )
{
- for (unsigned int i=0; iincrementFrame();
}
-void RtWvOut :: tick( const StkFrames& frames, unsigned int channel )
+void RtWvOut :: computeFrames( const StkFrames& frames )
{
- if ( channel == 0 || frames.channels() < channel ) {
- errorString_ << "RtWvOut::tick(): channel argument (" << channel << ") is zero or > channels in StkFrames argument!";
+ if ( stopped_ ) start();
+
+ if ( frames.channels() != nChannels_ ) {
+ errorString_ << "RtWvOut::computeFrames(): incompatible channel value in StkFrames argument!";
handleError( StkError::FUNCTION_ARGUMENT );
}
- if ( stopped_ )
- start();
-
- if ( frames.channels() == 1 ) {
- for ( unsigned int i=0; iclipTest( sample );
- dataPtr_[counter_*channels_+j] = sample;
- }
- counter_++;
- totalCount_++;
-
- if ( counter_ >= (unsigned int)bufferSize_ ) {
- try {
- audio_->tickStream();
- }
- catch (RtError &error) {
- handleError( error.getMessageString(), StkError::AUDIO_SYSTEM );
- }
- counter_ = 0;
- }
- }
-}
-
-void RtWvOut :: tickFrame( const StkFrames& frames )
-{
- if ( channels_ != frames.channels() ) {
- errorString_ << "RtWvOut::tickFrame(): incompatible channel value in StkFrames argument!";
- handleError( StkError::FUNCTION_ARGUMENT );
- }
-
- if ( stopped_ )
- start();
-
unsigned int j;
- StkFloat sample;
- if ( channels_ == 1 || frames.interleaved() ) {
- unsigned long iFrames = 0, iData = counter_;
- for ( unsigned int i=0; iclipTest( sample );
- dataPtr_[iData++] = sample;
- }
- counter_++;
- totalCount_++;
+ if ( nChannels_ == 1 || frames.interleaved() ) {
- if ( counter_ >= (unsigned int)bufferSize_ ) {
- try {
- audio_->tickStream();
- }
- catch (RtError &error) {
- handleError( error.getMessageString(), StkError::AUDIO_SYSTEM );
- }
- counter_ = 0;
+ unsigned int iFrames = 0;
+ for ( unsigned int i=0; iincrementFrame();
}
}
- else {
- unsigned int hop = frames.frames();
- unsigned long iData = counter_;
- for ( unsigned int i=0; iclipTest( sample );
- dataPtr_[iData++] = sample;
- }
- counter_++;
- totalCount_++;
+ else { // non-interleaved frames
- if ( counter_ >= (unsigned int)bufferSize_ ) {
- try {
- audio_->tickStream();
- }
- catch (RtError &error) {
- handleError( error.getMessageString(), StkError::AUDIO_SYSTEM );
- }
- counter_ = 0;
+ unsigned long hop = frames.frames();
+ unsigned int index;
+ for ( unsigned int i=0; iincrementFrame();
}
}
}
+
+
+
diff --git a/src/Sampler.cpp b/src/Sampler.cpp
index 4ce7d2a..1d09934 100644
--- a/src/Sampler.cpp
+++ b/src/Sampler.cpp
@@ -5,7 +5,7 @@
This instrument provides an ADSR envelope, a one-pole filter, and
structures for an arbitrary number of attack and loop waves.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
diff --git a/src/Saxofony.cpp b/src/Saxofony.cpp
index 8943f08..16f50ba 100644
--- a/src/Saxofony.cpp
+++ b/src/Saxofony.cpp
@@ -31,7 +31,7 @@
- Vibrato Gain = 1
- Breath Pressure = 128
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -51,9 +51,7 @@ Saxofony :: Saxofony(StkFloat lowestFrequency)
reedTable_.setOffset( 0.7 );
reedTable_.setSlope( 0.3 );
- // Concatenate the STK rawwave path to the rawwave file
- vibrato_ = new WaveLoop( (Stk::rawwavePath() + "sinewave.raw").c_str(), true );
- vibrato_->setFrequency((StkFloat) 5.735);
+ vibrato_.setFrequency((StkFloat) 5.735);
outputGain_ = 0.3;
noiseGain_ = 0.2;
@@ -62,7 +60,6 @@ Saxofony :: Saxofony(StkFloat lowestFrequency)
Saxofony :: ~Saxofony()
{
- delete vibrato_;
}
void Saxofony :: clear()
@@ -138,7 +135,7 @@ void Saxofony :: noteOff(StkFloat amplitude)
#endif
}
-StkFloat Saxofony :: tick()
+StkFloat Saxofony :: computeSample()
{
StkFloat pressureDiff;
StkFloat breathPressure;
@@ -147,7 +144,7 @@ StkFloat Saxofony :: tick()
// Calculate the breath pressure (envelope + noise + vibrato)
breathPressure = envelope_.tick();
breathPressure += breathPressure * noiseGain_ * noise_.tick();
- breathPressure += breathPressure * vibratoGain_ * vibrato_->tick();
+ breathPressure += breathPressure * vibratoGain_ * vibrato_.tick();
temp = -0.95 * filter_.tick( delays_[0].lastOut() );
lastOutput_ = temp - delays_[1].lastOut();
@@ -159,16 +156,6 @@ StkFloat Saxofony :: tick()
return lastOutput_;
}
-StkFloat *Saxofony :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Instrmnt::tick( vector, vectorSize );
-}
-
-StkFrames& Saxofony :: tick( StkFrames& frames, unsigned int channel )
-{
- return Instrmnt::tick( frames, channel );
-}
-
void Saxofony :: controlChange(int number, StkFloat value)
{
StkFloat norm = value * ONE_OVER_128;
@@ -188,7 +175,7 @@ void Saxofony :: controlChange(int number, StkFloat value)
else if (number == __SK_NoiseLevel_) // 4
noiseGain_ = ( norm * 0.4 );
else if (number == 29) // 29
- vibrato_->setFrequency( norm * 12.0 );
+ vibrato_.setFrequency( norm * 12.0 );
else if (number == __SK_ModWheel_) // 1
vibratoGain_ = ( norm * 0.5 );
else if (number == __SK_AfterTouch_Cont_) // 128
diff --git a/src/Shakers.cpp b/src/Shakers.cpp
index 195c5f2..929b71d 100644
--- a/src/Shakers.cpp
+++ b/src/Shakers.cpp
@@ -53,7 +53,7 @@
/***************************************************/
#include "Stk.h"
-#include
+#include
int my_random(int max) // Return Random Int Between 0 and max
{
@@ -816,7 +816,7 @@ void Shakers :: noteOff(StkFloat amplitude)
const StkFloat MIN_ENERGY = 0.3;
-StkFloat Shakers :: tick()
+StkFloat Shakers :: computeSample()
{
StkFloat data;
StkFloat temp_rand;
@@ -887,16 +887,6 @@ StkFloat Shakers :: tick()
return lastOutput_;
}
-StkFloat *Shakers :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Instrmnt::tick( vector, vectorSize );
-}
-
-StkFrames& Shakers :: tick( StkFrames& frames, unsigned int channel )
-{
- return Instrmnt::tick( frames, channel );
-}
-
void Shakers :: controlChange(int number, StkFloat value)
{
StkFloat norm = value * ONE_OVER_128;
diff --git a/src/Simple.cpp b/src/Simple.cpp
index f226da3..6f1c4f2 100644
--- a/src/Simple.cpp
+++ b/src/Simple.cpp
@@ -13,7 +13,7 @@
- Envelope Rate = 11
- Gain = 128
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -73,7 +73,7 @@ void Simple :: setFrequency(StkFloat frequency)
loop_->setFrequency( frequency );
}
-StkFloat Simple :: tick()
+StkFloat Simple :: computeSample()
{
lastOutput_ = loopGain_ * loop_->tick();
biquad_.tick( noise_.tick() );
@@ -83,16 +83,6 @@ StkFloat Simple :: tick()
return lastOutput_;
}
-StkFloat *Simple :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Instrmnt::tick( vector, vectorSize );
-}
-
-StkFrames& Simple :: tick( StkFrames& frames, unsigned int channel )
-{
- return Instrmnt::tick( frames, channel );
-}
-
void Simple :: controlChange(int number, StkFloat value)
{
StkFloat norm = value * ONE_OVER_128;
diff --git a/src/SineWave.cpp b/src/SineWave.cpp
new file mode 100644
index 0000000..e36c45c
--- /dev/null
+++ b/src/SineWave.cpp
@@ -0,0 +1,103 @@
+/***************************************************/
+/*! \class SineWave
+ \brief STK sinusoid oscillator class.
+
+ This class computes and saves a static sine "table" that can be
+ shared by multiple instances. It has an interface similar to the
+ WaveLoop class but inherits from the Generator class. Output
+ values are computed using linear interpolation.
+
+ The "table" length, set in SineWave.h, is 2048 samples by default.
+
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
+*/
+/***************************************************/
+
+#include "SineWave.h"
+#include
+
+StkFrames SineWave :: table_;
+
+SineWave :: SineWave( void )
+ : time_(0.0), rate_(1.0), phaseOffset_(0.0)
+{
+ if ( table_.empty() ) {
+ table_.resize( TABLE_SIZE + 1, 1 );
+ StkFloat temp = 1.0 / TABLE_SIZE;
+ for ( unsigned long i=0; i<=TABLE_SIZE; i++ )
+ table_[i] = sin( TWO_PI * i * temp );
+ }
+}
+
+SineWave :: ~SineWave()
+{
+}
+
+void SineWave :: reset(void)
+{
+ time_ = 0.0;
+ lastOutput_ = 0;
+}
+
+void SineWave :: setFrequency( StkFloat frequency )
+{
+ // This is a looping frequency.
+ this->setRate( TABLE_SIZE * frequency / Stk::sampleRate() );
+}
+
+void SineWave :: addTime( StkFloat time )
+{
+ // Add an absolute time in samples.
+ time_ += time;
+
+ while ( time_ < 0.0 )
+ time_ += TABLE_SIZE;
+ while ( time_ >= TABLE_SIZE )
+ time_ -= TABLE_SIZE;
+}
+
+void SineWave :: addPhase( StkFloat angle )
+{
+ // Add a time in cycles (one cycle = TABLE_SIZE).
+ time_ += TABLE_SIZE * angle;
+
+ while ( time_ < 0.0 )
+ time_ += TABLE_SIZE;
+ while ( time_ >= TABLE_SIZE )
+ time_ -= TABLE_SIZE;
+}
+
+void SineWave :: addPhaseOffset( StkFloat angle )
+{
+ // Add a phase offset in cycles, where 1.0 = TABLE_SIZE.
+ phaseOffset_ = TABLE_SIZE * angle;
+}
+
+StkFloat SineWave :: computeSample( void )
+{
+ // Check limits of time address ... if necessary, recalculate modulo
+ // TABLE_SIZE.
+ while ( time_ < 0.0 )
+ time_ += TABLE_SIZE;
+ while ( time_ >= TABLE_SIZE )
+ time_ -= TABLE_SIZE;
+
+ StkFloat tyme;
+ if ( phaseOffset_ ) {
+ tyme = time_ + phaseOffset_;
+ while ( tyme < 0.0 )
+ tyme += TABLE_SIZE;
+ while ( tyme >= TABLE_SIZE )
+ tyme -= TABLE_SIZE;
+ }
+ else {
+ tyme = time_;
+ }
+
+ lastOutput_ = table_.interpolate( tyme );
+
+ // Increment time, which can be negative.
+ time_ += rate_;
+
+ return lastOutput_;
+}
diff --git a/src/SingWave.cpp b/src/SingWave.cpp
index 8f382f1..06fba0b 100644
--- a/src/SingWave.cpp
+++ b/src/SingWave.cpp
@@ -9,7 +9,7 @@
from pitch shifting. It will be used as an
excitation source for other instruments.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -22,21 +22,19 @@ SingWave :: SingWave( std::string fileName, bool raw)
rate_ = 1.0;
sweepRate_ = 0.001;
- modulator_ = new Modulate();
- modulator_->setVibratoRate( 6.0 );
- modulator_->setVibratoGain( 0.04 );
- modulator_->setRandomGain( 0.005 );
+ modulator_.setVibratoRate( 6.0 );
+ modulator_.setVibratoGain( 0.04 );
+ modulator_.setRandomGain( 0.005 );
this->setFrequency( 75.0 );
pitchEnvelope_.setRate( 1.0 );
- this->tick();
- this->tick();
+ this->computeSample();
+ this->computeSample();
pitchEnvelope_.setRate( sweepRate_ * rate_ );
}
SingWave :: ~SingWave()
{
delete wave_;
- delete modulator_;
}
void SingWave :: reset()
@@ -67,17 +65,17 @@ void SingWave :: setFrequency(StkFloat frequency)
void SingWave :: setVibratoRate(StkFloat rate)
{
- modulator_->setVibratoRate( rate );
+ modulator_.setVibratoRate( rate );
}
void SingWave :: setVibratoGain(StkFloat gain)
{
- modulator_->setVibratoGain(gain);
+ modulator_.setVibratoGain(gain);
}
void SingWave :: setRandomGain(StkFloat gain)
{
- modulator_->setRandomGain(gain);
+ modulator_.setRandomGain(gain);
}
void SingWave :: setSweepRate(StkFloat rate)
@@ -105,25 +103,15 @@ void SingWave :: noteOff()
envelope_.keyOff();
}
-StkFloat SingWave :: tick()
+StkFloat SingWave :: computeSample()
{
// Set the wave rate.
StkFloat newRate = pitchEnvelope_.tick();
- newRate += newRate * modulator_->tick();
+ newRate += newRate * modulator_.tick();
wave_->setRate( newRate );
lastOutput_ = wave_->tick();
lastOutput_ *= envelope_.tick();
-
+
return lastOutput_;
}
-
-StkFloat *SingWave :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Generator::tick( vector, vectorSize );
-}
-
-StkFrames& SingWave :: tick( StkFrames& frames, unsigned int channel )
-{
- return Generator::tick( frames, channel );
-}
diff --git a/src/Sitar.cpp b/src/Sitar.cpp
index b808b31..967e85b 100644
--- a/src/Sitar.cpp
+++ b/src/Sitar.cpp
@@ -13,7 +13,7 @@
Stanford, bearing the names of Karplus and/or
Strong.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -98,7 +98,7 @@ void Sitar :: noteOff(StkFloat amplitude)
#endif
}
-StkFloat Sitar :: tick()
+StkFloat Sitar :: computeSample()
{
if ( fabs(targetDelay_ - delay_) > 0.001 ) {
if ( targetDelay_ < delay_ )
@@ -113,13 +113,3 @@ StkFloat Sitar :: tick()
return lastOutput_;
}
-
-StkFloat *Sitar :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Instrmnt::tick( vector, vectorSize );
-}
-
-StkFrames& Sitar :: tick( StkFrames& frames, unsigned int channel )
-{
- return Instrmnt::tick( frames, channel );
-}
diff --git a/src/Skini.cpp b/src/Skini.cpp
index 4234d48..0bcf320 100644
--- a/src/Skini.cpp
+++ b/src/Skini.cpp
@@ -19,7 +19,7 @@
See also SKINI.txt.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -173,6 +173,11 @@ long Skini :: parseString( std::string& line, Message& message )
case SK_STR: // Must be the last field.
message.remainder = tokens[iValue+3];
return message.type;
+
+ default: // MIDI extension message
+ message.intValues[iValue] = dataType;
+ message.floatValues[iValue] = (StkFloat) message.intValues[iValue];
+ iValue--;
}
if ( ++iValue == 1 )
diff --git a/src/Socket.cpp b/src/Socket.cpp
index 863f85f..6aa1ae6 100644
--- a/src/Socket.cpp
+++ b/src/Socket.cpp
@@ -1,171 +1,46 @@
/***************************************************/
/*! \class Socket
- \brief STK TCP socket client/server class.
+ \brief STK internet socket abstract base class.
- This class provides a uniform cross-platform
- TCP socket client or socket server interface.
- Methods are provided for reading or writing
- data buffers to/from connections. This class
- also provides a number of static functions for
- use with external socket descriptors.
+ This class provides common functionality for TCP and UDP internet
+ socket server and client subclasses.
- The user is responsible for checking the values
- returned by the read/write methods. Values
- less than or equal to zero indicate a closed
- or lost connection or the occurence of an error.
-
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
#include "Socket.h"
-#include
-#include
-#if (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__))
-
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
-
-#elif defined(__OS_WINDOWS__)
-
- #include
-
-#endif
-
-Socket :: Socket( int port )
+Socket :: Socket()
{
soket_ = -1;
- server_ = true;
- port_ = port;
-
- // Create a socket server.
-#if defined(__OS_WINDOWS__) // windoze-only stuff
- WSADATA wsaData;
- WORD wVersionRequested = MAKEWORD(1,1);
-
- WSAStartup(wVersionRequested, &wsaData);
- if (wsaData.wVersion != wVersionRequested) {
- errorString_ << "Socket: Incompatible Windows socket library version!";
- handleError( StkError::PROCESS_SOCKET );
- }
-#endif
-
- // Create the server-side socket
- soket_ = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- if (soket_ < 0) {
- errorString_ << "Socket: Couldn't create socket server!";
- handleError( StkError::PROCESS_SOCKET );
- }
-
- int flag = 1;
- int result = setsockopt( soket_, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int) );
- if (result < 0) {
- errorString_ << "Socket: Error setting socket options!";
- handleError( StkError::PROCESS_SOCKET );
- }
-
- struct sockaddr_in mysocket;
- mysocket.sin_family=AF_INET;
- mysocket.sin_addr.s_addr=INADDR_ANY;
- mysocket.sin_port=htons( port );
-
- // Bind socket to the appropriate port and interface (INADDR_ANY)
- if ( bind(soket_, (struct sockaddr *)&mysocket, sizeof(mysocket)) < 0 ) {
- errorString_ << "Socket: Couldn't bind socket!";
- handleError( StkError::PROCESS_SOCKET );
- }
-
- // Listen for incoming connection(s)
- if ( listen(soket_, 1) < 0 ) {
- errorString_ << "Socket: Couldn't start server listening!";
- handleError( StkError::PROCESS_SOCKET );
- }
-}
-
-Socket :: Socket(int port, const char *hostname )
-{
- soket_ = -1;
- server_ = false;
- port_ = port;
-
-#if defined(__OS_WINDOWS__) // windoze-only stuff
- WSADATA wsaData;
- WORD wVersionRequested = MAKEWORD(1,1);
-
- WSAStartup(wVersionRequested, &wsaData);
- if (wsaData.wVersion != wVersionRequested) {
- errorString_ << "Socket: Incompatible Windows socket library version!";
- handleError( StkError::PROCESS_SOCKET );
- }
-#endif
-
- // Create a socket client connection.
- connect( port, hostname );
+ port_ = -1;
}
Socket :: ~Socket()
{
-#if (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__))
+ this->close( soket_ );
- ::close( soket_ );
+#if defined(__OS_WINDOWS__)
-#elif defined(__OS_WINDOWS__)
-
- ::closesocket( soket_ );
WSACleanup();
#endif
}
-int Socket :: connect( int port, const char *hostname )
+void Socket :: close( int socket )
{
- // This method is for client connections only!
- if ( server_ == true ) return -1;
+ if ( !isValid( socket ) ) return;
- // Close an existing connection if it exists.
- if ( isValid( soket_ ) ) this->close();
+#if (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__))
- // Create the client-side socket
- soket_ = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- if (soket_ < 0) {
- errorString_ << "Socket: Couldn't create socket client!";
- handleError( StkError::PROCESS_SOCKET );
- }
+ ::close( socket );
- int flag = 1;
- int result = setsockopt( soket_, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int) );
- if (result < 0) {
- errorString_ << "Socket: Error setting socket options!";
- handleError( StkError::PROCESS_SOCKET );
- }
+#elif defined(__OS_WINDOWS__)
- struct hostent *hostp;
- if ( (hostp = gethostbyname(hostname)) == 0 ) {
- errorString_ << "Socket: unknown host (" << hostname << ")!";
- handleError( StkError::PROCESS_SOCKET_IPADDR );
- }
+ ::closesocket( socket );
- // Fill in the address structure
- struct sockaddr_in server_address;
- server_address.sin_family = AF_INET;
- memcpy((void *)&server_address.sin_addr, hostp->h_addr, hostp->h_length);
- server_address.sin_port = htons(port);
-
- // Connect to the server
- if ( ::connect(soket_, (struct sockaddr *)&server_address,
- sizeof(server_address) ) < 0) {
- errorString_ << "Socket: Couldn't connect to socket server!";
- handleError( StkError::PROCESS_SOCKET );
- }
-
- return soket_;
+#endif
}
int Socket :: id( void ) const
@@ -178,14 +53,6 @@ int Socket :: port( void ) const
return port_;
}
-int Socket :: accept( void )
-{
- if ( server_ )
- return ::accept( soket_, NULL, NULL );
- else
- return -1;
-}
-
bool Socket :: isValid( int socket )
{
return socket != -1;
@@ -209,48 +76,15 @@ void Socket :: setBlocking( int socket, bool enable )
#endif
}
-void Socket :: close( void )
-{
- if ( !isValid( soket_ ) ) return;
- this->close( soket_ );
- soket_ = -1;
-}
-
-void Socket :: close( int socket )
-{
- if ( !isValid( socket ) ) return;
-
-#if (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__))
-
- ::close( socket );
-
-#elif defined(__OS_WINDOWS__)
-
- ::closesocket( socket );
-
-#endif
-}
-
-int Socket :: writeBuffer(const void *buffer, long bufferSize, int flags )
-{
- if ( !isValid( soket_ ) ) return -1;
- return send( soket_, (const char *)buffer, bufferSize, flags );
-}
-
int Socket :: writeBuffer(int socket, const void *buffer, long bufferSize, int flags )
{
if ( !isValid( socket ) ) return -1;
return send( socket, (const char *)buffer, bufferSize, flags );
}
-int Socket :: readBuffer(void *buffer, long bufferSize, int flags )
-{
- if ( !isValid( soket_ ) ) return -1;
- return recv( soket_, (char *)buffer, bufferSize, flags );
-}
-
int Socket :: readBuffer(int socket, void *buffer, long bufferSize, int flags )
{
if ( !isValid( socket ) ) return -1;
return recv( socket, (char *)buffer, bufferSize, flags );
}
+
diff --git a/src/StifKarp.cpp b/src/StifKarp.cpp
index c860b16..4fa19b1 100644
--- a/src/StifKarp.cpp
+++ b/src/StifKarp.cpp
@@ -17,13 +17,13 @@
- String Sustain = 11
- String Stretch = 1
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
#include "StifKarp.h"
#include "SKINI.msg"
-#include
+#include
StifKarp :: StifKarp(StkFloat lowestFrequency)
{
@@ -180,7 +180,7 @@ void StifKarp :: noteOff(StkFloat amplitude)
#endif
}
-StkFloat StifKarp :: tick()
+StkFloat StifKarp :: computeSample()
{
StkFloat temp = delayLine_.lastOut() * loopGain_;
@@ -196,16 +196,6 @@ StkFloat StifKarp :: tick()
return lastOutput_;
}
-StkFloat *StifKarp :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Instrmnt::tick( vector, vectorSize );
-}
-
-StkFrames& StifKarp :: tick( StkFrames& frames, unsigned int channel )
-{
- return Instrmnt::tick( frames, channel );
-}
-
void StifKarp :: controlChange(int number, StkFloat value)
{
StkFloat norm = value * ONE_OVER_128;
diff --git a/src/Stk.cpp b/src/Stk.cpp
index 8461210..e718a6d 100644
--- a/src/Stk.cpp
+++ b/src/Stk.cpp
@@ -8,7 +8,7 @@
provides error handling and byte-swapping
functions.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -18,9 +18,12 @@ StkFloat Stk :: srate_ = (StkFloat) SRATE;
std::string Stk :: rawwavepath_ = RAWWAVE_PATH;
const Stk::StkFormat Stk :: STK_SINT8 = 0x1;
const Stk::StkFormat Stk :: STK_SINT16 = 0x2;
+const Stk::StkFormat Stk :: STK_SINT24 = 0x4;
const Stk::StkFormat Stk :: STK_SINT32 = 0x8;
const Stk::StkFormat Stk :: STK_FLOAT32 = 0x10;
const Stk::StkFormat Stk :: STK_FLOAT64 = 0x20;
+bool Stk :: showWarnings_ = false;
+bool Stk :: printErrors_ = true;
Stk :: Stk(void)
{
@@ -123,60 +126,186 @@ void Stk :: handleError( const char *message, StkError::Type type )
void Stk :: handleError( std::string message, StkError::Type type )
{
- if (type == StkError::WARNING || type == StkError::STATUS )
+ if ( type == StkError::WARNING || type == StkError::STATUS ) {
+ if ( !showWarnings_ ) return;
std::cerr << '\n' << message << '\n' << std::endl;
+ }
else if (type == StkError::DEBUG_WARNING) {
#if defined(_STK_DEBUG_)
std::cerr << '\n' << message << '\n' << std::endl;
#endif
}
else {
- // Print error message before throwing.
- std::cerr << '\n' << message << '\n' << std::endl;
+ if ( printErrors_ ) {
+ // Print error message before throwing.
+ std::cerr << '\n' << message << '\n' << std::endl;
+ }
throw StkError(message, type);
}
}
+//
+// StkFrames definitions
+//
+
StkFrames :: StkFrames( unsigned int nFrames, unsigned int nChannels, bool interleaved )
: nFrames_( nFrames ), nChannels_( nChannels ), interleaved_( interleaved )
{
- if ( nChannels == 0 ) {
- std::string message = "StkFrames::StkFrames: nChannels argument should be 1 or greater (even if nFrames = 0) ... correcting to one channel!";
- Stk::handleError( message, StkError::WARNING );
- nChannels_ = 1;
- }
-
size_ = nFrames_ * nChannels_;
- if ( size_ > 0 ) data_.resize( size_, 0.0 );
+ bufferSize_ = size_;
+
+ if ( size_ > 0 ) {
+ data_ = (StkFloat *) calloc( size_, sizeof( StkFloat ) );
+#if defined(_STK_DEBUG_)
+ if ( data_ == NULL ) {
+ std::string error = "StkFrames: memory allocation error in constructor!";
+ Stk::handleError( error, StkError::MEMORY_ALLOCATION );
+ }
+#endif
+ }
+ else data_ = 0;
+
+ dataRate_ = Stk::sampleRate();
}
StkFrames :: StkFrames( const StkFloat& value, unsigned int nFrames, unsigned int nChannels, bool interleaved )
: nFrames_( nFrames ), nChannels_( nChannels ), interleaved_( interleaved )
{
- if ( nChannels == 0 ) {
- std::string message = "StkFrames::StkFrames: nChannels argument should be 1 or greater (even if nFrames = 0) ... correcting to one channel!";
- Stk::handleError( message, StkError::WARNING );
- nChannels_ = 1;
- }
-
size_ = nFrames_ * nChannels_;
- if ( size_ > 0 ) data_.resize( size_, value );
+ bufferSize_ = size_;
+ if ( size_ > 0 ) {
+ data_ = (StkFloat *) malloc( size_ * sizeof( StkFloat ) );
+#if defined(_STK_DEBUG_)
+ if ( data_ == NULL ) {
+ std::string error = "StkFrames: memory allocation error in constructor!";
+ Stk::handleError( error, StkError::MEMORY_ALLOCATION );
+ }
+#endif
+ for ( long i=0; i<(long)size_; i++ ) data_[i] = value;
+ }
+ else data_ = 0;
+
+ dataRate_ = Stk::sampleRate();
}
-void StkFrames :: resize( unsigned int nFrames, unsigned int nChannels, StkFloat value )
+StkFrames :: ~StkFrames()
+{
+ if ( data_ ) free( data_ );
+}
+
+bool StkFrames :: empty() const
+{
+ if ( size_ > 0 ) return false;
+ else return true;
+}
+
+void StkFrames :: resize( size_t nFrames, unsigned int nChannels )
{
nFrames_ = nFrames;
nChannels_ = nChannels;
- if ( nChannels == 0 ) {
- std::string message = "StkFrames::resize(): nChannels argument should be 1 or greater (even if nFrames = 0) ... correcting to one channel!";
- Stk::handleError( message, StkError::WARNING );
- nChannels_ = 1;
- }
-
- size_t newSize = nFrames_ * nChannels_;
- if ( size_ != newSize ) {
- size_ = newSize;
- data_.resize( size_, value );
+ size_ = nFrames_ * nChannels_;
+ if ( size_ > bufferSize_ ) {
+ if ( data_ ) free( data_ );
+ data_ = (StkFloat *) malloc( size_ * sizeof( StkFloat ) );
+#if defined(_STK_DEBUG_)
+ if ( data_ == NULL ) {
+ std::string error = "StkFrames::resize: memory allocation error!";
+ Stk::handleError( error, StkError::MEMORY_ALLOCATION );
+ }
+#endif
+ bufferSize_ = size_;
}
}
+
+void StkFrames :: resize( size_t nFrames, unsigned int nChannels, StkFloat value )
+{
+ this->resize( nFrames, nChannels );
+
+ for ( size_t i=0; i= size_ ) {
+ std::ostringstream error;
+ error << "StkFrames::operator[]: invalid index (" << n << ") value!";
+ Stk::handleError( error.str(), StkError::MEMORY_ACCESS );
+ }
+#endif
+
+ return data_[n];
+}
+
+StkFloat StkFrames :: operator[] ( size_t n ) const
+{
+#if defined(_STK_DEBUG_)
+ if ( n >= size_ ) {
+ std::ostringstream error;
+ error << "StkFrames::operator[]: invalid index (" << n << ") value!";
+ Stk::handleError( error.str(), StkError::MEMORY_ACCESS );
+ }
+#endif
+
+ return data_[n];
+}
+
+StkFloat& StkFrames :: operator() ( size_t frame, unsigned int channel )
+{
+#if defined(_STK_DEBUG_)
+ if ( frame >= nFrames_ || channel >= nChannels_ ) {
+ std::ostringstream error;
+ error << "StkFrames::operator(): invalid frame (" << frame << ") or channel (" << channel << ") value!";
+ Stk::handleError( error.str(), StkError::MEMORY_ACCESS );
+ }
+#endif
+
+ if ( interleaved_ )
+ return data_[ frame * nChannels_ + channel ];
+ else
+ return data_[ channel * nFrames_ + frame ];
+}
+
+StkFloat StkFrames :: operator() ( size_t frame, unsigned int channel ) const
+{
+#if defined(_STK_DEBUG_)
+ if ( frame >= nFrames_ || channel >= nChannels_ ) {
+ std::ostringstream error;
+ error << "StkFrames::operator(): invalid frame (" << frame << ") or channel (" << channel << ") value!";
+ Stk::handleError( error.str(), StkError::MEMORY_ACCESS );
+ }
+#endif
+
+ if ( interleaved_ )
+ return data_[ frame * nChannels_ + channel ];
+ else
+ return data_[ channel * nFrames_ + frame ];
+}
+
+StkFloat StkFrames :: interpolate( StkFloat frame, unsigned int channel ) const
+{
+#if defined(_STK_DEBUG_)
+ if ( frame >= (StkFloat) nFrames_ || channel >= nChannels_ ) {
+ std::ostringstream error;
+ error << "StkFrames::interpolate: invalid frame (" << frame << ") or channel (" << channel << ") value!";
+ Stk::handleError( error.str(), StkError::MEMORY_ACCESS );
+ }
+#endif
+
+ size_t iIndex = ( size_t ) frame; // integer part of index
+ StkFloat output, alpha = frame - (StkFloat) iIndex; // fractional part of index
+
+ if ( interleaved_ ) {
+ iIndex = iIndex * nChannels_ + channel;
+ output = data_[ iIndex ];
+ output += ( alpha * ( data_[ iIndex + nChannels_ ] - output ) );
+ }
+ else {
+ iIndex += channel * nFrames_;
+ output = data_[ iIndex ];
+ output += ( alpha * ( data_[ iIndex++ ] - output ) );
+ }
+
+ return output;
+}
diff --git a/src/SubNoise.cpp b/src/SubNoise.cpp
index 5400eb7..54a14f9 100644
--- a/src/SubNoise.cpp
+++ b/src/SubNoise.cpp
@@ -6,48 +6,42 @@
using the C rand() function. The quality of the
rand() function varies from one OS to another.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
#include "SubNoise.h"
-SubNoise :: SubNoise(int subRate) : Noise()
-{
- rate_ = subRate;
+SubNoise :: SubNoise( int subRate ) : Noise()
+{
+ if ( subRate <= 0 ) {
+ errorString_ << "SubNoise: subRate argument is negative ... setting to 16!";
+ handleError( StkError::WARNING );
+ rate_ = 16;
+ }
+
+ // Precompute an output.
+ Noise::computeSample();
counter_ = rate_;
}
+
SubNoise :: ~SubNoise()
{
}
-int SubNoise :: subRate(void) const
+void SubNoise :: setRate( int subRate )
{
- return rate_;
-}
-
-void SubNoise :: setRate(int subRate)
-{
- if (subRate > 0)
+ if ( subRate > 0 )
rate_ = subRate;
}
-StkFloat SubNoise :: tick()
+StkFloat SubNoise :: computeSample()
{
- if ( ++counter_ > rate_ ) {
- Noise::tick();
- counter_ = 1;
+ if ( counter_-- == 0 ) {
+ Noise::computeSample();
+ counter_ = rate_;
}
return lastOutput_;
}
-StkFloat *SubNoise :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Generator::tick( vector, vectorSize );
-}
-
-StkFrames& SubNoise :: tick( StkFrames& frames, unsigned int channel )
-{
- return Generator::tick( frames, channel );
-}
diff --git a/src/Table.cpp b/src/Table.cpp
deleted file mode 100644
index 6982cd3..0000000
--- a/src/Table.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-/***************************************************/
-/*! \class Table
- \brief STK table lookup class.
-
- This class loads a table of floating-point
- doubles, which are assumed to be in big-endian
- format. Linear interpolation is performed for
- fractional lookup indexes.
-
- An StkError will be thrown if the table file
- is not found.
-
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
-*/
-/***************************************************/
-
-#include "Table.h"
-#include
-#include
-
-Table :: Table( std::string fileName)
-{
- // Use the system call "stat" to determine the file length
- struct stat filestat;
- if ( stat( fileName.c_str(), &filestat ) == -1 ) {
- errorString_ << "Table: Couldn't stat or find file (" << fileName << ").";
- handleError( StkError::FILE_NOT_FOUND );
- }
- length_ = (long) filestat.st_size / 8; // length in 8-byte samples
-
- // Open the file and read samples into data[]
- FILE *fd;
- fd = fopen(fileName.c_str(),"rb");
- if (!fd) {
- errorString_ << "Table::Table: unable to open or find file (" << fileName << ")";
- handleError( StkError::FILE_NOT_FOUND );
- }
-
- data_.resize( length_, 0.0 );
-
- // Read samples into data
- long i = 0;
- double temp;
- while ( fread( &temp, 8, 1, fd ) ) {
-#ifdef __LITTLE_ENDIAN__
- swap64( (unsigned char *)&temp );
-#endif
- data_[i++] = (StkFloat) temp;
- }
- fclose(fd);
-
- lastOutput_ = 0.0;
-}
-
-Table :: ~Table()
-{
-}
-
-long Table :: getLength() const
-{
- return length_;
-}
-
-StkFloat Table :: tick(StkFloat index)
-{
- StkFloat alpha;
- long temp;
-
- if ( index > length_-1 ) {
- errorString_ << "Table: Index (" << index << ") exceeds table length ... sticking at end!\n";
- handleError( StkError::WARNING );
- index = length_-1;
- }
- else if (index < 0.0) {
- errorString_ << "Table: Index (" << index << ") is less than zero ... setting to zero!\n";
- handleError( StkError::WARNING );
- index = 0.0;
- }
-
- // Index in range 0 to length-1
- temp = (long) index; // Integer part of index
- alpha = index - (StkFloat) temp; // Fractional part of index
- if (alpha > 0.0) { // Do linear interpolation
- lastOutput_ = data_[temp];
- lastOutput_ += (alpha*(data_[temp+1] - lastOutput_));
- }
- else lastOutput_ = data_[temp];
-
- return lastOutput_;
-}
-
-StkFloat *Table :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Function::tick( vector, vectorSize );
-}
-
-StkFrames& Table :: tick( StkFrames& frames, unsigned int channel )
-{
- return Function::tick( frames, channel );
-}
diff --git a/src/TcpClient.cpp b/src/TcpClient.cpp
new file mode 100644
index 0000000..6dd1af3
--- /dev/null
+++ b/src/TcpClient.cpp
@@ -0,0 +1,100 @@
+/***************************************************/
+/*! \class TcpClient
+ \brief STK TCP socket client class.
+
+ This class provides a uniform cross-platform TCP socket client
+ interface. Methods are provided for reading or writing data
+ buffers to/from connections.
+
+ TCP sockets are reliable and connection-oriented. A TCP socket
+ client must be connected to a TCP server before data can be sent
+ or received. Data delivery is guaranteed in order, without loss,
+ error, or duplication. That said, TCP transmissions tend to be
+ slower than those using the UDP protocol and data sent with
+ multiple \e write() calls can be arbitrarily combined by the
+ underlying system.
+
+ The user is responsible for checking the values
+ returned by the read/write methods. Values
+ less than or equal to zero indicate a closed
+ or lost connection or the occurence of an error.
+
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
+*/
+/***************************************************/
+
+#include "TcpClient.h"
+
+TcpClient :: TcpClient(int port, std::string hostname )
+{
+#if defined(__OS_WINDOWS__) // windoze-only stuff
+ WSADATA wsaData;
+ WORD wVersionRequested = MAKEWORD(1,1);
+
+ WSAStartup(wVersionRequested, &wsaData);
+ if (wsaData.wVersion != wVersionRequested) {
+ errorString_ << "TcpClient: Incompatible Windows socket library version!";
+ handleError( StkError::PROCESS_SOCKET );
+ }
+#endif
+
+ // Create a socket client connection.
+ connect( port, hostname );
+}
+
+TcpClient :: ~TcpClient()
+{
+}
+
+int TcpClient :: connect( int port, std::string hostname )
+{
+ // Close any existing connections.
+ this->close( soket_ );
+
+ // Create the client-side socket
+ soket_ = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (soket_ < 0) {
+ errorString_ << "TcpClient: Couldn't create socket client!";
+ handleError( StkError::PROCESS_SOCKET );
+ }
+
+ int flag = 1;
+ int result = setsockopt( soket_, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int) );
+ if (result < 0) {
+ errorString_ << "TcpClient: Error setting socket options!";
+ handleError( StkError::PROCESS_SOCKET );
+ }
+
+ struct hostent *hostp;
+ if ( (hostp = gethostbyname( hostname.c_str() )) == 0 ) {
+ errorString_ << "TcpClient: unknown host (" << hostname << ")!";
+ handleError( StkError::PROCESS_SOCKET_IPADDR );
+ }
+
+ // Fill in the address structure
+ struct sockaddr_in server_address;
+ server_address.sin_family = AF_INET;
+ memcpy((void *)&server_address.sin_addr, hostp->h_addr, hostp->h_length);
+ server_address.sin_port = htons(port);
+
+ // Connect to the server
+ if ( ::connect(soket_, (struct sockaddr *)&server_address,
+ sizeof(server_address) ) < 0) {
+ errorString_ << "TcpClient: Couldn't connect to socket server!";
+ handleError( StkError::PROCESS_SOCKET );
+ }
+
+ return soket_;
+}
+
+int TcpClient :: writeBuffer(const void *buffer, long bufferSize, int flags )
+{
+ if ( !isValid( soket_ ) ) return -1;
+ return send( soket_, (const char *)buffer, bufferSize, flags );
+}
+
+int TcpClient :: readBuffer(void *buffer, long bufferSize, int flags )
+{
+ if ( !isValid( soket_ ) ) return -1;
+ return recv( soket_, (char *)buffer, bufferSize, flags );
+}
diff --git a/src/TcpServer.cpp b/src/TcpServer.cpp
new file mode 100644
index 0000000..b5dadd0
--- /dev/null
+++ b/src/TcpServer.cpp
@@ -0,0 +1,95 @@
+/***************************************************/
+/*! \class TcpServer
+ \brief STK TCP socket server class.
+
+ This class provides a uniform cross-platform TCP socket server
+ interface. Methods are provided for reading or writing data
+ buffers to/from connections.
+
+ TCP sockets are reliable and connection-oriented. A TCP socket
+ server must accept a connection from a TCP client before data can
+ be sent or received. Data delivery is guaranteed in order,
+ without loss, error, or duplication. That said, TCP transmissions
+ tend to be slower than those using the UDP protocol and data sent
+ with multiple \e write() calls can be arbitrarily combined by the
+ underlying system.
+
+ The user is responsible for checking the values
+ returned by the read/write methods. Values
+ less than or equal to zero indicate a closed
+ or lost connection or the occurence of an error.
+
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
+*/
+/***************************************************/
+
+#include "TcpServer.h"
+
+TcpServer :: TcpServer( int port )
+{
+ // Create a socket server.
+#if defined(__OS_WINDOWS__) // windoze-only stuff
+ WSADATA wsaData;
+ WORD wVersionRequested = MAKEWORD(1,1);
+
+ WSAStartup(wVersionRequested, &wsaData);
+ if (wsaData.wVersion != wVersionRequested) {
+ errorString_ << "TcpServer: Incompatible Windows socket library version!";
+ handleError( StkError::PROCESS_SOCKET );
+ }
+#endif
+
+ // Create the server-side socket
+ soket_ = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (soket_ < 0) {
+ errorString_ << "TcpServer: Couldn't create socket server!";
+ handleError( StkError::PROCESS_SOCKET );
+ }
+
+ int flag = 1;
+ int result = setsockopt( soket_, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int) );
+ if (result < 0) {
+ errorString_ << "TcpServer: Error setting socket options!";
+ handleError( StkError::PROCESS_SOCKET );
+ }
+
+ struct sockaddr_in address;
+ address.sin_family = AF_INET;
+ address.sin_addr.s_addr = INADDR_ANY;
+ address.sin_port = htons( port );
+
+ // Bind socket to the appropriate port and interface (INADDR_ANY)
+ if ( bind( soket_, (struct sockaddr *)&address, sizeof(address) ) < 0 ) {
+ errorString_ << "TcpServer: Couldn't bind socket!";
+ handleError( StkError::PROCESS_SOCKET );
+ }
+
+ // Listen for incoming connection(s)
+ if ( listen( soket_, 1 ) < 0 ) {
+ errorString_ << "TcpServer: Couldn't start server listening!";
+ handleError( StkError::PROCESS_SOCKET );
+ }
+
+ port_ = port;
+}
+
+TcpServer :: ~TcpServer()
+{
+}
+
+int TcpServer :: accept( void )
+{
+ return ::accept( soket_, NULL, NULL );
+}
+
+int TcpServer :: writeBuffer(const void *buffer, long bufferSize, int flags )
+{
+ if ( !isValid( soket_ ) ) return -1;
+ return send( soket_, (const char *)buffer, bufferSize, flags );
+}
+
+int TcpServer :: readBuffer(void *buffer, long bufferSize, int flags )
+{
+ if ( !isValid( soket_ ) ) return -1;
+ return recv( soket_, (char *)buffer, bufferSize, flags );
+}
diff --git a/src/TcpWvIn.cpp b/src/TcpWvIn.cpp
deleted file mode 100644
index adfc2db..0000000
--- a/src/TcpWvIn.cpp
+++ /dev/null
@@ -1,336 +0,0 @@
-/***************************************************/
-/*! \class TcpWvIn
- \brief STK internet streaming input class.
-
- This protected Wvin subclass can read streamed
- data over a network via a TCP socket connection.
- The data is assumed in big-endian, or network,
- byte order.
-
- TcpWvIn supports multi-channel data in
- interleaved format. It is important to
- distinguish the tick() methods, which return
- samples produced by averaging across sample
- frames, from the tickFrame() methods, which
- return pointers to multi-channel sample frames.
- For single-channel data, these methods return
- equivalent values.
-
- This class starts a socket server, which waits
- for a single remote connection. The default
- data type for the incoming stream is signed
- 16-bit integers, though any of the defined
- StkFormats are permissible.
-
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
-*/
-/***************************************************/
-
-#include "TcpWvIn.h"
-
-const int N_BUFFERS = 10;
-
-// Do OS dependent includes
-#if (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__))
- #include
- #include
- #include
-#endif
-
-extern "C" THREAD_RETURN THREAD_TYPE inputThread(void * ptr)
-{
- thread_info *info = (thread_info *)ptr;
-
- while ( !info->finished ) {
- ((TcpWvIn *) info->object)->receive();
- }
-
- return 0;
-}
-
-TcpWvIn :: TcpWvIn( int port )
-{
- init( port );
-}
-
-TcpWvIn :: ~TcpWvIn()
-{
- // Close down the thread.
- connected_ = false;
- threadInfo_.finished = true;
- delete thread_;
-
- delete soket_;
-
- if (buffer_)
- delete [] buffer_;
-}
-
-void TcpWvIn :: init( int port )
-{
- buffer_ = 0;
- bufferBytes_ = 0;
- connected_ = false;
-
- // Start socket server ... an error can be thrown from the Socket class.
- soket_ = new Socket( port );
-
- thread_ = new Thread();
- threadInfo_.finished = false;
- threadInfo_.object = (void *) this;
-
- // Start the input thread.
- if ( !thread_->start( &inputThread, &threadInfo_ ) ) {
- errorString_ << "TcpWvIn::init: unable to start input thread!";
- handleError( StkError::PROCESS_THREAD );
- }
-}
-
-void TcpWvIn :: listen(unsigned int nChannels, Stk::StkFormat format)
-{
- mutex_.lock();
-
- if ( connected_ ) {
- soket_->close(fd_);
- }
-
- if ( nChannels < 1 ) {
- errorString_ << "TcpWvOut::listen: the channel argument (" << nChannels << ") must be greater than zero.";
- handleError( StkError::FUNCTION_ARGUMENT );
- }
-
- unsigned int lastChannels = channels_;
- channels_ = nChannels;
-
- if ( format == STK_SINT16 ) dataSize_ = 2;
- else if ( format == STK_SINT32 || format == STK_FLOAT32 ) dataSize_ = 4;
- else if ( format == STK_FLOAT64 ) dataSize_ = 8;
- else if ( format == STK_SINT8 ) dataSize_ = 1;
- else {
- errorString_ << "TcpWvIn::listen: unknown data type specified (" << format << ").";
- handleError( StkError::FUNCTION_ARGUMENT );
- }
- dataType_ = format;
-
- int lastBufferBytes = bufferBytes_;
- bufferBytes_ = CHUNK_SIZE * N_BUFFERS * channels_ * dataSize_;
-
- // Allocate new memory if necessary.
- if ( lastBufferBytes < bufferBytes_ ) {
- if ( buffer_) delete [] buffer_;
- buffer_ = (char *) new char[bufferBytes_];
- }
- if ( lastChannels < channels_ ) {
- if ( data_ ) delete [] data_;
- data_ = (StkFloat *) new StkFloat[CHUNK_SIZE*channels_];
- if ( lastOutputs_ ) delete [] lastOutputs_;
- lastOutputs_ = (StkFloat *) new StkFloat[channels_];
- }
-
- WvIn::reset();
- counter_ = 0;
- writePoint_ = 0;
- bytesFilled_ = 0;
-
- // Accept a connection.
- errorString_ << "TcpWvIn: listening for connection on port " << soket_->port() << " ... ";
- handleError( StkError::STATUS );
- fd_ = soket_->accept();
- if ( fd_ < 0) {
- errorString_ << "TcpWvIn: Could not accept connection request!";
- handleError( StkError::PROCESS_SOCKET );
- }
- errorString_ << "TcpWvIn::listen: connection made!";
- handleError( StkError::STATUS );
-
- // Start input thread.
- connected_ = true;
-
- mutex_.unlock();
-}
-
-void TcpWvIn :: receive( void )
-{
- if ( !connected_ ) {
- Stk::sleep(100);
- return;
- }
-
- fd_set mask;
- FD_ZERO(&mask);
- FD_SET(fd_, &mask);
-
- // The select function will block until data is available for reading.
- select(fd_+1, &mask, (fd_set *)0, (fd_set *)0, NULL);
-
- if (FD_ISSET(fd_, &mask)) {
- mutex_.lock();
- long unfilled = bufferBytes_ - bytesFilled_;
- if ( unfilled > 0 ) {
- // There's room in our buffer for more data.
- long endPoint = writePoint_ + unfilled;
- if ( endPoint > bufferBytes_ ) unfilled -= endPoint - bufferBytes_;
- int i = Socket::readBuffer(fd_, (void *)&buffer_[writePoint_], unfilled, 0);
- if ( i <= 0 ) {
- errorString_ << "TcpWvIn::receive: the remote TcpWvIn socket connection has closed.";
- handleError( StkError::STATUS );
- connected_ = false;
- mutex_.unlock();
- return;
- }
- bytesFilled_ += i;
- writePoint_ += i;
- if (writePoint_ == bufferBytes_)
- writePoint_ = 0;
- mutex_.unlock();
- }
- else {
- // Sleep 10 milliseconds AFTER unlocking mutex.
- mutex_.unlock();
- Stk::sleep( 10 );
- }
- }
-}
-
-int TcpWvIn :: readData( void )
-{
- // We have two potential courses of action should this method
- // be called and the input buffer isn't sufficiently filled.
- // One solution is to fill the data buffer with zeros and return.
- // The other solution is to wait until the necessary data exists.
- // I chose the latter, as it works for both streamed files
- // (non-realtime data transport) and realtime playback (given
- // adequate network bandwidth and speed).
-
- // Wait until data is ready.
- long bytes = CHUNK_SIZE * channels_ * dataSize_;
- while ( connected_ && bytesFilled_ < bytes )
- Stk::sleep( 10 );
-
- if ( !connected_ && bytesFilled_ == 0 ) return 0;
- bytes = ( bytesFilled_ < bytes ) ? bytesFilled_ : bytes;
-
- // Copy samples from buffer to data.
- long samples = bytes / dataSize_;
- mutex_.lock();
- if ( dataType_ == STK_SINT16 ) {
- gain_ = 1.0 / 32767.0;
- SINT16 *buf = (SINT16 *) (buffer_+readPoint_);
- for (int i=0; i 0 || counter_ > 0 )
- return true;
- else
- return connected_;
-}
-
-const StkFloat *TcpWvIn :: lastFrame(void) const
-{
- return lastOutputs_;
-}
-
-StkFloat TcpWvIn :: lastOut(void) const
-{
- return WvIn::lastOut();
-}
-
-StkFloat TcpWvIn :: tick(void)
-{
- return WvIn::tick();
-}
-
-StkFloat *TcpWvIn :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return WvIn::tick( vector, vectorSize );
-}
-
-StkFrames& TcpWvIn :: tick( StkFrames& frames, unsigned int channel )
-{
- return WvIn::tick( frames, channel );
-}
-
-const StkFloat *TcpWvIn :: tickFrame(void)
-{
- // If no connection and we've output all samples in the queue, return.
- if ( !connected_ && bytesFilled_ == 0 && counter_ == 0 ) return lastOutputs_;
-
- if (counter_ == 0)
- counter_ = readData();
-
- long temp = (CHUNK_SIZE - counter_) * channels_;
- for (unsigned int i=0; i
-
-TcpWvOut :: TcpWvOut()
-{
- buffer_ = 0;
- soket_ = 0;
-}
-
-TcpWvOut :: TcpWvOut(int port, const char *hostname, unsigned int nChannels, Stk::StkFormat format)
-{
- buffer_ = 0;
- soket_ = 0;
- connect( port, hostname, nChannels, format );
-}
-
-TcpWvOut :: ~TcpWvOut()
-{
- disconnect();
- delete soket_;
- delete [] buffer_;
-}
-
-void TcpWvOut :: connect(int port, const char *hostname, unsigned int nChannels, Stk::StkFormat format)
-{
- if ( soket_ && soket_->isValid( soket_->id() ) )
- disconnect();
-
- if (nChannels < 1) {
- errorString_ << "TcpWvOut::connect: the channel argument (" << nChannels << ") must be greater than zero!";
- handleError( StkError::FUNCTION_ARGUMENT );
- }
-
- unsigned int lastChannels = channels_;
- channels_ = nChannels;
-
- if ( format == STK_SINT8 ) dataSize_ = 1;
- else if ( format == STK_SINT16 ) dataSize_ = 2;
- else if ( format == STK_SINT32 || format == STK_FLOAT32 ) dataSize_ = 4;
- else if ( format == STK_FLOAT64 ) dataSize_ = 8;
- else {
- errorString_ << "TcpWvOut::connect: unknown data type specified (" << format << ").";
- handleError( StkError::FUNCTION_ARGUMENT );
- }
- dataType_ = format;
-
- if ( !soket_ )
- soket_ = new Socket( port, hostname );
- else
- soket_->connect( port, hostname );
-
- // Allocate new memory if necessary.
- if ( lastChannels < channels_ ) {
- data_.resize( BUFFER_SIZE*channels_ );
- if ( buffer_) delete [] buffer_;
- long bytes = dataSize_ * BUFFER_SIZE * channels_;
- buffer_ = (char *) new char[bytes];
- }
- counter_ = 0;
-}
-
-void TcpWvOut :: disconnect(void)
-{
- if ( soket_ ) {
- writeData( counter_ );
- soket_->close();
- }
-}
-
-void TcpWvOut :: writeData( unsigned long frames )
-{
- if ( dataType_ == STK_SINT8 ) {
- signed char *ptr = (signed char *) buffer_;
- for ( unsigned long k=0; kclipTest( data_[k] );
- *ptr++ = (signed char) (data_[k] * 127.0);
- }
- }
- else if ( dataType_ == STK_SINT16 ) {
- SINT16 *ptr = (SINT16 *) buffer_;
- for ( unsigned long k=0; kclipTest( data_[k] );
- *ptr = (SINT16) (data_[k] * 32767.0);
-#ifdef __LITTLE_ENDIAN__
- swap16 ((unsigned char *)ptr);
-#endif
- ptr++;
- }
- }
- else if ( dataType_ == STK_SINT32 ) {
- SINT32 *ptr = (SINT32 *) buffer_;
- for ( unsigned long k=0; kclipTest( data_[k] );
- *ptr = (SINT32) (data_[k] * 2147483647.0);
-#ifdef __LITTLE_ENDIAN__
- swap32 ((unsigned char *)ptr);
-#endif
- ptr++;
- }
- }
- else if ( dataType_ == STK_FLOAT32 ) {
- FLOAT32 *ptr = (FLOAT32 *) buffer_;
- for ( unsigned long k=0; kclipTest( data_[k] );
- *ptr = (FLOAT32) data_[k];
-#ifdef __LITTLE_ENDIAN__
- swap32 ((unsigned char *)ptr);
-#endif
- ptr++;
- }
- }
- else if ( dataType_ == STK_FLOAT64 ) {
- FLOAT64 *ptr = (FLOAT64 *) buffer_;
- for ( unsigned long k=0; kclipTest( data_[k] );
- *ptr = (FLOAT64) data_[k];
-#ifdef __LITTLE_ENDIAN__
- swap64 ((unsigned char *)ptr);
-#endif
- ptr++;
- }
- }
-
- long bytes = dataSize_ * frames * channels_;
- if ( soket_->writeBuffer( (const void *)buffer_, bytes, 0 ) < 0 ) {
- errorString_ << "TcpWvOut: connection to socket server failed!";
- handleError( StkError::PROCESS_SOCKET );
- }
-}
-
-unsigned long TcpWvOut :: getFrames( void ) const
-{
- return totalCount_;
-}
-
-StkFloat TcpWvOut :: getTime( void ) const
-{
- return (StkFloat) totalCount_ / Stk::sampleRate();
-}
-
-void TcpWvOut :: tick( const StkFloat sample )
-{
- if ( !soket_ || !soket_->isValid( soket_->id() ) ) return;
-
- for ( unsigned int j=0; jisValid( soket_->id() ) ) return;
-
- for (unsigned int i=0; i channels in StkFrames argument!";
- handleError( StkError::FUNCTION_ARGUMENT );
- }
-
- if ( !soket_ || !soket_->isValid( soket_->id() ) ) return;
-
- if ( frames.channels() == 1 ) {
- for ( unsigned int i=0; iisValid( soket_->id() ) ) return;
-
- unsigned int j;
- for ( unsigned int i=0; iisValid( soket_->id() ) ) return;
-
- unsigned int j;
- if ( channels_ == 1 || frames.interleaved() ) {
- unsigned long iFrames = 0, iData = counter_;
- for ( unsigned int i=0; isetAllTimes( 0.004, 4.0, 0.0, 0.04);
twozero_.setGain( 0.5 );
- vibrato_->setFrequency( 2.0 );
+ vibrato_.setFrequency( 2.0 );
}
TubeBell :: ~TubeBell()
@@ -78,7 +78,7 @@ void TubeBell :: noteOn(StkFloat frequency, StkFloat amplitude)
#endif
}
-StkFloat TubeBell :: tick()
+StkFloat TubeBell :: computeSample()
{
StkFloat temp, temp2;
@@ -95,19 +95,9 @@ StkFloat TubeBell :: tick()
temp += control2_ * 0.5 * gains_[2] * adsr_[2]->tick() * waves_[2]->tick();
// Calculate amplitude modulation and apply it to output.
- temp2 = vibrato_->tick() * modDepth_;
+ temp2 = vibrato_.tick() * modDepth_;
temp = temp * (1.0 + temp2);
lastOutput_ = temp * 0.5;
return lastOutput_;
}
-
-StkFloat *TubeBell :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Instrmnt::tick( vector, vectorSize );
-}
-
-StkFrames& TubeBell :: tick( StkFrames& frames, unsigned int channel )
-{
- return Instrmnt::tick( frames, channel );
-}
diff --git a/src/TwoPole.cpp b/src/TwoPole.cpp
index e3fd8a5..121ca7c 100644
--- a/src/TwoPole.cpp
+++ b/src/TwoPole.cpp
@@ -8,7 +8,7 @@
frequency response while maintaining a nearly
constant filter gain.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -75,9 +75,9 @@ StkFloat TwoPole :: lastOut(void) const
return Filter::lastOut();
}
-StkFloat TwoPole :: tick(StkFloat sample)
+StkFloat TwoPole :: tick( StkFloat input )
{
- inputs_[0] = gain_ * sample;
+ inputs_[0] = gain_ * input;
outputs_[0] = b_[0] * inputs_[0] - a_[2] * outputs_[2] - a_[1] * outputs_[1];
outputs_[2] = outputs_[1];
outputs_[1] = outputs_[0];
@@ -85,11 +85,6 @@ StkFloat TwoPole :: tick(StkFloat sample)
return outputs_[0];
}
-StkFloat *TwoPole :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Filter::tick( vector, vectorSize );
-}
-
StkFrames& TwoPole :: tick( StkFrames& frames, unsigned int channel )
{
return Filter::tick( frames, channel );
diff --git a/src/TwoZero.cpp b/src/TwoZero.cpp
index ee22728..5217d09 100644
--- a/src/TwoZero.cpp
+++ b/src/TwoZero.cpp
@@ -8,7 +8,7 @@
frequency response while maintaining a
constant filter gain.
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -76,9 +76,9 @@ StkFloat TwoZero :: lastOut(void) const
return Filter::lastOut();
}
-StkFloat TwoZero :: tick(StkFloat sample)
+StkFloat TwoZero :: tick( StkFloat input )
{
- inputs_[0] = gain_ * sample;
+ inputs_[0] = gain_ * input;
outputs_[0] = b_[2] * inputs_[2] + b_[1] * inputs_[1] + b_[0] * inputs_[0];
inputs_[2] = inputs_[1];
inputs_[1] = inputs_[0];
@@ -86,11 +86,6 @@ StkFloat TwoZero :: tick(StkFloat sample)
return outputs_[0];
}
-StkFloat *TwoZero :: tick(StkFloat *vector, unsigned int vectorSize)
-{
- return Filter::tick( vector, vectorSize );
-}
-
StkFrames& TwoZero :: tick( StkFrames& frames, unsigned int channel )
{
return Filter::tick( frames, channel );
diff --git a/src/UdpSocket.cpp b/src/UdpSocket.cpp
new file mode 100644
index 0000000..353fdd8
--- /dev/null
+++ b/src/UdpSocket.cpp
@@ -0,0 +1,104 @@
+/***************************************************/
+/*! \class UdpSocket
+ \brief STK UDP socket server/client class.
+
+ This class provides a uniform cross-platform UDP socket
+ server/client interface. Methods are provided for reading or
+ writing data buffers. The constructor creates a UDP socket and
+ binds it to the specified port. Note that only one socket can be
+ bound to a given port on the same machine.
+
+ UDP sockets provide unreliable, connection-less service. Messages
+ can be lost, duplicated, or received out of order. That said,
+ data transmission tends to be faster than with TCP connections and
+ datagrams are not potentially combined by the underlying system.
+
+ The user is responsible for checking the values returned by the
+ read/write methods. Values less than or equal to zero indicate
+ the occurence of an error.
+
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
+*/
+/***************************************************/
+
+#include "UdpSocket.h"
+
+UdpSocket :: UdpSocket(int port )
+{
+ validAddress_ = false;
+
+#if defined(__OS_WINDOWS__) // windoze-only stuff
+ WSADATA wsaData;
+ WORD wVersionRequested = MAKEWORD(1,1);
+
+ WSAStartup(wVersionRequested, &wsaData);
+ if (wsaData.wVersion != wVersionRequested) {
+ errorString_ << "UdpSocket: Incompatible Windows socket library version!";
+ handleError( StkError::PROCESS_SOCKET );
+ }
+#endif
+
+ // Create the UDP socket
+ soket_ = ::socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
+ if ( soket_ < 0 ) {
+ errorString_ << "UdpSocket: Couldn't create UDP socket!";
+ handleError( StkError::PROCESS_SOCKET );
+ }
+
+ struct sockaddr_in address;
+ address.sin_family = AF_INET;
+ address.sin_addr.s_addr = INADDR_ANY;
+ address.sin_port = htons( port );
+
+ // Bind socket to the appropriate port and interface (INADDR_ANY)
+ if ( bind(soket_, (struct sockaddr *)&address, sizeof(address)) < 0 ) {
+ errorString_ << "UdpSocket: Couldn't bind socket in constructor!";
+ handleError( StkError::PROCESS_SOCKET );
+ }
+
+ port_ = port;
+}
+
+UdpSocket :: ~UdpSocket()
+{
+}
+
+void UdpSocket :: setDestination( int port, std::string hostname )
+{
+ this->setAddress( &address_, port, hostname );
+ validAddress_ = true;
+}
+
+void UdpSocket :: setAddress( struct sockaddr_in *address, int port, std::string hostname )
+{
+ struct hostent *hostp;
+ if ( (hostp = gethostbyname( hostname.c_str() )) == 0 ) {
+ errorString_ << "UdpSocket::setAddress: unknown host (" << hostname << ")!";
+ handleError( StkError::PROCESS_SOCKET_IPADDR );
+ }
+
+ // Fill in the address structure
+ address->sin_family = AF_INET;
+ memcpy((void *)&address->sin_addr, hostp->h_addr, hostp->h_length);
+ address->sin_port = htons( port );
+}
+
+int UdpSocket :: writeBuffer( const void *buffer, long bufferSize, int flags )
+{
+ if ( !isValid( soket_ ) || !validAddress_ ) return -1;
+ return sendto( soket_, (const char *)buffer, bufferSize, flags, (struct sockaddr *)&address_, sizeof(address_) );
+}
+
+int UdpSocket :: readBuffer( void *buffer, long bufferSize, int flags )
+{
+ if ( !isValid( soket_ ) ) return -1;
+ return recvfrom( soket_, (char *)buffer, bufferSize, flags, NULL, NULL );
+}
+
+int UdpSocket :: writeBufferTo( const void *buffer, long bufferSize, int port, std::string hostname, int flags )
+{
+ if ( !isValid( soket_ ) ) return -1;
+ struct sockaddr_in address;
+ this->setAddress( &address, port, hostname );
+ return sendto( soket_, (const char *)buffer, bufferSize, flags, (struct sockaddr *)&address, sizeof(address) );
+}
diff --git a/src/Vector3D.cpp b/src/Vector3D.cpp
index 7011c97..8377432 100644
--- a/src/Vector3D.cpp
+++ b/src/Vector3D.cpp
@@ -49,7 +49,7 @@ StkFloat Vector3D :: getLength()
void Vector3D :: setXYZ(StkFloat x, StkFloat y, StkFloat z)
{
- myX_ = z;
+ myX_ = x;
myY_ = y;
myZ_ = z;
};
diff --git a/src/VoicForm.cpp b/src/VoicForm.cpp
index 4f487cc..381e66c 100644
--- a/src/VoicForm.cpp
+++ b/src/VoicForm.cpp
@@ -21,7 +21,7 @@
- Vibrato Gain = 1
- Loudness (Spectral Tilt) = 128
- by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
*/
/***************************************************/
@@ -29,7 +29,7 @@
#include "Phonemes.h"
#include "SKINI.msg"
-#include