From 3f126af4e5fb191c4b63f404dec3513edfd05f72 Mon Sep 17 00:00:00 2001 From: Gary Scavone Date: Wed, 25 Sep 2013 14:47:10 +0200 Subject: [PATCH] Version 3.2 --- README-Linux.txt | 17 - README-Win.txt | 71 - STK/AgogoBel.cpp | 79 - STK/AgogoBel.h | 26 - STK/BiQuad.h | 31 - STK/DLineL.cpp | 77 - STK/DLineL.h | 34 - STK/DLineN.cpp | 70 - STK/DLineN.h | 35 - STK/MIDIIO.cpp | 582 ------ STK/MIDIIO.h | 56 - STK/Marimba.cpp | 116 -- STK/Marimba.h | 32 - STK/MatWvIn.cpp | 178 -- STK/Modal4.cpp | 189 -- STK/Modal4.h | 51 - STK/Object.cpp | 23 - STK/OnePole.cpp | 62 - STK/OnePole.h | 35 - STK/RTSoundIO.cpp | 965 --------- STK/RTSoundIO.h | 71 - STK/RTWvIn.cpp | 126 -- STK/RTWvOut.cpp | 58 - STK/RawWvIn.cpp | 79 - STK/SndWvIn.cpp | 102 - STK/SndWvOut.cpp | 133 -- STK/SndWvOut.h | 36 - STK/Vibraphn.cpp | 80 - STK/Vibraphn.h | 27 - STK/WavWvIn.cpp | 103 - STK/WvIn.cpp | 222 -- STK/WvIn.h | 51 - STK/WvOut.cpp | 27 - STK/WvOut.h | 27 - STK/swapstuf.cpp | 42 - STK/swapstuf.h | 6 - Hierarchy.txt => doc/Hierarchy.txt | 95 +- doc/README-Linux.txt | 28 + doc/README-NeXT.txt | 14 + README-SGI.txt => doc/README-SGI.txt | 6 +- doc/README-Win.txt | 69 + README.txt => doc/README.txt | 37 +- ReleaseNotes.txt => doc/ReleaseNotes.txt | 21 +- SKINI11.txt => doc/SKINI11.txt | 0 effects/effects.cpp | 165 -- effects/effects.opt | Bin 48640 -> 0 bytes effects/effects.plg | 80 - effects/threads.cpp | 279 --- effects/threads.h | 30 - {STK => include}/ADSR.h | 0 include/AifWvIn.h | 30 + include/AifWvOut.h | 32 + {STK => include}/BeeThree.h | 0 include/BiQuad.h | 40 + include/BlowHole.h | 57 + {STK => include}/BowTabl.h | 0 {STK => include}/Bowed.h | 0 {STK => include}/BowedBar.h | 20 +- {STK => include}/Brass.h | 0 include/ByteSwap.h | 5 + {STK => include}/Clarinet.h | 0 include/Controller.h | 119 ++ {STK => include}/DCBlock.h | 0 {STK => include}/DLineA.h | 0 include/DLineL.h | 45 + include/DLineN.h | 45 + {STK => include}/DrumSynt.h | 0 {STK => include}/Envelope.h | 0 include/FIR.h | 34 + {STK => include}/FM4Alg3.h | 0 {STK => include}/FM4Alg4.h | 0 {STK => include}/FM4Alg5.h | 0 {STK => include}/FM4Alg6.h | 0 {STK => include}/FM4Alg8.h | 0 {STK => include}/FM4Op.h | 0 {STK => include}/FMVoices.h | 0 {STK => include}/Filter.h | 0 {STK => include}/Flute.h | 0 {STK => include}/FormSwep.h | 0 {STK => include}/HeavyMtl.h | 0 {STK => include}/Instrmnt.h | 0 {STK => include}/JCRev.h | 0 {STK => include}/JetTabl.h | 0 {STK => include}/LipFilt.h | 0 {STK => include}/Mandolin.h | 0 {STK => include}/MatWvIn.h | 10 +- {STK => include}/MatWvOut.h | 16 +- include/Modal4.h | 55 + include/ModalBar.h | 30 + {STK => include}/Modulatr.h | 0 {STK => include}/Moog1.h | 0 {STK => include}/NRev.h | 0 {STK => include}/Noise.h | 0 {STK => include}/Object.h | 66 +- include/OnePole.h | 44 + {STK => include}/OneZero.h | 0 {STK => include}/PRCRev.h | 0 {STK => include}/PercFlut.h | 0 {STK => include}/Plucked.h | 0 {STK => include}/Plucked2.h | 0 {STK => include}/PoleZero.h | 10 +- {STK => include}/RawWvIn.h | 10 +- {STK => include}/RawWvOut.h | 15 +- {STK => include}/ReedTabl.h | 0 {STK => include}/Reverb.h | 0 {STK => include}/Rhodey.h | 0 include/RtAudio.h | 155 ++ STK/RTDuplex.h => include/RtDuplex.h | 22 +- include/RtMidi.h | 66 + STK/RTWvIn.h => include/RtWvIn.h | 37 +- STK/RTWvOut.h => include/RtWvOut.h | 33 +- {STK => include}/SKINI11.h | 0 {STK => include}/SKINI11.msg | 5 +- {STK => include}/SamplFlt.h | 0 {STK => include}/Sampler.h | 0 {STK => include}/Shakers.h | 0 {STK => include}/Simple.h | 0 {STK => include}/SingWave.h | 1 + {STK => include}/SndWvIn.h | 10 +- include/SndWvOut.h | 29 + include/StkError.h | 46 + include/StrmWvIn.h | 40 + include/StrmWvOut.h | 36 + {STK => include}/SubNoise.h | 0 {STK => include}/TablLook.h | 1 + {STK => include}/TubeBell.h | 0 {STK => include}/TwoPole.h | 0 {STK => include}/TwoZero.h | 0 {STK => include}/VoicForm.h | 0 {STK => include}/VoicMang.h | 0 {STK => include}/WavWvIn.h | 10 +- {STK => include}/WavWvOut.h | 15 +- {STK => include}/Wurley.h | 0 include/WvIn.h | 81 + include/WvOut.h | 43 + {STK => include}/mandplyr.h | 0 {ragamatic => include}/miditabl.h | 2 +- {STK => include}/phontabl.h | 0 mus151/Debug/.placeholder | 0 mus151/GUITwoOsc | 1 - mus151/MUS151.cpp | 118 -- mus151/MUS151.ncb | Bin 107520 -> 0 bytes mus151/MUS151.opt | Bin 48640 -> 0 bytes mus151/Makefile | 64 - mus151/README-mus151.txt | 22 - mus151/Release/.placeholder | 0 mus151/TwoOsc.cpp | 80 - mus151/TwoOsc.h | 33 - mus151/miditabl.h | 19 - mus151/tcl/TwoWaves.tcl | 221 -- mus151/threads.cpp | 279 --- mus151/threads.h | 30 - {effects => projects/effects}/Chorus.cpp | 2 - {effects => projects/effects}/Chorus.h | 6 +- {effects => projects/effects}/Echo.cpp | 0 {effects => projects/effects}/Echo.h | 4 +- {effects => projects/effects}/GUIeffects | 0 {effects => projects/effects}/Makefile | 26 +- projects/effects/Makefile.sgi | 53 + {effects => projects/effects}/PitShift.cpp | 0 {effects => projects/effects}/PitShift.h | 4 +- .../effects}/README-effects.txt | 10 +- .../effects/Release}/.placeholder | 0 projects/effects/effects.cpp | 171 ++ {effects => projects/effects}/effects.dsp | 91 +- {effects => projects/effects}/effects.dsw | 2 +- {effects => projects/effects}/tcl/Effects.tcl | 2 +- projects/examples/Makefile | 60 + projects/examples/examples.dsw | 89 + projects/examples/ioN.cpp | 99 + projects/examples/ioN.dsp | 142 ++ projects/examples/playN.cpp | 66 + projects/examples/playN.dsp | 167 ++ projects/examples/recordN.cpp | 71 + projects/examples/recordN.dsp | 166 ++ projects/examples/simple.tcl | 54 + projects/examples/sineN.cpp | 79 + projects/examples/sineN.dsp | 156 ++ projects/examples/streamInN.cpp | 73 + .../examples/streamInN.dsp | 123 +- projects/examples/streamOutN.cpp | 73 + projects/examples/streamOutN.dsp | 158 ++ {ragamatic => projects/ragamatic}/GUIRaga | 0 {ragamatic => projects/ragamatic}/Makefile | 38 +- projects/ragamatic/Makefile.sgi | 58 + .../ragamatic}/README-raga.txt | 0 {ragamatic => projects/ragamatic}/Sitar1.cpp | 0 {ragamatic => projects/ragamatic}/Sitar1.h | 10 +- .../ragamatic}/StrDrone.cpp | 0 {ragamatic => projects/ragamatic}/StrDrone.h | 10 +- {ragamatic => projects/ragamatic}/Tabla.cpp | 0 {ragamatic => projects/ragamatic}/Tabla.h | 6 +- .../ragamatic}/VoicDrum.cpp | 0 {ragamatic => projects/ragamatic}/VoicDrum.h | 6 +- {ragamatic => projects/ragamatic}/ragamat.cpp | 232 +-- {ragamatic => projects/ragamatic}/ragamat.dsp | 142 +- .../ragamatic/ragamatic.dsw | 4 +- .../ragamatic}/rawwaves/DrDoi1.raw | Bin .../ragamatic}/rawwaves/DrDoi2.raw | Bin .../ragamatic}/rawwaves/DrTak1.raw | Bin .../ragamatic}/rawwaves/DrTak2.raw | Bin .../ragamatic}/rawwaves/Drdak2.raw | Bin .../ragamatic}/rawwaves/Drdak3.raw | Bin .../ragamatic}/rawwaves/Drdak4.raw | Bin .../ragamatic}/rawwaves/Drddak1.raw | Bin .../ragamatic}/rawwaves/Drdee1.raw | Bin .../ragamatic}/rawwaves/Drdee2.raw | Bin .../ragamatic}/rawwaves/Drdoo1.raw | Bin .../ragamatic}/rawwaves/Drdoo2.raw | Bin .../ragamatic}/rawwaves/Drdoo3.raw | Bin .../ragamatic}/rawwaves/Drjun1.raw | Bin .../ragamatic}/rawwaves/Drjun2.raw | Bin .../ragamatic}/rawwaves/ahh.raw | Bin .../ragamatic}/rawwaves/bassdrum.raw | Bin .../ragamatic}/rawwaves/bee1.raw | Bin .../ragamatic}/rawwaves/britestk.raw | Bin .../ragamatic}/rawwaves/cowbell1.raw | Bin .../ragamatic}/rawwaves/dee1.raw | Bin .../ragamatic}/rawwaves/dee2.raw | Bin .../ragamatic}/rawwaves/din1.raw | Bin .../ragamatic}/rawwaves/fwavblnk.raw | Bin .../ragamatic}/rawwaves/gun1.raw | Bin .../ragamatic}/rawwaves/halfwave.raw | Bin .../ragamatic}/rawwaves/hihatcym.raw | Bin .../ragamatic}/rawwaves/impuls10.raw | Bin .../ragamatic}/rawwaves/impuls20.raw | Bin .../ragamatic}/rawwaves/impuls40.raw | Bin .../ragamatic}/rawwaves/jun1.raw | Bin .../ragamatic}/rawwaves/jun2.raw | Bin .../ragamatic}/rawwaves/makefunc.c | 0 .../ragamatic}/rawwaves/makemidi.c | 0 .../ragamatic}/rawwaves/makewavs.c | 0 .../ragamatic}/rawwaves/mand1.raw | Bin .../ragamatic}/rawwaves/mand10.raw | Bin .../ragamatic}/rawwaves/mand11.raw | Bin .../ragamatic}/rawwaves/mand12.raw | Bin .../ragamatic}/rawwaves/mand2.raw | Bin .../ragamatic}/rawwaves/mand3.raw | Bin .../ragamatic}/rawwaves/mand4.raw | Bin .../ragamatic}/rawwaves/mand5.raw | Bin .../ragamatic}/rawwaves/mand6.raw | Bin .../ragamatic}/rawwaves/mand7.raw | Bin .../ragamatic}/rawwaves/mand8.raw | Bin .../ragamatic}/rawwaves/mand9.raw | Bin .../ragamatic}/rawwaves/silence.raw | Bin .../ragamatic}/rawwaves/tak1.raw | Bin .../ragamatic}/rawwaves/tak2.raw | Bin .../ragamatic}/rawwaves/tak3.raw | Bin .../ragamatic}/rawwaves/tak4.raw | Bin .../ragamatic}/tcl/TCLRaga.tcl | 68 +- .../ragamatic}/tcl/bitmaps/prc.xbm | 0 .../ragamatic}/tcl/bitmaps/prcFunny.xbm | 0 .../ragamatic}/tcl/bitmaps/ragamat.bmp | Bin .../ragamatic}/tcl/bitmaps/ragamat.xbm | 0 .../ragamatic}/tcl/bitmaps/ragamat2.bmp | Bin .../ragamatic}/tcl/bitmaps/ragamat2.xbm | 0 projects/syntmono/GUIBowedBar | 1 + projects/syntmono/GUIDrums | 1 + projects/syntmono/GUIModal | 1 + projects/syntmono/GUIPhysical | 1 + projects/syntmono/GUIShakers | 1 + projects/syntmono/GUIVoice | 1 + {syntmono => projects/syntmono}/Makefile | 46 +- {syntmono => projects/syntmono}/Makefile.sgi | 37 +- .../syntmono}/Release/.placeholder | 0 {syntmono => projects/syntmono}/STK.dsw | 2 +- projects/syntmono/StkDemo | 1 + {syntmono => projects/syntmono}/md2skini.dsp | 28 +- .../syntmono}/scores/bookert.ski | 0 .../syntmono}/scores/capture.ski | 0 .../syntmono}/scores/chords.ski | 0 .../syntmono}/scores/doogie.ski | 0 .../syntmono}/scores/drumfunk.ski | 0 .../syntmono}/scores/drumtest.ski | 0 .../syntmono}/scores/duelingb.ski | 0 .../syntmono}/scores/fiddle.ski | 0 .../syntmono}/scores/flutbach.ski | 0 .../syntmono}/scores/funicula.ski | 0 .../syntmono}/scores/funskini.ski | 0 .../syntmono}/scores/instructions | 0 .../syntmono}/scores/lacrymos.ski | 0 .../syntmono}/scores/mandtune.ski | 0 .../syntmono}/scores/marimba2.ski | 0 .../syntmono}/scores/marimtst.ski | 0 .../syntmono}/scores/misacrio.ski | 0 .../syntmono}/scores/morazbel.ski | 0 .../syntmono}/scores/organs.ski | 0 .../syntmono}/scores/pickdamp.ski | 0 .../syntmono}/scores/pictures.ski | 0 .../syntmono}/scores/riderson.ski | 0 .../syntmono}/scores/scales.ski | 0 .../syntmono}/scores/shaktest.ski | 0 .../syntmono}/scores/simplgft.ski | 0 .../syntmono}/scores/spain.ski | 0 .../syntmono}/scores/spain0.ski | 0 .../syntmono}/scores/streetsf.ski | 0 .../syntmono}/scores/test.ski | 0 .../syntmono}/scores/thecars.ski | 0 .../syntmono}/scores/tubebell.ski | 0 .../syntmono}/scores/vocaliz.ski | 0 projects/syntmono/syntmono.cpp | 148 ++ {syntmono => projects/syntmono}/syntmono.dsp | 347 ++-- .../syntmono}/tcl/TCLBowedBar.tcl | 28 +- .../syntmono}/tcl/TCLDemo.tcl | 264 ++- .../syntmono}/tcl/TCLDrums.tcl | 2 +- .../syntmono/tcl/TCLModal.tcl | 211 +- .../syntmono}/tcl/TCLPhys.tcl | 20 +- .../syntmono}/tcl/TCLShakers.tcl | 18 +- .../syntmono}/tcl/TCLVoice.tcl | 20 +- .../syntmono}/tcl/bitmaps/KFMod.xbm | 0 .../syntmono}/tcl/bitmaps/KFiddl.xbm | 0 .../syntmono}/tcl/bitmaps/KFloot.xbm | 0 .../syntmono}/tcl/bitmaps/KHose.xbm | 0 .../syntmono}/tcl/bitmaps/KModal.xbm | 0 .../syntmono}/tcl/bitmaps/KPluk.xbm | 0 .../syntmono}/tcl/bitmaps/KVoicForm.xbm | 0 .../syntmono}/tcl/bitmaps/KVoiceFM.xbm | 0 .../syntmono}/tcl/bitmaps/Klar.xbm | 0 .../syntmono}/tcl/bitmaps/bamboo.xbm | 0 .../syntmono}/tcl/bitmaps/cabasa.xbm | 0 .../syntmono}/tcl/bitmaps/guiro.xbm | 0 .../syntmono}/tcl/bitmaps/kasm.xbm | 0 .../syntmono}/tcl/bitmaps/maraca.xbm | 0 .../syntmono}/tcl/bitmaps/phism.xbm | 0 .../syntmono}/tcl/bitmaps/prc.xbm | 0 .../syntmono}/tcl/bitmaps/prcFunny.xbm | 0 .../syntmono}/tcl/bitmaps/rachet.xbm | 0 .../syntmono}/tcl/bitmaps/sleighbell.xbm | 0 .../syntmono}/tcl/bitmaps/tambourine.xbm | 0 projects/syntmono/utilities.cpp | 285 +++ {syntmono => projects/syntmono}/utilities.h | 4 +- ragamatic/ragamat.plg | 53 - ragamatic/ragamatic.dsw | 29 - ragamatic/threads.cpp | 279 --- ragamatic/threads.h | 30 - {STK => src}/ADSR.cpp | 0 src/AifWvIn.cpp | 209 ++ src/AifWvOut.cpp | 192 ++ {STK => src}/BeeThree.cpp | 0 {STK => src}/BiQuad.cpp | 64 +- src/BlowHole.cpp | 209 ++ {STK => src}/BowTabl.cpp | 0 {STK => src}/Bowed.cpp | 1 - {STK => src}/BowedBar.cpp | 138 +- {STK => src}/Brass.cpp | 1 - src/ByteSwap.cpp | 55 + {STK => src}/Clarinet.cpp | 1 - src/Controller.cpp | 490 +++++ {STK => src}/DCBlock.cpp | 0 {STK => src}/DLineA.cpp | 0 src/DLineL.cpp | 172 ++ src/DLineN.cpp | 158 ++ {STK => src}/DrumSynt.cpp | 3 +- {STK => src}/Envelope.cpp | 0 src/FIR.cpp | 67 + {STK => src}/FM4Alg3.cpp | 0 {STK => src}/FM4Alg4.cpp | 0 {STK => src}/FM4Alg5.cpp | 0 {STK => src}/FM4Alg6.cpp | 0 {STK => src}/FM4Alg8.cpp | 0 {STK => src}/FM4Op.cpp | 5 - {STK => src}/FMVoices.cpp | 0 {STK => src}/Filter.cpp | 0 {STK => src}/Flute.cpp | 1 - {STK => src}/FormSwep.cpp | 0 {STK => src}/HeavyMtl.cpp | 0 {STK => src}/Instrmnt.cpp | 0 {STK => src}/JCRev.cpp | 0 {STK => src}/JetTabl.cpp | 0 {STK => src}/LipFilt.cpp | 0 {STK => src}/MD2SKINI.cpp | 12 +- src/Makefile | 52 + {STK => src}/Mandolin.cpp | 2 +- src/MatWvIn.cpp | 235 +++ {STK => src}/MatWvOut.cpp | 71 +- src/Modal4.cpp | 202 ++ src/ModalBar.cpp | 149 ++ {STK => src}/Modulatr.cpp | 1 - {STK => src}/Moog1.cpp | 3 - {STK => src}/NRev.cpp | 0 {STK => src}/Noise.cpp | 0 src/Object.cpp | 24 + src/OnePole.cpp | 101 + {STK => src}/OneZero.cpp | 0 {STK => src}/PRCRev.cpp | 0 {STK => src}/PercFlut.cpp | 0 {STK => src}/Plucked.cpp | 0 {STK => src}/Plucked2.cpp | 0 {STK => src}/PoleZero.cpp | 33 +- src/RawWvIn.cpp | 134 ++ {STK => src}/RawWvOut.cpp | 69 +- {STK => src}/ReedTabl.cpp | 0 {STK => src}/Reverb.cpp | 0 {STK => src}/Rhodey.cpp | 0 src/RtAudio.cpp | 1810 +++++++++++++++++ STK/RTDuplex.cpp => src/RtDuplex.cpp | 51 +- src/RtMidi.cpp | 1078 ++++++++++ src/RtWvIn.cpp | 146 ++ src/RtWvOut.cpp | 81 + {STK => src}/SKINI11.cpp | 0 {STK => src}/SKINI11.tbl | 0 {STK => src}/SamplFlt.cpp | 0 {STK => src}/Sampler.cpp | 0 {STK => src}/Shakers.cpp | 10 +- {STK => src}/Simple.cpp | 1 - {STK => src}/SingWave.cpp | 55 +- src/SndWvIn.cpp | 172 ++ src/SndWvOut.cpp | 121 ++ src/StkError.cpp | 28 + src/StrmWvIn.cpp | 389 ++++ src/StrmWvOut.cpp | 168 ++ {STK => src}/SubNoise.cpp | 0 {STK => src}/TablLook.cpp | 22 +- {STK => src}/TubeBell.cpp | 0 {STK => src}/TwoPole.cpp | 0 {STK => src}/TwoZero.cpp | 0 {STK => src}/VoicForm.cpp | 0 {STK => src}/VoicMang.cpp | 18 - src/WavWvIn.cpp | 204 ++ {STK => src}/WavWvOut.cpp | 86 +- {STK => src}/Wurley.cpp | 0 src/WvIn.cpp | 282 +++ src/WvOut.cpp | 51 + {STK => src}/mandplyr.cpp | 0 syntmono/GUIBowedBar | 1 - syntmono/GUIDrums | 1 - syntmono/GUIPhysical | 1 - syntmono/GUIPlukStruk | 1 - syntmono/GUIShakers | 1 - syntmono/GUIVoice | 1 - syntmono/MIDIPhysical | 1 - syntmono/MIDIPlukStruk | 1 - syntmono/MIDIVoice | 1 - syntmono/Release/.placeholder | 0 syntmono/STK.opt | Bin 53760 -> 0 bytes syntmono/STKdemo | 1 - syntmono/md2skini.plg | 32 - syntmono/miditabl.h | 19 - syntmono/syntmono.cpp | 181 -- syntmono/syntmono.plg | 107 - syntmono/threads.cpp | 279 --- syntmono/threads.h | 30 - syntmono/utilities.cpp | 243 --- 443 files changed, 11772 insertions(+), 8060 deletions(-) delete mode 100644 README-Linux.txt delete mode 100644 README-Win.txt delete mode 100644 STK/AgogoBel.cpp delete mode 100644 STK/AgogoBel.h delete mode 100644 STK/BiQuad.h delete mode 100644 STK/DLineL.cpp delete mode 100644 STK/DLineL.h delete mode 100644 STK/DLineN.cpp delete mode 100644 STK/DLineN.h delete mode 100644 STK/MIDIIO.cpp delete mode 100644 STK/MIDIIO.h delete mode 100644 STK/Marimba.cpp delete mode 100644 STK/Marimba.h delete mode 100644 STK/MatWvIn.cpp delete mode 100644 STK/Modal4.cpp delete mode 100644 STK/Modal4.h delete mode 100644 STK/Object.cpp delete mode 100644 STK/OnePole.cpp delete mode 100644 STK/OnePole.h delete mode 100644 STK/RTSoundIO.cpp delete mode 100644 STK/RTSoundIO.h delete mode 100644 STK/RTWvIn.cpp delete mode 100644 STK/RTWvOut.cpp delete mode 100644 STK/RawWvIn.cpp delete mode 100644 STK/SndWvIn.cpp delete mode 100644 STK/SndWvOut.cpp delete mode 100644 STK/SndWvOut.h delete mode 100644 STK/Vibraphn.cpp delete mode 100644 STK/Vibraphn.h delete mode 100644 STK/WavWvIn.cpp delete mode 100644 STK/WvIn.cpp delete mode 100644 STK/WvIn.h delete mode 100644 STK/WvOut.cpp delete mode 100644 STK/WvOut.h delete mode 100644 STK/swapstuf.cpp delete mode 100644 STK/swapstuf.h rename Hierarchy.txt => doc/Hierarchy.txt (69%) create mode 100644 doc/README-Linux.txt create mode 100644 doc/README-NeXT.txt rename README-SGI.txt => doc/README-SGI.txt (53%) create mode 100644 doc/README-Win.txt rename README.txt => doc/README.txt (55%) rename ReleaseNotes.txt => doc/ReleaseNotes.txt (80%) rename SKINI11.txt => doc/SKINI11.txt (100%) delete mode 100644 effects/effects.cpp delete mode 100644 effects/effects.opt delete mode 100644 effects/effects.plg delete mode 100644 effects/threads.cpp delete mode 100644 effects/threads.h rename {STK => include}/ADSR.h (100%) create mode 100644 include/AifWvIn.h create mode 100644 include/AifWvOut.h rename {STK => include}/BeeThree.h (100%) create mode 100644 include/BiQuad.h create mode 100644 include/BlowHole.h rename {STK => include}/BowTabl.h (100%) rename {STK => include}/Bowed.h (100%) rename {STK => include}/BowedBar.h (78%) rename {STK => include}/Brass.h (100%) create mode 100644 include/ByteSwap.h rename {STK => include}/Clarinet.h (100%) create mode 100644 include/Controller.h rename {STK => include}/DCBlock.h (100%) rename {STK => include}/DLineA.h (100%) create mode 100644 include/DLineL.h create mode 100644 include/DLineN.h rename {STK => include}/DrumSynt.h (100%) rename {STK => include}/Envelope.h (100%) create mode 100644 include/FIR.h rename {STK => include}/FM4Alg3.h (100%) rename {STK => include}/FM4Alg4.h (100%) rename {STK => include}/FM4Alg5.h (100%) rename {STK => include}/FM4Alg6.h (100%) rename {STK => include}/FM4Alg8.h (100%) rename {STK => include}/FM4Op.h (100%) rename {STK => include}/FMVoices.h (100%) rename {STK => include}/Filter.h (100%) rename {STK => include}/Flute.h (100%) rename {STK => include}/FormSwep.h (100%) rename {STK => include}/HeavyMtl.h (100%) rename {STK => include}/Instrmnt.h (100%) rename {STK => include}/JCRev.h (100%) rename {STK => include}/JetTabl.h (100%) rename {STK => include}/LipFilt.h (100%) rename {STK => include}/Mandolin.h (100%) rename {STK => include}/MatWvIn.h (87%) rename {STK => include}/MatWvOut.h (78%) create mode 100644 include/Modal4.h create mode 100644 include/ModalBar.h rename {STK => include}/Modulatr.h (100%) rename {STK => include}/Moog1.h (100%) rename {STK => include}/NRev.h (100%) rename {STK => include}/Noise.h (100%) rename {STK => include}/Object.h (62%) create mode 100644 include/OnePole.h rename {STK => include}/OneZero.h (100%) rename {STK => include}/PRCRev.h (100%) rename {STK => include}/PercFlut.h (100%) rename {STK => include}/Plucked.h (100%) rename {STK => include}/Plucked2.h (100%) rename {STK => include}/PoleZero.h (80%) rename {STK => include}/RawWvIn.h (79%) rename {STK => include}/RawWvOut.h (76%) rename {STK => include}/ReedTabl.h (100%) rename {STK => include}/Reverb.h (100%) rename {STK => include}/Rhodey.h (100%) create mode 100644 include/RtAudio.h rename STK/RTDuplex.h => include/RtDuplex.h (68%) create mode 100644 include/RtMidi.h rename STK/RTWvIn.h => include/RtWvIn.h (58%) rename STK/RTWvOut.h => include/RtWvOut.h (52%) rename {STK => include}/SKINI11.h (100%) rename {STK => include}/SKINI11.msg (96%) rename {STK => include}/SamplFlt.h (100%) rename {STK => include}/Sampler.h (100%) rename {STK => include}/Shakers.h (100%) rename {STK => include}/Simple.h (100%) rename {STK => include}/SingWave.h (98%) rename {STK => include}/SndWvIn.h (78%) create mode 100644 include/SndWvOut.h create mode 100644 include/StkError.h create mode 100644 include/StrmWvIn.h create mode 100644 include/StrmWvOut.h rename {STK => include}/SubNoise.h (100%) rename {STK => include}/TablLook.h (97%) rename {STK => include}/TubeBell.h (100%) rename {STK => include}/TwoPole.h (100%) rename {STK => include}/TwoZero.h (100%) rename {STK => include}/VoicForm.h (100%) rename {STK => include}/VoicMang.h (100%) rename {STK => include}/WavWvIn.h (79%) rename {STK => include}/WavWvOut.h (75%) rename {STK => include}/Wurley.h (100%) create mode 100644 include/WvIn.h create mode 100644 include/WvOut.h rename {STK => include}/mandplyr.h (100%) rename {ragamatic => include}/miditabl.h (97%) rename {STK => include}/phontabl.h (100%) delete mode 100644 mus151/Debug/.placeholder delete mode 100755 mus151/GUITwoOsc delete mode 100644 mus151/MUS151.cpp delete mode 100644 mus151/MUS151.ncb delete mode 100644 mus151/MUS151.opt delete mode 100644 mus151/Makefile delete mode 100644 mus151/README-mus151.txt delete mode 100644 mus151/Release/.placeholder delete mode 100644 mus151/TwoOsc.cpp delete mode 100644 mus151/TwoOsc.h delete mode 100644 mus151/miditabl.h delete mode 100644 mus151/tcl/TwoWaves.tcl delete mode 100644 mus151/threads.cpp delete mode 100644 mus151/threads.h rename {effects => projects/effects}/Chorus.cpp (98%) rename {effects => projects/effects}/Chorus.h (89%) rename {effects => projects/effects}/Echo.cpp (100%) rename {effects => projects/effects}/Echo.h (90%) rename {effects => projects/effects}/GUIeffects (100%) rename {effects => projects/effects}/Makefile (62%) create mode 100644 projects/effects/Makefile.sgi rename {effects => projects/effects}/PitShift.cpp (100%) rename {effects => projects/effects}/PitShift.h (91%) rename {effects => projects/effects}/README-effects.txt (71%) rename {effects/Debug => projects/effects/Release}/.placeholder (100%) create mode 100644 projects/effects/effects.cpp rename {effects => projects/effects}/effects.dsp (69%) rename {effects => projects/effects}/effects.dsw (82%) rename {effects => projects/effects}/tcl/Effects.tcl (99%) create mode 100644 projects/examples/Makefile create mode 100755 projects/examples/examples.dsw create mode 100644 projects/examples/ioN.cpp create mode 100755 projects/examples/ioN.dsp create mode 100644 projects/examples/playN.cpp create mode 100755 projects/examples/playN.dsp create mode 100644 projects/examples/recordN.cpp create mode 100755 projects/examples/recordN.dsp create mode 100644 projects/examples/simple.tcl create mode 100644 projects/examples/sineN.cpp create mode 100755 projects/examples/sineN.dsp create mode 100644 projects/examples/streamInN.cpp rename mus151/MUS151.dsp => projects/examples/streamInN.dsp (52%) mode change 100644 => 100755 create mode 100644 projects/examples/streamOutN.cpp create mode 100755 projects/examples/streamOutN.dsp rename {ragamatic => projects/ragamatic}/GUIRaga (100%) rename {ragamatic => projects/ragamatic}/Makefile (59%) create mode 100644 projects/ragamatic/Makefile.sgi rename {ragamatic => projects/ragamatic}/README-raga.txt (100%) rename {ragamatic => projects/ragamatic}/Sitar1.cpp (100%) rename {ragamatic => projects/ragamatic}/Sitar1.h (86%) rename {ragamatic => projects/ragamatic}/StrDrone.cpp (100%) rename {ragamatic => projects/ragamatic}/StrDrone.h (86%) rename {ragamatic => projects/ragamatic}/Tabla.cpp (100%) rename {ragamatic => projects/ragamatic}/Tabla.h (93%) rename {ragamatic => projects/ragamatic}/VoicDrum.cpp (100%) rename {ragamatic => projects/ragamatic}/VoicDrum.h (93%) rename {ragamatic => projects/ragamatic}/ragamat.cpp (51%) rename {ragamatic => projects/ragamatic}/ragamat.dsp (69%) rename mus151/MUS151.dsw => projects/ragamatic/ragamatic.dsw (72%) mode change 100644 => 100755 rename {ragamatic => projects/ragamatic}/rawwaves/DrDoi1.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/DrDoi2.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/DrTak1.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/DrTak2.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/Drdak2.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/Drdak3.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/Drdak4.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/Drddak1.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/Drdee1.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/Drdee2.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/Drdoo1.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/Drdoo2.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/Drdoo3.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/Drjun1.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/Drjun2.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/ahh.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/bassdrum.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/bee1.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/britestk.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/cowbell1.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/dee1.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/dee2.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/din1.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/fwavblnk.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/gun1.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/halfwave.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/hihatcym.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/impuls10.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/impuls20.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/impuls40.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/jun1.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/jun2.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/makefunc.c (100%) rename {ragamatic => projects/ragamatic}/rawwaves/makemidi.c (100%) rename {ragamatic => projects/ragamatic}/rawwaves/makewavs.c (100%) rename {ragamatic => projects/ragamatic}/rawwaves/mand1.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/mand10.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/mand11.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/mand12.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/mand2.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/mand3.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/mand4.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/mand5.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/mand6.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/mand7.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/mand8.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/mand9.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/silence.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/tak1.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/tak2.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/tak3.raw (100%) rename {ragamatic => projects/ragamatic}/rawwaves/tak4.raw (100%) rename {ragamatic => projects/ragamatic}/tcl/TCLRaga.tcl (80%) rename {ragamatic => projects/ragamatic}/tcl/bitmaps/prc.xbm (100%) rename {ragamatic => projects/ragamatic}/tcl/bitmaps/prcFunny.xbm (100%) rename {ragamatic => projects/ragamatic}/tcl/bitmaps/ragamat.bmp (100%) rename {ragamatic => projects/ragamatic}/tcl/bitmaps/ragamat.xbm (100%) rename {ragamatic => projects/ragamatic}/tcl/bitmaps/ragamat2.bmp (100%) rename {ragamatic => projects/ragamatic}/tcl/bitmaps/ragamat2.xbm (100%) create mode 100755 projects/syntmono/GUIBowedBar create mode 100755 projects/syntmono/GUIDrums create mode 100755 projects/syntmono/GUIModal create mode 100755 projects/syntmono/GUIPhysical create mode 100755 projects/syntmono/GUIShakers create mode 100755 projects/syntmono/GUIVoice rename {syntmono => projects/syntmono}/Makefile (56%) rename {syntmono => projects/syntmono}/Makefile.sgi (67%) rename {effects => projects/syntmono}/Release/.placeholder (100%) rename {syntmono => projects/syntmono}/STK.dsw (85%) create mode 100755 projects/syntmono/StkDemo rename {syntmono => projects/syntmono}/md2skini.dsp (80%) rename {syntmono => projects/syntmono}/scores/bookert.ski (100%) rename {syntmono => projects/syntmono}/scores/capture.ski (100%) rename {syntmono => projects/syntmono}/scores/chords.ski (100%) rename {syntmono => projects/syntmono}/scores/doogie.ski (100%) rename {syntmono => projects/syntmono}/scores/drumfunk.ski (100%) rename {syntmono => projects/syntmono}/scores/drumtest.ski (100%) rename {syntmono => projects/syntmono}/scores/duelingb.ski (100%) rename {syntmono => projects/syntmono}/scores/fiddle.ski (100%) rename {syntmono => projects/syntmono}/scores/flutbach.ski (100%) rename {syntmono => projects/syntmono}/scores/funicula.ski (100%) rename {syntmono => projects/syntmono}/scores/funskini.ski (100%) rename {syntmono => projects/syntmono}/scores/instructions (100%) rename {syntmono => projects/syntmono}/scores/lacrymos.ski (100%) rename {syntmono => projects/syntmono}/scores/mandtune.ski (100%) rename {syntmono => projects/syntmono}/scores/marimba2.ski (100%) rename {syntmono => projects/syntmono}/scores/marimtst.ski (100%) rename {syntmono => projects/syntmono}/scores/misacrio.ski (100%) rename {syntmono => projects/syntmono}/scores/morazbel.ski (100%) rename {syntmono => projects/syntmono}/scores/organs.ski (100%) rename {syntmono => projects/syntmono}/scores/pickdamp.ski (100%) rename {syntmono => projects/syntmono}/scores/pictures.ski (100%) rename {syntmono => projects/syntmono}/scores/riderson.ski (100%) rename {syntmono => projects/syntmono}/scores/scales.ski (100%) rename {syntmono => projects/syntmono}/scores/shaktest.ski (100%) rename {syntmono => projects/syntmono}/scores/simplgft.ski (100%) rename {syntmono => projects/syntmono}/scores/spain.ski (100%) rename {syntmono => projects/syntmono}/scores/spain0.ski (100%) rename {syntmono => projects/syntmono}/scores/streetsf.ski (100%) rename {syntmono => projects/syntmono}/scores/test.ski (100%) rename {syntmono => projects/syntmono}/scores/thecars.ski (100%) rename {syntmono => projects/syntmono}/scores/tubebell.ski (100%) rename {syntmono => projects/syntmono}/scores/vocaliz.ski (100%) create mode 100644 projects/syntmono/syntmono.cpp rename {syntmono => projects/syntmono}/syntmono.dsp (61%) rename {syntmono => projects/syntmono}/tcl/TCLBowedBar.tcl (88%) rename {syntmono => projects/syntmono}/tcl/TCLDemo.tcl (77%) rename {syntmono => projects/syntmono}/tcl/TCLDrums.tcl (98%) rename syntmono/tcl/TCLStruk.tcl => projects/syntmono/tcl/TCLModal.tcl (51%) rename {syntmono => projects/syntmono}/tcl/TCLPhys.tcl (92%) rename {syntmono => projects/syntmono}/tcl/TCLShakers.tcl (92%) rename {syntmono => projects/syntmono}/tcl/TCLVoice.tcl (91%) rename {syntmono => projects/syntmono}/tcl/bitmaps/KFMod.xbm (100%) rename {syntmono => projects/syntmono}/tcl/bitmaps/KFiddl.xbm (100%) rename {syntmono => projects/syntmono}/tcl/bitmaps/KFloot.xbm (100%) rename {syntmono => projects/syntmono}/tcl/bitmaps/KHose.xbm (100%) rename {syntmono => projects/syntmono}/tcl/bitmaps/KModal.xbm (100%) rename {syntmono => projects/syntmono}/tcl/bitmaps/KPluk.xbm (100%) rename {syntmono => projects/syntmono}/tcl/bitmaps/KVoicForm.xbm (100%) rename {syntmono => projects/syntmono}/tcl/bitmaps/KVoiceFM.xbm (100%) rename {syntmono => projects/syntmono}/tcl/bitmaps/Klar.xbm (100%) rename {syntmono => projects/syntmono}/tcl/bitmaps/bamboo.xbm (100%) rename {syntmono => projects/syntmono}/tcl/bitmaps/cabasa.xbm (100%) rename {syntmono => projects/syntmono}/tcl/bitmaps/guiro.xbm (100%) rename {syntmono => projects/syntmono}/tcl/bitmaps/kasm.xbm (100%) rename {syntmono => projects/syntmono}/tcl/bitmaps/maraca.xbm (100%) rename {syntmono => projects/syntmono}/tcl/bitmaps/phism.xbm (100%) rename {syntmono => projects/syntmono}/tcl/bitmaps/prc.xbm (100%) rename {syntmono => projects/syntmono}/tcl/bitmaps/prcFunny.xbm (100%) rename {syntmono => projects/syntmono}/tcl/bitmaps/rachet.xbm (100%) rename {syntmono => projects/syntmono}/tcl/bitmaps/sleighbell.xbm (100%) rename {syntmono => projects/syntmono}/tcl/bitmaps/tambourine.xbm (100%) create mode 100644 projects/syntmono/utilities.cpp rename {syntmono => projects/syntmono}/utilities.h (82%) delete mode 100755 ragamatic/ragamat.plg delete mode 100755 ragamatic/ragamatic.dsw delete mode 100644 ragamatic/threads.cpp delete mode 100644 ragamatic/threads.h rename {STK => src}/ADSR.cpp (100%) create mode 100644 src/AifWvIn.cpp create mode 100644 src/AifWvOut.cpp rename {STK => src}/BeeThree.cpp (100%) rename {STK => src}/BiQuad.cpp (50%) create mode 100644 src/BlowHole.cpp rename {STK => src}/BowTabl.cpp (100%) rename {STK => src}/Bowed.cpp (99%) rename {STK => src}/BowedBar.cpp (73%) rename {STK => src}/Brass.cpp (99%) create mode 100644 src/ByteSwap.cpp rename {STK => src}/Clarinet.cpp (99%) create mode 100644 src/Controller.cpp rename {STK => src}/DCBlock.cpp (100%) rename {STK => src}/DLineA.cpp (100%) create mode 100644 src/DLineL.cpp create mode 100644 src/DLineN.cpp rename {STK => src}/DrumSynt.cpp (98%) rename {STK => src}/Envelope.cpp (100%) create mode 100644 src/FIR.cpp rename {STK => src}/FM4Alg3.cpp (100%) rename {STK => src}/FM4Alg4.cpp (100%) rename {STK => src}/FM4Alg5.cpp (100%) rename {STK => src}/FM4Alg6.cpp (100%) rename {STK => src}/FM4Alg8.cpp (100%) rename {STK => src}/FM4Op.cpp (98%) rename {STK => src}/FMVoices.cpp (100%) rename {STK => src}/Filter.cpp (100%) rename {STK => src}/Flute.cpp (99%) rename {STK => src}/FormSwep.cpp (100%) rename {STK => src}/HeavyMtl.cpp (100%) rename {STK => src}/Instrmnt.cpp (100%) rename {STK => src}/JCRev.cpp (100%) rename {STK => src}/JetTabl.cpp (100%) rename {STK => src}/LipFilt.cpp (100%) rename {STK => src}/MD2SKINI.cpp (98%) create mode 100644 src/Makefile rename {STK => src}/Mandolin.cpp (99%) create mode 100644 src/MatWvIn.cpp rename {STK => src}/MatWvOut.cpp (80%) create mode 100644 src/Modal4.cpp create mode 100644 src/ModalBar.cpp rename {STK => src}/Modulatr.cpp (98%) rename {STK => src}/Moog1.cpp (97%) rename {STK => src}/NRev.cpp (100%) rename {STK => src}/Noise.cpp (100%) create mode 100644 src/Object.cpp create mode 100644 src/OnePole.cpp rename {STK => src}/OneZero.cpp (100%) rename {STK => src}/PRCRev.cpp (100%) rename {STK => src}/PercFlut.cpp (100%) rename {STK => src}/Plucked.cpp (100%) rename {STK => src}/Plucked2.cpp (100%) rename {STK => src}/PoleZero.cpp (62%) create mode 100644 src/RawWvIn.cpp rename {STK => src}/RawWvOut.cpp (51%) rename {STK => src}/ReedTabl.cpp (100%) rename {STK => src}/Reverb.cpp (100%) rename {STK => src}/Rhodey.cpp (100%) create mode 100644 src/RtAudio.cpp rename STK/RTDuplex.cpp => src/RtDuplex.cpp (60%) create mode 100644 src/RtMidi.cpp create mode 100644 src/RtWvIn.cpp create mode 100644 src/RtWvOut.cpp rename {STK => src}/SKINI11.cpp (100%) rename {STK => src}/SKINI11.tbl (100%) rename {STK => src}/SamplFlt.cpp (100%) rename {STK => src}/Sampler.cpp (100%) rename {STK => src}/Shakers.cpp (98%) rename {STK => src}/Simple.cpp (99%) rename {STK => src}/SingWave.cpp (80%) create mode 100644 src/SndWvIn.cpp create mode 100644 src/SndWvOut.cpp create mode 100644 src/StkError.cpp create mode 100644 src/StrmWvIn.cpp create mode 100644 src/StrmWvOut.cpp rename {STK => src}/SubNoise.cpp (100%) rename {STK => src}/TablLook.cpp (79%) rename {STK => src}/TubeBell.cpp (100%) rename {STK => src}/TwoPole.cpp (100%) rename {STK => src}/TwoZero.cpp (100%) rename {STK => src}/VoicForm.cpp (100%) rename {STK => src}/VoicMang.cpp (93%) create mode 100644 src/WavWvIn.cpp rename {STK => src}/WavWvOut.cpp (62%) rename {STK => src}/Wurley.cpp (100%) create mode 100644 src/WvIn.cpp create mode 100644 src/WvOut.cpp rename {STK => src}/mandplyr.cpp (100%) delete mode 100755 syntmono/GUIBowedBar delete mode 100755 syntmono/GUIDrums delete mode 100755 syntmono/GUIPhysical delete mode 100755 syntmono/GUIPlukStruk delete mode 100755 syntmono/GUIShakers delete mode 100755 syntmono/GUIVoice delete mode 100755 syntmono/MIDIPhysical delete mode 100755 syntmono/MIDIPlukStruk delete mode 100755 syntmono/MIDIVoice delete mode 100644 syntmono/Release/.placeholder delete mode 100755 syntmono/STK.opt delete mode 100755 syntmono/STKdemo delete mode 100755 syntmono/md2skini.plg delete mode 100644 syntmono/miditabl.h delete mode 100644 syntmono/syntmono.cpp delete mode 100644 syntmono/syntmono.plg delete mode 100644 syntmono/threads.cpp delete mode 100644 syntmono/threads.h delete mode 100644 syntmono/utilities.cpp diff --git a/README-Linux.txt b/README-Linux.txt deleted file mode 100644 index 1551f91..0000000 --- a/README-Linux.txt +++ /dev/null @@ -1,17 +0,0 @@ -STK: A ToolKit of Audio Synthesis Classes and Instruments in C++ -Version 3.1 - -By Perry R. Cook, 1995-2000 -and Gary P. Scavone, 1997-2000. - -Please read the file README.txt for more general STK information. - -STK for Linux is currently using the OSS sound and MIDI API. The free version of OSS will probably work, though it doesn't work with as many soundcards as the commercial version (which costs about $20). The Advanced Linux Sound Architecture (ALSA) drivers seem to perform well, though I've done only minimal testing with them. You'll need to install the OSS compatability library. You can read more about ALSA at http://www.alsa-project.org/. ALSA is open source and holds great promise for audio under Linux. - -STK should compile without much trouble under Linux. Since all Linux distributions typically include the GNU makefile utilities, you should be able to use the default Makefile. Typing "make" will initiate the compilation process. - -NOTE REGARDING PTHREADS: - -The only issue which seems to crop up on different versions of Linux concerns threads. I am using the MIT pthreads API. Under RedHat Linux 4.x, I had to specifically include (the default pthread library didn't work). However, under RedHat Linux 5.0 and higher, the default works and the path doesn't exist. I've decided to assume the default works. If you get errors with regard to pthreads when you compile, you'll have to search your system for the MIT pthread distribution and change the appropriate include statements in MIDIIO.cpp, MD2SKINI.cpp, and threads.cpp. - - diff --git a/README-Win.txt b/README-Win.txt deleted file mode 100644 index 81323a9..0000000 --- a/README-Win.txt +++ /dev/null @@ -1,71 +0,0 @@ -STK: A ToolKit of Audio Synthesis Classes and Instruments in C++ -Version 3.1 - -By Perry R. Cook, 1995-2000 -and Gary P. Scavone, 1997-2000. - -Please read the file README.txt for more general STK information. - -DirectX and WindowsNT Issues: ------------------------------ - -The newly offered STK realtime sound input capabilities under Windoze are only supported using the DirectSoundCapture API. The latency is pretty horrendous, but what do you expect? Also, there is a good chance you don't have DirectSoundCapture support on your computer. You should download the DirectX 6.0 (or higher) runtime libraries from Microsoft's WWW site (http://www.microsoft.com/directx/download.asp) in order to run the pre-compiled STK executables for Windoze. There is no DirectSoundCapture support for WindowsNT ... you'll have to switch to Windows 2000. If you wish to compile STK under WindowsNT (without realtime audio input support), you'll have to uncomment the __WINMM_API_ flag (and comment out the __WINDS_API flag) in Object.h and recompile the source code. - -Realtime sound output under Windoze is supported using either the DirectSound (dsound.lib) API or the old WinMM (winmm.lib) API. The DirectSound version appears to well out-perform the older API. All new versions of Win95/98/NT come with the DirectSound library, but early versions did not. If you have trouble running the distributed executables (compiled for DirectSound API), then you probably don't have DirectSound installed on your system. You can download the necessary DirectSound stuff from Microsoft's WWW pages (http://www.microsoft.com/directx/download.asp). If all else fails, you should be able to compile using the winmm.lib routines ... more latency, but at least it will work. - -Realtime MIDI input is supported using the winmm.lib API. - -Visual C++ workspaces have been created for the various STK projects. Everything has already been configured for you. The intermediate .obj files will be written to either the "Release" or "Debug" directories, but the executable files will be written to the main project directories (where they need to be for proper execution). If you should somehow lose or hose the VC++ workspace file (STK.dsw), then you will have to do a LOT of configuring to recreate it ... it's probably easier just to download the distribution again from our WWW sites. Anyway, for your benefit and mine, here is a list of things that need to be added to the various "Project Settings": - -1. Under General: Set "Output files:" to (this will put the executable in the main project directory. - -2. Under C/C++ > Code Generation: Set "Use run-time library:" to Multithreaded. - -3. Under Link > General: Add winmm.lib, dsound.lib, and Wsock32.lib to the end of the Object/library modules list. - -4. Add all the necessary files to the project. - -NOTE: For some of my personal STK files, I've had trouble compiling in VC++ with the "Optimize Speed" optimization setting (in Project Settings -> C/C++ -> Optimizations:). The files compile, but don't work the way they should when executed. These same files, however, have worked when compiled with the "Default" optimization setting. I've heard that there are bugs with some of these optimization settings. - -Remember that items 1-3 above need to be done for each project and for each configuration. There might be an easy way to make global changes, but I couldn't figure it out. - -To use the Tcl/Tk GUIs, you will have to install Tcl/Tk. I got version 8.0 and it works very well (and installed easily). The distribution is available on the WWW and is free. - -In order for socketing to work, it is necessary to have the TCP protocol installed on your computer. This can be done from the "Network" control panel. - -Finally, to use it all - - - -PLAY SKINI SCOREFILES IN REALTIME: - - syntmono Clarinet -r < scores/streetsf.ski - - -USE TCL/TK GUIs FOR REALTIME CONTROL: - -1. Open a DOS console window and start syntmono (eg. syntmono Clarinet -r -is). - -2. Double click on a Tcl/Tk file in TCLSpecs (eg. TCLPhys.tcl) from the Windows Explorer to start the GUI. Select the "communications" menu item and "Socket" and make the connection. - -3. Start moving the sliders to control the instrument. - - -USE REALTIME MIDI INPUT FOR CONTROL: - -1. Open a DOS console window and start syntmono (eg. syntmono Clarinet -r -is). - -2. Open another DOS console window and start MD2SKINI in the following way: - - MD2SKINI -s - - This assumes you already have MIDI setup correctly for your computer. - - -WINDOWS NT ONLY: - -Realtime piping seems to work under WindowsNT in much the same way as on Unix platforms. Thus, it is possible to pipe realtime control data to syntmono under WindowsNT as well. - - -WINDOWS 2000: - -I don't have Windows 2000 and I don't expect to get it anytime soon. Things should work under 2000 at least as well as they do using NT. Since 2000 is supposed to ship with DirectX 7.0, the DirectSoundCapture functionality should work as well. \ No newline at end of file diff --git a/STK/AgogoBel.cpp b/STK/AgogoBel.cpp deleted file mode 100644 index 0bb1129..0000000 --- a/STK/AgogoBel.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/*******************************************/ -/* AgogoBell SubClass of Modal4 Instrument*/ -/* by Perry R. Cook, 1995-96 */ -/* */ -/* Controls: CONTROL1 = stickHardness */ -/* CONTROL2 = strikePosition */ -/* CONTROL3 = vibFreq */ -/* MOD_WHEEL= vibAmt */ -/*******************************************/ - -/* Modes measured from my Agogo Bell by FFT: */ -/* 360, 1470, 2401, 4600 */ - -#include "AgogoBel.h" -#include "SKINI11.msg" - -AgogoBel :: AgogoBel() : Modal4() -{ - // Concatenate the STK RAWWAVE_PATH to the rawwave file - char file[128]; - strcpy(file, RAWWAVE_PATH); - wave = new RawWvIn(strcat(file,"rawwaves/britestk.raw"), "oneshot"); - wave->normalize(); - wave->setRate((MY_FLOAT) 7.0); // hardstick - this->setRatioAndReson(0, (MY_FLOAT) 1.00,(MY_FLOAT) 0.999); // Set our - this->setRatioAndReson(1, (MY_FLOAT) 4.08,(MY_FLOAT) 0.999); // resonances - this->setRatioAndReson(2,(MY_FLOAT) 6.669,(MY_FLOAT) 0.999); // here - this->setRatioAndReson(3,(MY_FLOAT) -3725.0, (MY_FLOAT)0.999); // (One fixed) - this->setFiltGain(0,(MY_FLOAT) 0.06); // And filter - this->setFiltGain(1,(MY_FLOAT) 0.05); // gains too - this->setFiltGain(2,(MY_FLOAT) 0.03); - this->setFiltGain(3,(MY_FLOAT) 0.02); - directGain = (MY_FLOAT) 0.25; -} - -AgogoBel :: ~AgogoBel() -{ - delete wave; -} - -void AgogoBel :: setStickHardness(MY_FLOAT hardness) -{ - stickHardness = hardness; /* To an approximation, */ - wave->setRate((MY_FLOAT) 3.0 + ((MY_FLOAT) 8.0 * stickHardness)); /* hardness <-> center */ - masterGain = (MY_FLOAT) 1.0; /* freq and amplitude */ -} - -void AgogoBel :: setStrikePosition(MY_FLOAT position) -{ - MY_FLOAT temp,temp2; - temp2 = position * PI; - strikePosition = position; /* Hack only first */ - temp = (MY_FLOAT) sin(0.7 * temp2); /* three modes, */ - this->setFiltGain(0,(MY_FLOAT) 0.08 * temp); /* leave the other */ - temp = (MY_FLOAT) sin(0.1 + (5.0 * temp2)); /* fixed. Why? */ - this->setFiltGain(1,(MY_FLOAT) 0.07 * temp); /* So it doesn't */ - temp = (MY_FLOAT) sin(0.2 + (7.0 * temp2)); /* sound like a */ - this->setFiltGain(2,(MY_FLOAT) 0.04 * temp); /* sample! */ -} - -void AgogoBel :: controlChange(int number, MY_FLOAT value) -{ -#if defined(_debug_) - printf("AgogoBel : ControlChange: Number=%i Value=%f\n",number,value); -#endif - if (number == __SK_StickHardness_) - this->setStickHardness(value * NORM_7); - else if (number == __SK_StrikePosition_) - this->setStrikePosition(value * NORM_7); - else if (number == __SK_ModFrequency_) - vibr->setFreq((value * NORM_7 * (MY_FLOAT) 12.0)); - else if (number == __SK_ModWheel_) - vibrGain = (value * NORM_7); - else if (number == __SK_AfterTouch_Cont_) - this->strike(value * NORM_7); - else { - printf("AgogoBel : Undefined Control Number!!\n"); - } -} diff --git a/STK/AgogoBel.h b/STK/AgogoBel.h deleted file mode 100644 index 625cf87..0000000 --- a/STK/AgogoBel.h +++ /dev/null @@ -1,26 +0,0 @@ -/*******************************************/ -/* AgogoBell SubClass of Modal4 Instrument*/ -/* by Perry R. Cook, 1995-96 */ -/* */ -/* Controls: CONTROL1 = stickHardness */ -/* CONTROL2 = strikePosition */ -/* CONTROL3 = vibFreq */ -/* MOD_WHEEL= vibAmt */ -/*******************************************/ - -#if !defined(__AgogoBel_h) -#define __AgogoBel_h - -#include "Modal4.h" - -class AgogoBel : public Modal4 -{ - public: - AgogoBel(); - ~AgogoBel(); - void setStickHardness(MY_FLOAT hardness); - void setStrikePosition(MY_FLOAT position); - virtual void controlChange(int number, MY_FLOAT value); -}; - -#endif diff --git a/STK/BiQuad.h b/STK/BiQuad.h deleted file mode 100644 index b8178f2..0000000 --- a/STK/BiQuad.h +++ /dev/null @@ -1,31 +0,0 @@ -/*******************************************/ -/* BiQuad (2-pole, 2-zero) Filter Class, */ -/* by Perry R. Cook, 1995-96 */ -/* See books on filters to understand */ -/* more about how this works. Nothing */ -/* out of the ordinary in this version. */ -/*******************************************/ - -#if !defined(__BiQuad_h) -#define __BiQuad_h - -#include "Filter.h" - -class BiQuad : public Filter -{ - protected: - MY_FLOAT poleCoeffs[2]; - MY_FLOAT zeroCoeffs[2]; - public: - BiQuad(); - ~BiQuad(); - void clear(); - void setPoleCoeffs(MY_FLOAT *coeffs); - void setZeroCoeffs(MY_FLOAT *coeffs); - void setGain(MY_FLOAT aValue); - void setFreqAndReson(MY_FLOAT freq, MY_FLOAT reson); - void setEqualGainZeroes(); - MY_FLOAT tick(MY_FLOAT sample); -}; - -#endif diff --git a/STK/DLineL.cpp b/STK/DLineL.cpp deleted file mode 100644 index 2ce064c..0000000 --- a/STK/DLineL.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/*******************************************/ -/* Linearly Interpolating Delay Line */ -/* Object by Perry R. Cook 1995-96 */ -/* This one uses a delay line of maximum */ -/* length specified on creation, and */ -/* linearly interpolates fractional */ -/* length. It is designed to be more */ -/* efficient if the delay length is not */ -/* changed very often. */ -/*******************************************/ - -#include "DLineL.h" - -DLineL :: DLineL() -{ - // Default max delay length set to 2047. - length = 2048; - inputs = (MY_FLOAT *) malloc(length * sizeof(MY_FLOAT)); - this->clear(); - inPoint = 0; - outPoint = length >> 1; -} - -DLineL :: DLineL(long max_length) -{ - length = max_length; - inputs = (MY_FLOAT *) malloc(length * sizeof(MY_FLOAT)); - this->clear(); - inPoint = 0; - outPoint = length >> 1; -} - -DLineL :: ~DLineL() -{ - free(inputs); -} - -void DLineL :: clear() -{ - long i; - for (i=0;i length-1) { // if delay is too big, - printf("DLineL: Delay length too big.\n"); - printf("Setting to maximum length of %ld.\n",length-1); - outPointer = inPoint + 1; // force delay to max_length - } - else - outPointer = inPoint - lag; // read chases write - while (outPointer<0) - outPointer += length; // modulo maximum length - outPoint = (long) outPointer; // integer part - alpha = outPointer - outPoint; // fractional part - omAlpha = (MY_FLOAT) 1.0 - alpha; // 1.0 - fractional part (more efficient) -} - -MY_FLOAT DLineL :: tick(MY_FLOAT sample) // Take one, yield one -{ - inputs[inPoint++] = sample; // Input next sample - if (inPoint == length) // Check for end condition - inPoint -= length; - lastOutput = inputs[outPoint++] * omAlpha; // first 1/2 of interpolation - if (outPointclear(); - inPoint = 0; - outPoint = length >> 1; -} - -DLineN :: DLineN(long max_length) -{ - // Writing before reading allows delays from 0 to length-1. - // Thus, if we want to allow a delay of max_length, we need - // a delay-line of length = max_length+1. - length = max_length+1; - inputs = (MY_FLOAT *) malloc(length * sizeof(MY_FLOAT)); - this->clear(); - inPoint = 0; - outPoint = length >> 1; -} - -DLineN :: ~DLineN() -{ - free(inputs); -} - -void DLineN :: clear() -{ - long i; - for (i=0;i length-1) { // if delay is too big, - printf("DLineN: Delay length too big ... setting to maximum length of %ld.\n",length-1); - outPoint = inPoint + 1; // force delay to max_length - } - else - outPoint = inPoint - (long) lag; // read chases write - while (outPoint<0) outPoint += length; // modulo maximum length -} - -MY_FLOAT DLineN :: tick(MY_FLOAT sample) // Take one, yield one -{ - inputs[inPoint++] = sample; // Input next sample - if (inPoint == length) // Check for end condition - inPoint -= length; - lastOutput = inputs[outPoint++]; // Read out next value - if (outPoint>=length) // Check for end condition - outPoint -= length; - return lastOutput; -} diff --git a/STK/DLineN.h b/STK/DLineN.h deleted file mode 100644 index 6adada8..0000000 --- a/STK/DLineN.h +++ /dev/null @@ -1,35 +0,0 @@ -/*******************************************/ -/* Non-Interpolating Delay Line */ -/* Object by Perry R. Cook 1995-96. */ -/* Revised by Gary Scavone, 1999. */ -/* */ -/* This one uses either a delay line of */ -/* maximum length specified on creation */ -/* or a default length of 2048 samples. */ -/* A non-interpolating delay line is */ -/* typically used in non-time varying */ -/* (reverb) applications. */ -/*******************************************/ - -#if !defined(__DLineN_h) -#define __DLineN_h - -#include "Filter.h" - -class DLineN : public Filter -{ - protected: - long inPoint; - long outPoint; - long length; - public: - DLineN(); - DLineN(long max_length); - ~DLineN(); - void clear(); - void setDelay(MY_FLOAT length); - MY_FLOAT tick(MY_FLOAT sample); -}; - -#endif - diff --git a/STK/MIDIIO.cpp b/STK/MIDIIO.cpp deleted file mode 100644 index fb6eb58..0000000 --- a/STK/MIDIIO.cpp +++ /dev/null @@ -1,582 +0,0 @@ -/******************************************/ -/* MIDIIO.cpp */ -/* Realtime MIDI I/O Object for STK, */ -/* by Gary P. Scavone, 1998. */ -/* Based in part on code by Perry */ -/* Cook (SGI), Paul Leonard (Linux), */ -/* the RoseGarden team (Linux), and */ -/* Bill Putnam (Win95/NT). */ -/* */ -/* At the moment, this object only */ -/* handles MIDI Input, though MIDI */ -/* Output code can go here when someone */ -/* decides they need it (and writes it). */ -/* */ -/* This object opens a MIDI Input device */ -/* and parses MIDI messages into a MIDI */ -/* buffer. Time stamp info is converted */ -/* to deltaTime. MIDI data is stored as */ -/* MY_FLOAT to conform with SKINI. */ -/******************************************/ - -#include "MIDIIO.h" - -#if defined(__STK_REALTIME_) - -#define MIDI_BUFFER_SIZE 1024 -int writeOffset; -int readOffset; - -#if defined(__OS_IRIX_) - -/*************************************/ -/* SGI MIDI INPUT */ -/*************************************/ - -#include -#include -#include -#include - -MDport inport; - -MDevent *midiBuffer; - -pthread_t midi_input_thread; - -void *midiInputThread(void *) -{ - MDevent newMessage; - int status; - - while (1) { - mdReceive(inport, &newMessage, 1); - status = (newMessage.msg[0] & MD_STATUSMASK); - - // Ignore all system messages - //if (!((status & 0xff) == 0xfe || (status & 0xff) == 0xf8)) { - if (status != 0xf0) { - midiBuffer[writeOffset] = newMessage; - writeOffset++; - - if( writeOffset >= MIDI_BUFFER_SIZE ) - writeOffset = 0; - } - } -} - -MIDIIO :: MIDIIO() -{ - int nports; - - nports = mdInit(); - printf("%d MIDI devices available\n", nports); - inport = mdOpenInPort(NULL); - if (inport == NULL) { - fprintf(stderr,"Cannot open MIDI device.\n"); - printf("Exiting MIDIIO Process.\n"); - exit(0); - } - mdSetStampMode(inport, MD_NOSTAMP); - - // Set up the circular buffer for the Midi Input Messages - midiBuffer = new MDevent[MIDI_BUFFER_SIZE]; - readOffset = 0; - writeOffset = 0; - - if (pthread_create(&midi_input_thread, NULL, midiInputThread, NULL)) { - fprintf(stderr, "unable to create MIDI input thread ... aborting.\n"); - exit(0); - } -} - -MIDIIO :: ~MIDIIO() -{ - pthread_cancel(midi_input_thread); - mdClosePort(inport); - delete [] midiBuffer; -} - -int MIDIIO :: nextMessage() -{ - int status; - int byte1; - int byte2; - MDevent lastEvent; - static unsigned long long lastTimeStamp = 0; - - if ( readOffset == writeOffset ) return 0; - - lastEvent = midiBuffer[readOffset]; - - readOffset++; - if ( readOffset >= MIDI_BUFFER_SIZE ) readOffset = 0; - - status = (lastEvent.msg[0] & MD_STATUSMASK); - byte1 = lastEvent.msg[1]; - byte2 = lastEvent.msg[2]; - channel = (lastEvent.msg[0] & MD_CHANNELMASK); - - if ((status == MD_PROGRAMCHANGE) || - (status == MD_CHANNELPRESSURE)) - { - messageType = status; - byteTwo = (float) byte1; - deltaTime = (MY_FLOAT) ((lastEvent.stamp - lastTimeStamp) * 0.000000001); - lastTimeStamp = lastEvent.stamp; - } - else if ((status == MD_NOTEON) || (status == MD_NOTEOFF) || - (status == MD_CONTROLCHANGE) || (status == MD_POLYKEYPRESSURE)) - { - messageType = status; - byteTwo = (float) byte1; - byteThree = (float) byte2; - deltaTime = (MY_FLOAT) ((lastEvent.stamp - lastTimeStamp) * 0.000000001); - lastTimeStamp = lastEvent.stamp; - } - else if (status == MD_PITCHBENDCHANGE) - { - messageType = status; - byteTwo = (float) byte1 * NORM_7; - byteTwo += (float) byte2; - deltaTime = (MY_FLOAT) ((lastEvent.stamp - lastTimeStamp) * 0.000000001); - lastTimeStamp = lastEvent.stamp; - } - else - { - messageType = -1; - } - - return messageType; -} - - -#elif defined(__OSS_API_) - -/*************************************/ -/* OSS MIDI INPUT */ -/*************************************/ - -#include -#include -#include -#include -#include -#include -#include -//#include - -int _seqfd; - -typedef unsigned char byte; - -typedef struct { - byte data[4]; - unsigned long time; -} MIDIMESSAGE; - -MIDIMESSAGE *midiBuffer; - -/* System Messages */ -#define MIDI_SYSTEM_MSG ((byte)0xF0) -#define MessageType(MSG) (byte)((MSG) & ((byte)0xF0)) - -#define SEQUENCER_PATH "/dev/sequencer" - -/* MIDI time code at 100 ticks per second. */ -#define OSS_MIDI_CLOCK_RATE 100 - -pthread_t midi_input_thread; - -void *midiInputThread(void *) -{ - byte NumArgs = 0; - byte ArgsLeft = 0; - unsigned long lastTime = 0; - unsigned long newTime = 0; - byte InBytes[4]; - static MIDIMESSAGE newMessage; - int n; - - while (1) { - if ((n = read(_seqfd, &InBytes, sizeof(InBytes))) == -1) { - fprintf(stderr,"Error reading " SEQUENCER_PATH "\n"); - exit(0); - } - - if (n == 4) { /* ignore reads returning less than 4 bytes */ - switch ( InBytes[0] ) - { - case SEQ_WAIT: - /* MIDI clock ticks ... the first MIDI message deltaTime is calculated - * with respect to the start of the MIDI clock. - */ - newTime = ((InBytes[3]<<16)|(InBytes[2]<<8)| InBytes[1]); - break; - - case SEQ_ECHO: - /* no echo events yet defined */ -#ifdef DEBUG - fprintf(stderr,"ECHO EVENT\n"); -#endif - break; - - case SEQ_MIDIPUTC: - /* Determination of a full MIDI message from the input MIDI stream is based - here on the observation that MIDI status bytes and subsequent data bytes - are NOT returned in the same read() call. Rather, they are spread out - over multiple read() returns, with only a single value per return. So, - if we find a status byte, we then determine the number of expected - operands and process that number of subsequent read()s to determine the - complete MIDI message. - */ - if (InBytes[1] & 0x80) { /* Status Byte */ - if (MessageType(InBytes[1]) == MIDI_SYSTEM_MSG) - { - NumArgs = 0; /* no timing info */ -#ifdef DEBUG - fprintf(stderr, "SYSTEM MESSAGE\n"); -#endif - } - else if (MessageType(InBytes[1]) == MIDI_PGM_CHANGE || - MessageType(InBytes[1]) == MIDI_CHN_PRESSURE) - { - NumArgs = 1; - } - else - { - NumArgs = 2; - } - newMessage.data[0] = InBytes[1]; - ArgsLeft = NumArgs; - newMessage.data[1] = 0; - newMessage.data[2] = 0; - } - - if (ArgsLeft && !(InBytes[1] & 0x80)) { /* not a status byte */ - if (ArgsLeft == NumArgs) - newMessage.data[1] = InBytes[1]; - else - { - newMessage.data[2] = InBytes[1]; - } - - --ArgsLeft; - - /* If MIDI message complete, then setup for running status mode - (another event of the same type without status byte). - */ - if ( !ArgsLeft ) { - if (MessageType(newMessage.data[0]) == (int) MIDI_PGM_CHANGE || - MessageType(newMessage.data[0]) == (int) MIDI_CHN_PRESSURE) - { - ArgsLeft = 1; - } - else - { - ArgsLeft = 2; - } - newMessage.time = newTime - lastTime; - lastTime = newTime; - - // Put newMessage in the circular buffer - midiBuffer[writeOffset] = newMessage; - writeOffset++; - - if( writeOffset >= MIDI_BUFFER_SIZE ) - writeOffset = 0; - break; - } - } - - default: - break; - } - } - } -} - -MIDIIO :: MIDIIO() -{ - int err = 0; - _seqfd = 0; - -#ifdef NONBLOCKING_MIDI - if((_seqfd = open(SEQUENCER_PATH, O_RDONLY+O_NONBLOCK, 0)) == -1) { -#else - if((_seqfd = open(SEQUENCER_PATH, O_RDONLY, 0)) == -1) { -#endif - fprintf(stderr,"Cannot open " SEQUENCER_PATH ". \n"); - printf("Exiting MIDIIO Process.\n"); - exit(0); - } - - // Set up the circular buffer for the Midi Input Messages - midiBuffer = new MIDIMESSAGE[MIDI_BUFFER_SIZE]; - readOffset = 0; - writeOffset = 0; - - err = pthread_create(&midi_input_thread, NULL, midiInputThread, NULL); - if (err) - { - fprintf(stderr, "Unable to create MIDI input thread.\n"); - printf("Exiting MIDIIO Process.\n"); - exit(0); - } -} - -MIDIIO :: ~MIDIIO() -{ - pthread_cancel(midi_input_thread); - if (_seqfd != 0) close(_seqfd); - delete [] midiBuffer; -} - -int MIDIIO::nextMessage() -{ - MIDIMESSAGE lastEvent; - - if ( readOffset == writeOffset ) return 0; - - lastEvent = midiBuffer[readOffset]; - - readOffset++; - if ( readOffset >= MIDI_BUFFER_SIZE ) readOffset = 0; - - messageType = (int) (lastEvent.data[0] & 0xf0); - channel = (int) (lastEvent.data[0] & 0x0f); - byteTwo = (float) lastEvent.data[1]; - if (messageType == (int) MIDI_PITCH_BEND) - byteTwo = (float) lastEvent.data[2] + (byteTwo * NORM_7); - else - byteThree = (float) lastEvent.data[2]; - deltaTime = (float) lastEvent.time / OSS_MIDI_CLOCK_RATE; - - return messageType; -} - - -#elif defined(__OS_Win_) - -/*************************************/ -/* Windoze MIDI INPUT */ -/*************************************/ - -#include -#include "MIDIIO.h" - -#define MIDI_NOTEON 0x90 -#define MIDI_NOTEOFF 0x80 -#define MIDI_POLYKEYPRESSURE 0xA0 -#define MIDI_CHANNELPRESSURE 0xD0 -#define MIDI_PROGRAMCHANGE 0xC0 -#define MIDI_CONTROLCHANGE 0xB0 -#define MIDI_PITCHBEND 0xE0 - -typedef struct { - DWORD data; - DWORD time; -} MIDIMESSAGE; - -MIDIMESSAGE *midiBuffer; - -static void CALLBACK midiInputCallback( HMIDIOUT hmin, UINT inputStatus, - DWORD instancePtr, DWORD midiMessage, DWORD timestamp) -{ - MIDIMESSAGE newMessage; - - switch (inputStatus) { - case MIM_OPEN: -#ifdef TESTING_MIDI_IN - printf("MIM_OPEN\n"); -#endif - break; - - case MIM_CLOSE: -#ifdef TESTING_MIDI_IN - printf("MIM_CLOSE\n"); -#endif - break; - - case MIM_DATA: -#ifdef TESTING_MIDI_IN - printf("MIM_DATA\n"); -#endif - // Ignore Active Sensing messages - if ((midiMessage & 0xff) == 0xfe || (midiMessage & 0xff) == 0xf8) { - break; - } - newMessage.data = midiMessage; - newMessage.time = timestamp; - - // Put newMessage in the circular buffer - midiBuffer[writeOffset] = newMessage; - writeOffset++; - - if( writeOffset >= MIDI_BUFFER_SIZE ) - writeOffset = 0; - break; - - case MIM_ERROR: - fprintf(stderr,"Invalid MIDI message received!\n"); -#ifdef TESTING_MIDI_IN - printf("MIM_ERROR\n"); -#endif - break; - - case MIM_LONGDATA: - /* System exclusive buffer is returned */ - break; - - case MIM_LONGERROR: -#ifdef TESTING_MIDI_IN - printf("MIM_LONGERROR\n"); -#endif - break; - - default: - break; - } -} - -HMIDIIN hMidiIn ; // Handle to Midi Output Device - -MIDIIO :: MIDIIO() -{ - MMRESULT result; - UINT uDeviceID; - MIDIINCAPS deviceCaps; - UINT i; - char inputString[128]; - - uDeviceID = midiInGetNumDevs(); - printf("%i MIDI Input Devices Available.\n",uDeviceID); - if (uDeviceID == 0) { - printf("Exiting MIDIIO Process.\n"); - exit(0); - } - - for (i=0; i 1) { - printf("\nType the MIDI Device to open: "); - fgets(inputString, 128, stdin); - uDeviceID = (UINT) atoi(inputString); - } - else uDeviceID -= 1; - - // Open the port and return any errors - result = midiInOpen(&hMidiIn, uDeviceID, (DWORD)&midiInputCallback, (DWORD)NULL, CALLBACK_FUNCTION); - if (result != MMSYSERR_NOERROR) { - fprintf(stderr,"Cannot open MIDI Input Device %d!\n", uDeviceID); - printf("Exiting MIDIIO Process.\n"); - exit(0); - } - - // Set up the circular buffer for the Midi Input Messages - midiBuffer = new MIDIMESSAGE[MIDI_BUFFER_SIZE]; - readOffset = 0; - writeOffset = 0; - - midiInStart( hMidiIn ); -} - -MIDIIO :: ~MIDIIO() -{ - midiInReset( hMidiIn ); - midiInStop( hMidiIn ); - midiInClose( hMidiIn ); - delete [] midiBuffer; -} - -int MIDIIO :: nextMessage() -{ - int status; - int byte1; - int byte2; - MIDIMESSAGE lastEvent; - static DWORD lastTime = 0; - static DWORD newTime = 0; - - if ( readOffset == writeOffset ) return 0; - - lastEvent = midiBuffer[readOffset]; - - readOffset++; - if ( readOffset >= MIDI_BUFFER_SIZE ) readOffset = 0; - - status = (int) (lastEvent.data & 0xff); - byte1 = (int) (lastEvent.data & 0xff00) >> 8; - byte2 = (int) (lastEvent.data & 0xff0000) >> 16; - channel = (int) (status & 0x0f); - status &= 0xf0; // Clear lower byte of status - newTime = lastEvent.time; - deltaTime = (float) (newTime - lastTime) * 0.001; - lastTime = newTime; - - if ((status == MIDI_PROGRAMCHANGE) || - (status == MIDI_CHANNELPRESSURE)) - { - messageType = status; - byteTwo = (float) byte1; - } - else if ((status == MIDI_NOTEON) || (status == MIDI_NOTEOFF) || - (status == MIDI_CONTROLCHANGE) || (status == MIDI_POLYKEYPRESSURE)) - { - messageType = status; - byteTwo = (float) byte1; - byteThree = (float) byte2; - } - else if (status == MIDI_PITCHBEND) - { - messageType = status; - byteTwo = (float) (byte1 * NORM_7); - byteTwo += (float) byte2; - } - else - { - messageType = -1; - } - - return messageType; -} - -#endif - -void MIDIIO :: printMessage() -{ - printf("type = %d, channel = %d, byte2 = %f, byte3 = %f\n", - this->getType(), this->getChannel(), this->getByteTwo(), - this->getByteThree()); -} - -int MIDIIO :: getType() -{ - return messageType; -} - -int MIDIIO :: getChannel() -{ - return channel; -} - -MY_FLOAT MIDIIO :: getByteTwo() -{ - return byteTwo; -} - -MY_FLOAT MIDIIO :: getByteThree() -{ - return byteThree; -} - -MY_FLOAT MIDIIO :: getDeltaTime() -{ - return deltaTime; -} - - -#endif diff --git a/STK/MIDIIO.h b/STK/MIDIIO.h deleted file mode 100644 index 94670d7..0000000 --- a/STK/MIDIIO.h +++ /dev/null @@ -1,56 +0,0 @@ -/******************************************/ -/* MIDIIO.h */ -/* Realtime MIDI I/O Object for STK, */ -/* by Gary P. Scavone, 1998. */ -/* Based in part on code by Perry */ -/* Cook (SGI), Paul Leonard (Linux), */ -/* the RoseGarden team (Linux), and */ -/* Bill Putnam (Win95/NT). */ -/* */ -/* At the moment, this object only */ -/* handles MIDI Input, though MIDI */ -/* Output code can go here when someone */ -/* decides they need it (and writes it). */ -/* */ -/* This object opens a MIDI Input device */ -/* and parses MIDI data. Time stamp */ -/* info is converted to deltaTime. */ -/* MIDI data is stored as MY_FLOAT to */ -/* conform with SKINI. */ -/******************************************/ - -#if !defined(__MIDIIO_h) -#define __MIDIIO_h - -#include "Object.h" - -class MIDIIO : public Object -{ - protected: - int messageType; - int channel; - float byteTwo; - float byteThree; - MY_FLOAT deltaTime; - public: - MIDIIO(); - ~MIDIIO(); - void printMessage(); - int nextMessage(); - int getType(); - int getChannel(); - MY_FLOAT getByteTwo(); - MY_FLOAT getByteThree(); - MY_FLOAT getDeltaTime(); -}; - -#if defined(__OS_Win_) - -#include -#include - -static void CALLBACK midiInputCallback( HMIDIOUT hmin, UINT inputStatus, - DWORD instancePtr, DWORD midiMessage, DWORD timestamp); - -#endif -#endif diff --git a/STK/Marimba.cpp b/STK/Marimba.cpp deleted file mode 100644 index 8a9423b..0000000 --- a/STK/Marimba.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/*******************************************/ -/* Marimba SubClass of Modal4 Instrument, */ -/* by Perry R. Cook, 1995-96 */ -/* */ -/* Controls: CONTROL1 = stickHardness */ -/* CONTROL2 = strikePosition*/ -/* CONTROL3 = vibFreq */ -/* MOD_WHEEL= vibAmt */ -/*******************************************/ - -#include "Marimba.h" -#include "SKINI11.msg" - -Marimba :: Marimba() : Modal4() -{ - // Concatenate the STK RAWWAVE_PATH to the rawwave file - char file[128]; - strcpy(file, RAWWAVE_PATH); - wave = new RawWvIn(strcat(file,"rawwaves/marmstk1.raw"),"oneshot"); - wave->normalize(); - wave->setRate((MY_FLOAT) 0.5); /* normal stick */ - this->setRatioAndReson(0, (MY_FLOAT) 1.00,(MY_FLOAT) 0.9996); /* Set all 132.0 */ - this->setRatioAndReson(1, (MY_FLOAT) 3.99,(MY_FLOAT) 0.9994); /* of our 523.0 */ - this->setRatioAndReson(2,(MY_FLOAT) 10.65,(MY_FLOAT) 0.9994); /* default 1405.0 */ - this->setRatioAndReson(3,-(MY_FLOAT) 2443.0,(MY_FLOAT) 0.999); /* resonances 2443.0 */ - this->setFiltGain(0,(MY_FLOAT) 0.04); /* and */ - this->setFiltGain(1,(MY_FLOAT) 0.01); /* gains */ - this->setFiltGain(2,(MY_FLOAT) 0.01); /* for each */ - this->setFiltGain(3,(MY_FLOAT) 0.008); /* resonance */ - directGain = (MY_FLOAT) 0.1; - multiStrike = 0; -} - -Marimba :: ~Marimba() -{ - delete wave; -} - -void Marimba :: setStickHardness(MY_FLOAT hardness) -{ - stickHardness = hardness; - wave->setRate((MY_FLOAT) (0.25 * (MY_FLOAT) pow(4.0,stickHardness))); - masterGain = (MY_FLOAT) 0.1 + ((MY_FLOAT) 1.8 * stickHardness); -} - -void Marimba :: setStrikePosition(MY_FLOAT position) -{ - MY_FLOAT temp,temp2; - temp2 = position * PI; - strikePosition = position; /* Hack only first three modes */ - temp = (MY_FLOAT) sin(temp2); - this->setFiltGain(0,(MY_FLOAT) 0.12 * temp); /* 1st mode function of pos. */ - temp = (MY_FLOAT) sin(0.05 + (3.9 * temp2)); - this->setFiltGain(1,(MY_FLOAT) -0.03 * temp); /* 2nd mode function of pos. */ - temp = (MY_FLOAT) sin(-0.05 + (11 * temp2)); - this->setFiltGain(2,(MY_FLOAT) 0.11 * temp); /* 3rd mode function of pos. */ -} - -void Marimba :: setModulationSpeed(MY_FLOAT mSpeed) -{ - /* don't bother here, marimba decay so fast, mod doesn't make sense */ -} - -void Marimba :: setModulationDepth(MY_FLOAT mDepth) -{ -} - -void Marimba :: strike(MY_FLOAT amplitude) -{ - int temp; - temp = rand() >> 10; - if (temp < 2) { - multiStrike = 1; -#if defined(_debug_) - printf("striking twice here!!\n"); -#endif - } - else if (temp < 1) { - multiStrike = 2; -#if defined(_debug_) - printf("striking three times here!!!\n"); -#endif - } -else multiStrike = 0; -Modal4::strike(amplitude); -} - -void Marimba :: controlChange(int number, MY_FLOAT value) -{ -#if defined(_debug_) - printf("Marimba : ControlChange: Number=%i Value=%f\n",number,value); -#endif - if (number == __SK_StickHardness_) - this->setStickHardness(value * NORM_7); - else if (number == __SK_StrikePosition_) - this->setStrikePosition(value * NORM_7); - else if (number == __SK_ModFrequency_) - vibr->setFreq((value * NORM_7 * (MY_FLOAT) 12.0)); - else if (number == __SK_ModWheel_) - vibrGain = (value * NORM_7); - else if (number == __SK_AfterTouch_Cont_) - this->strike(value * NORM_7); - else { - printf("Marimba : Undefined Control Number!!\n"); - } -} - -MY_FLOAT Marimba :: tick() -{ - if (multiStrike>0) - if (wave->isFinished()) { - wave->reset(); - multiStrike -= 1; - } - return Modal4::tick(); -} diff --git a/STK/Marimba.h b/STK/Marimba.h deleted file mode 100644 index 8e02111..0000000 --- a/STK/Marimba.h +++ /dev/null @@ -1,32 +0,0 @@ -/*******************************************/ -/* Marimba SubClass of Modal4 Instrument, */ -/* by Perry R. Cook, 1995-96 */ -/* */ -/* Controls: CONTROL1 = stickHardness */ -/* CONTROL2 = strikePosition*/ -/* CONTROL3 = vibFreq */ -/* MOD_WHEEL= vibAmt */ -/*******************************************/ - -#if !defined(__Marimba_h) -#define __Marimba_h - -#include "Modal4.h" - -class Marimba : public Modal4 -{ - private: - int multiStrike; - public: - Marimba(); - ~Marimba(); - void setStickHardness(MY_FLOAT hardness); - void setStrikePosition(MY_FLOAT position); - void setModulationSpeed(MY_FLOAT mSpeed); - void setModulationDepth(MY_FLOAT mDepth); - virtual void strike(MY_FLOAT amplitude); - virtual void controlChange(int number, MY_FLOAT value); - virtual MY_FLOAT tick(); -}; - -#endif diff --git a/STK/MatWvIn.cpp b/STK/MatWvIn.cpp deleted file mode 100644 index b716115..0000000 --- a/STK/MatWvIn.cpp +++ /dev/null @@ -1,178 +0,0 @@ -/*******************************************/ -/* MatWvIn Input Class, */ -/* by Gary P. Scavone, 1999 */ -/* */ -/* This object inherits from WvIn and is */ -/* used to open Matlab MAT-file data */ -/* (doubles) files for playback. In */ -/* order for this class to work, the */ -/* MAT-file must contain a single array */ -/* (matrix) of double-precision floating */ -/* point values (can be multi-channel). */ -/* It does not work for any other data */ -/* formats. */ -/* */ -/* MAT-file data is either big- or */ -/* little-endian, which can be determined */ -/* from the header. */ -/*******************************************/ - -#include "MatWvIn.h" -#include "swapstuf.h" - -MatWvIn :: MatWvIn(char *fileName, char *mode) -{ - extern double SwapDouble(double); - - // Open the file and get header info - FILE *fd; - fd = fopen(fileName,"rb"); - if (!fd) { - printf("Couldn't open or find MAT-file %s !!!\n",fileName); - exit(0); - } - - // Make sure this is a version 5 MAT-file format and find its endian-ness - char head[4]; - fseek(fd,0,SEEK_SET); - fread(&head,4,1,fd); // If any of the first 4 characters of the header = 0, - if (strstr(head,"0")) { // then this is a Version 4 MAT-file. - printf("This looks like a Version 4 MAT-file. I don't support\n"); - printf("that at the moment, but you can add the code to MatWvIn if\n"); - printf("you really need it.\n"); - exit(0); - } - char mi[2]; - int swap = 0; - fseek(fd,126,SEEK_SET); // Locate "M" and "I" characters in header - fread(&mi,2,1,fd); -#ifdef __LITTLE_ENDIAN__ - if (!strncmp(mi,"MI",2)) { - swap = 1; - } else if (strncmp(mi,"IM",2)) { - printf("This doesn't appear to be a MAT-file %s !!!\n",fileName); - exit(0); - } -#else - if (!strncmp(mi,"IM",2)) { - swap = 1; - } else if (strncmp(mi,"MI",2)) { - printf("This doesn't appear to be a MAT-file %s !!!\n",fileName); - exit(0); - } -#endif - - // Check the data element type - INT32 datatype; - fread(&datatype,4,1,fd); - if (swap) datatype = SwapINT32(datatype); - if (datatype != 14) { - printf("I'm expecting a single array (or matrix) data element.\n"); - printf("This doesn't appear to be the case with your data. Sorry!\n"); - exit(0); - } - - // Check the array data type - INT32 tmp; - INT32 size; - fseek(fd,168,SEEK_SET); - fread(&tmp,4,1,fd); - if (swap) tmp = SwapINT32(tmp); - if (tmp == 1) { // array name > 4 characters - fread(&tmp,4,1,fd); // get array name length - if (swap) tmp = SwapINT32(tmp); - size = (INT32) ceil((float)tmp/8); - fseek(fd,size*8,SEEK_CUR); // jump over array name - } - else { // array name <= 4 characters, compressed data element - fseek(fd,4,SEEK_CUR); - } - fread(&tmp,4,1,fd); - if (swap) tmp = SwapINT32(tmp); - if (tmp != 9) { - printf("I'm expecting the array data to be in double precision\n"); - printf("floating-point format. This doesn't appear to be the case\n"); - printf("with your data. Sorry!\n"); - exit(0); - } - - // Get number of rows from the header - INT32 rows; - fseek(fd,160,SEEK_SET); - fread(&rows,4,1,fd); // rows - if (swap) rows = SwapINT32(rows); - - // Get number of columns from the header - INT32 columns; - fread(&columns,4,1,fd); // columns - if (swap) columns = SwapINT32(columns); - - // Make channels = smaller of rows or columns - if (rows < columns) { - channels = rows; - length = columns; - } - else { - channels = columns; - length = rows; - } - data = (MY_FLOAT *) new MY_FLOAT[(length+1)*channels]; - - // Move read pointer to the data in the file - INT32 headsize; - fseek(fd,132,SEEK_SET); - fread(&headsize,4,1,fd); // file size from 132nd byte - if (swap) headsize = SwapINT32(headsize); - headsize -= length * 8 * channels; - fseek(fd,headsize,SEEK_CUR); - - // Read samples into data[] - long i = 0; - double temp; - if (channels == rows) { - while (fread(&temp,8,1,fd)) { - if (swap) temp = SwapDouble(temp); - data[i++] = (MY_FLOAT) temp; - } - } else { - long j = 0; - while (fread(&temp,8,1,fd)) { - if (swap) temp = SwapDouble(temp); - data[channels*i+j] = (MY_FLOAT) temp; - i++; - if (!(inormalize(); - vibr->setFreq((MY_FLOAT) 6.0); - vibrGain = (MY_FLOAT) 0.05; - - directGain = (MY_FLOAT) 0.0; - masterGain = (MY_FLOAT) 1.0; - baseFreq = (MY_FLOAT) 440.0; - this->setRatioAndReson(0,(MY_FLOAT) 1.00,(MY_FLOAT) 0.9997); /* Set some */ - this->setRatioAndReson(1,(MY_FLOAT) 1.30,(MY_FLOAT) 0.9997); /* silly */ - this->setRatioAndReson(2,(MY_FLOAT) 1.77,(MY_FLOAT) 0.9997); /* default */ - this->setRatioAndReson(3,(MY_FLOAT) 2.37,(MY_FLOAT) 0.9997); /* values here */ - this->setFiltGain(0,(MY_FLOAT) 0.01); - this->setFiltGain(1,(MY_FLOAT) 0.01); - this->setFiltGain(2,(MY_FLOAT) 0.01); - this->setFiltGain(3,(MY_FLOAT) 0.01); - this->clear(); - filters[0]->setEqualGainZeroes(); - filters[1]->setEqualGainZeroes(); - filters[2]->setEqualGainZeroes(); - filters[3]->setEqualGainZeroes(); - stickHardness = (MY_FLOAT) 0.5; - strikePosition = (MY_FLOAT) 0.561; -} - -Modal4 :: ~Modal4() -{ - delete envelope; - delete filters[0]; - delete filters[1]; - delete filters[2]; - delete filters[3]; - delete onepole; - delete vibr; -} - -void Modal4 :: clear() -{ - onepole->clear(); - filters[0]->clear(); - filters[1]->clear(); - filters[2]->clear(); - filters[3]->clear(); -} - -void Modal4 :: setFreq(MY_FLOAT frequency) -{ - baseFreq = frequency; - this->setRatioAndReson(0,ratios[0],resons[0]); - this->setRatioAndReson(1,ratios[1],resons[1]); - this->setRatioAndReson(2,ratios[2],resons[2]); - this->setRatioAndReson(3,ratios[3],resons[3]); -} - -#include - -void Modal4 :: setRatioAndReson(int whichOne, MY_FLOAT ratio,MY_FLOAT reson) -{ - MY_FLOAT temp; - if (ratio*baseFreq < SRATE_OVER_TWO) { - ratios[whichOne] = ratio; - } - else { - temp = ratio; - while (temp*baseFreq > SRATE_OVER_TWO) temp *= (MY_FLOAT) 0.5; - ratios[whichOne] = temp; -#if defined(_debug_) - printf("Modal4 : Aliasing would occur here, correcting.\n"); -#endif - } - resons[whichOne] = reson; - if (ratio<0) - temp = -ratio; - else - temp = ratio*baseFreq; - filters[whichOne]->setFreqAndReson(temp,reson); -} - -void Modal4 :: setMasterGain(MY_FLOAT aGain) -{ - masterGain = aGain; -} - -void Modal4 :: setDirectGain(MY_FLOAT aGain) -{ - directGain = aGain; -} - -void Modal4 :: setFiltGain(int whichOne, MY_FLOAT gain) -{ - filters[whichOne]->setGain(gain); -} - -void Modal4 :: strike(MY_FLOAT amplitude) -{ - int i; - MY_FLOAT temp; - envelope->setRate((MY_FLOAT) 1.0); - envelope->setTarget(amplitude); - onepole->setPole((MY_FLOAT) 1.0 - amplitude); - envelope->tick(); - wave->reset(); - for (i=0;i<4;i++) { - if (ratios[i] < 0) - temp = -ratios[i]; - else - temp = ratios[i] * baseFreq; - filters[i]->setFreqAndReson(temp,resons[i]); - } -} - -void Modal4 :: noteOn(MY_FLOAT freq, MY_FLOAT amp) -{ - this->strike(amp); - this->setFreq(freq); -#if defined(_debug_) - printf("Modal4 : NoteOn: Freq=%lf Amp=%lf\n",freq,amp); -#endif -} - -void Modal4 :: noteOff(MY_FLOAT amp) /* This calls damp, but inverts the */ -{ /* meaning of amplitude. */ - this->damp((MY_FLOAT) 1.0 - (amp * (MY_FLOAT) 0.03)); /* (high amplitude means fast damping) */ -#if defined(_debug_) - printf("Modal4 : NoteOff: Amp=%lf\n",amp); -#endif -} - -void Modal4 :: damp(MY_FLOAT amplitude) -{ - int i; - MY_FLOAT temp; - for (i=0;i<4;i++) { - if (ratios[i] < 0) - temp = -ratios[i]; - else - temp = ratios[i] * baseFreq; - filters[i]->setFreqAndReson(temp,resons[i]*amplitude); - } -} - -void Modal4 :: controlChange(int number, MY_FLOAT value) -{ -} - -MY_FLOAT Modal4 :: tick() -{ - MY_FLOAT temp,temp2; - temp = masterGain * onepole->tick(wave->tick() * envelope->tick()); - temp2 = filters[0]->tick(temp); - temp2 += filters[1]->tick(temp); - temp2 += filters[2]->tick(temp); - temp2 += filters[3]->tick(temp); - temp2 = temp2 - (temp2 * directGain); - temp2 += directGain * temp; - - if (vibrGain != 0.0) { - temp = (MY_FLOAT) 1.0 + (vibr->tick() * vibrGain); /* Calculate AM */ - temp2 = temp * temp2; /* and apply to master out */ - } - - lastOutput = temp2 * (MY_FLOAT) 2.0; - return lastOutput; -} - diff --git a/STK/Modal4.h b/STK/Modal4.h deleted file mode 100644 index 2758649..0000000 --- a/STK/Modal4.h +++ /dev/null @@ -1,51 +0,0 @@ -/*******************************************/ -/* 4 Resonance Modal Synthesis Instrument */ -/* by Perry R. Cook, 1995-96 */ -/* This instrument contains an excitation */ -/* wavetable, an envelope, and four reso- */ -/* nances (Non-Sweeping BiQuad Filters). */ -/*******************************************/ - -#if !defined(__Modal4_h) -#define __Modal4_h - -#include "Instrmnt.h" -#include "Envelope.h" -#include "RawWvIn.h" -#include "BiQuad.h" -#include "OnePole.h" - -class Modal4 : public Instrmnt -{ - protected: - Envelope *envelope; - RawWvIn *wave; - BiQuad *filters[4]; - OnePole *onepole; - RawWvIn *vibr; - MY_FLOAT vibrGain; - MY_FLOAT masterGain; - MY_FLOAT directGain; - MY_FLOAT stickHardness; - MY_FLOAT strikePosition; - MY_FLOAT baseFreq; - MY_FLOAT ratios[4]; - MY_FLOAT resons[4]; - public: - Modal4(); - virtual ~Modal4(); - void clear(); - virtual void setFreq(MY_FLOAT frequency); - void setRatioAndReson(int whichOne, MY_FLOAT ratio, MY_FLOAT reson); - void setMasterGain(MY_FLOAT aGain); - void setDirectGain(MY_FLOAT aGain); - void setFiltGain(int whichOne, MY_FLOAT gain); - virtual void strike(MY_FLOAT amplitude); - virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp); - virtual void noteOff(MY_FLOAT amp); - void damp(MY_FLOAT amplitude); - virtual void controlChange(int number, MY_FLOAT value); - virtual MY_FLOAT tick(); -}; - -#endif diff --git a/STK/Object.cpp b/STK/Object.cpp deleted file mode 100644 index d2f4b07..0000000 --- a/STK/Object.cpp +++ /dev/null @@ -1,23 +0,0 @@ -/*******************************************/ -/* Object Class, by Perry R. Cook, 1995-96*/ -/* This is mostly here for compatibility */ -/* with Objective C. We'll also stick */ -/* global defines here, so everyone will */ -/* see them. */ -/*******************************************/ - -#include "Object.h" -// #include "byteswap.c" - -/* This is just here for compatibility and convenience, - so there's no need to do any real calculations. - I do set up some redefinable variables here. */ - -Object :: Object() -{ -} - -Object :: ~Object() -{ -} - diff --git a/STK/OnePole.cpp b/STK/OnePole.cpp deleted file mode 100644 index fd096d4..0000000 --- a/STK/OnePole.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/*******************************************/ -/* One Pole Filter Class, */ -/* by Perry R. Cook, 1995-96 */ -/* The parameter gain is an additional */ -/* gain parameter applied to the filter */ -/* on top of the normalization that takes */ -/* place automatically. So the net max */ -/* gain through the system equals the */ -/* value of gain. sgain is the combina- */ -/* tion of gain and the normalization */ -/* parameter, so if you set the poleCoeff */ -/* to alpha, sgain is always set to */ -/* gain * (1.0 - fabs(alpha)). */ -/*******************************************/ - -#include "OnePole.h" - -OnePole :: OnePole() : Filter() -{ - poleCoeff = (MY_FLOAT) 0.9; - gain = (MY_FLOAT) 1.0; - sgain = (MY_FLOAT) 0.1; - outputs = (MY_FLOAT *) malloc(sizeof(MY_FLOAT)); - outputs[0] = (MY_FLOAT) 0.0; -} - -OnePole :: ~OnePole() -{ - free(outputs); -} - -void OnePole :: clear() -{ - outputs[0] = (MY_FLOAT) 0.0; - lastOutput = (MY_FLOAT) 0.0; -} - -void OnePole :: setPole(MY_FLOAT aValue) -{ - poleCoeff = aValue; - if (poleCoeff > 0.0) // Normalize gain to 1.0 max - sgain = gain * ((MY_FLOAT) 1.0 - poleCoeff); - else - sgain = gain * ((MY_FLOAT) 1.0 + poleCoeff); -} - -void OnePole :: setGain(MY_FLOAT aValue) -{ - gain = aValue; - if (poleCoeff > 0.0) - sgain = gain * ((MY_FLOAT) 1.0 - poleCoeff); // Normalize gain to 1.0 max - else - sgain = gain * ((MY_FLOAT) 1.0 + poleCoeff); -} - -MY_FLOAT OnePole :: tick(MY_FLOAT sample) // Perform Filter Operation -{ - outputs[0] = (sgain * sample) + (poleCoeff * outputs[0]); - lastOutput = outputs[0]; - return lastOutput; -} - diff --git a/STK/OnePole.h b/STK/OnePole.h deleted file mode 100644 index 282e7fa..0000000 --- a/STK/OnePole.h +++ /dev/null @@ -1,35 +0,0 @@ -/*******************************************/ -/* One Pole Filter Class, */ -/* by Perry R. Cook, 1995-96 */ -/* The parameter gain is an additional */ -/* gain parameter applied to the filter */ -/* on top of the normalization that takes */ -/* place automatically. So the net max */ -/* gain through the system equals the */ -/* value of gain. sgain is the combina- */ -/* tion of gain and the normalization */ -/* parameter, so if you set the poleCoeff */ -/* to alpha, sgain is always set to */ -/* gain * (1.0 - fabs(alpha)). */ -/*******************************************/ - -#if !defined(__OnePole_h) -#define __OnePole_h - -#include "Filter.h" - -class OnePole : public Filter -{ - protected: - MY_FLOAT poleCoeff; - MY_FLOAT sgain; - public: - OnePole(); - ~OnePole(); - void clear(); - void setPole(MY_FLOAT aValue); - void setGain(MY_FLOAT aValue); - MY_FLOAT tick(MY_FLOAT sample); -}; - -#endif diff --git a/STK/RTSoundIO.cpp b/STK/RTSoundIO.cpp deleted file mode 100644 index 4f73734..0000000 --- a/STK/RTSoundIO.cpp +++ /dev/null @@ -1,965 +0,0 @@ -/******************************************/ -/* RTSoundIO.cpp */ -/* Realtime Sound I/O Object for STK, */ -/* by Gary P. Scavone, 1998-1999. */ -/* */ -/* The sound output sections of this */ -/* object were based in part on code */ -/* by Doug Scott (SGI), Tim Stilson */ -/* (Linux), Bill Putnam (Win Wav), and */ -/* R. Marsanyi (DirectSound). */ -/* */ -/* This object provides a standard API */ -/* across all platforms for STK realtime */ -/* audio input/output. The sound output */ -/* code is fairly robust. Audio input, */ -/* however, is more dependent on the */ -/* capabilities of the particular OS and */ -/* the soundcard being used. For the */ -/* moment, I'll try to provide 1 and 2 */ -/* channel support. */ -/* */ -/* 16-bit integer audio input/output */ -/* data is being assumed. */ -/******************************************/ - -#include "RTSoundIO.h" - -#if (defined(__STK_REALTIME_) && defined(__OS_IRIX_)) - -#include -#include -#include - -RTSoundIO :: RTSoundIO(MY_FLOAT srate, int channels, char *mode) -{ - ALconfig audio_port_config; - int lookaheadbuffers = 8; // number of lookahead buffers - long pvbuf[4]; - int nbuf, totalBufSize; - - /* Check the number of channels */ - if (channels > 2) { - fprintf(stderr,"RTSoundIO: Unsupported # of audio i/o channels: %d\n", channels); - exit(0); - } - - /* Create ALconfig structure */ - audio_port_config = ALnewconfig(); - if (!audio_port_config) { - fprintf(stderr,"Couldn't create ALconfig:%s\n", alGetErrorString(oserror())); - exit(0); - } - - /* Configure channels */ - if(ALsetchannels(audio_port_config, channels) < 0) { - fprintf(stderr,"Cannot configure channels: %s\n", alGetErrorString(oserror())); - exit(0); - } - - /* Size the output queue */ - nbuf = (channels == 2) ? lookaheadbuffers : lookaheadbuffers/2; - totalBufSize = RT_BUFFER_SIZE * nbuf; - if(ALsetqueuesize(audio_port_config, totalBufSize) < 0) { - fprintf(stderr,"Cannot configure output queue size: %s\n", alGetErrorString(oserror())); - exit(0); - } - - if (!strcmp(mode,"play")) { // playback only - - /* Open the output audio port */ - audio_port_out = ALopenport("STK output port", "w", audio_port_config); - if(!audio_port_out) { - fprintf(stderr,"Cannot initialize output audio port: %s\n", alGetErrorString(oserror())); - exit(0); - } - - /* Set sample rate parameters */ - pvbuf[0] = AL_OUTPUT_RATE; - pvbuf[1] = (long) srate; - ALsetparams(AL_DEFAULT_DEVICE, pvbuf, 2); /* set output SR */ - - /* Tell port to accept refill at buffers - 1 */ - ALsetfillpoint(audio_port_out,RT_BUFFER_SIZE * (lookaheadbuffers - 1)); - audio_port_in = 0; - } - else if (!strcmp(mode,"record")) { // record only - - /* Open the input audio port */ - audio_port_in = ALopenport("STK input port", "r", audio_port_config); - if(!audio_port_in) { - fprintf(stderr,"Cannot initialize input audio port: %s\n", alGetErrorString(oserror())); - exit(0); - } - - /* Set sample rate parameters */ - pvbuf[0] = AL_OUTPUT_RATE; - pvbuf[1] = (long) srate; - ALsetparams(AL_DEFAULT_DEVICE, pvbuf, 2); /* set input SR */ - - /* tell port to accept refill at buffers - 1 */ - ALsetfillpoint(audio_port_in,RT_BUFFER_SIZE * (lookaheadbuffers - 1)); - audio_port_out = 0; - } - else if (!strcmp(mode,"duplex")) { // duplex mode - - /* Open the output audio port */ - audio_port_out = ALopenport("STK output port", "w", audio_port_config); - if(!audio_port_out) { - fprintf(stderr,"Cannot initialize output audio port: %s\n", alGetErrorString(oserror())); - exit(0); - } - - /* Open the input audio port */ - audio_port_in = ALopenport("STK input port", "r", audio_port_config); - if(!audio_port_in) { - fprintf(stderr,"Cannot initialize input audio port: %s\n", alGetErrorString(oserror())); - exit(0); - } - - /* Set sample rate parameters */ - pvbuf[0] = AL_OUTPUT_RATE; - pvbuf[1] = (long) srate; - pvbuf[2] = AL_INPUT_RATE; - pvbuf[3] = (long) srate; - ALsetparams(AL_DEFAULT_DEVICE, pvbuf, 4); /* set output SR */ - /* tell port to accept refill at buffers - 1 */ - ALsetfillpoint(audio_port_out,RT_BUFFER_SIZE * (lookaheadbuffers - 1)); - ALsetfillpoint(audio_port_in,RT_BUFFER_SIZE * (lookaheadbuffers - 1)); - } - else { - fprintf(stderr,"Unsupported RTSoundIO mode: %s\n",mode); - exit(0); - } - - ALfreeconfig(audio_port_config); - audio_port_config = 0; -} - -RTSoundIO :: ~RTSoundIO() -{ - if(audio_port_out) ALcloseport(audio_port_out); - audio_port_out=0; - - if(audio_port_in) ALcloseport(audio_port_in); - audio_port_in=0; -} - -int RTSoundIO :: playBuffer(short *buf, int bufsize) -{ - ALwritesamps(audio_port_out, buf, bufsize); - return 0; -} - -int RTSoundIO :: recordBuffer(short *buf, int bufsize) -{ - ALreadsamps(audio_port_in, buf, bufsize); - return 0; -} - - -/* Linux OSS Sound API here */ - -#elif (defined(__STK_REALTIME_) && defined(__OSS_API_)) - -#define ABS(x) ((x < 0) ? (-x) : (x)) - -#include -#include -#include -#include -#include - -RTSoundIO :: RTSoundIO(MY_FLOAT srate, int channels, char *mode) -{ - int lookaheadbuffers = 8; // number of lookahead buffers - int nbuf; - - char DEVICE_NAME[100]; - int format; - int stereo; /* 0=mono, 1=stereo */ - int stereoset; - int speed; - int BUFFER_SIZE_LOG; - int fragsize; - - BUFFER_SIZE_LOG = (int)(log10((double)RT_BUFFER_SIZE)/log10(2.0)); - - /* Check the number of channels */ - if (channels > 2) { - fprintf(stderr,"RTSoundIO: Unsupported # of audio i/o channels: %d\n", channels); - exit(0); - } - - if (channels == 2) stereo = 1; - else stereo = 0; - - strcpy(DEVICE_NAME,"/dev/dsp"); - - if (!strcmp(mode,"play")) { // playback only - if ((audio_fd = open(DEVICE_NAME, O_WRONLY, 0)) == -1) - { /* Opening device failed */ - fprintf(stderr,"Cannot open audio device: %s\n",DEVICE_NAME); - exit(0); - } - } - else if (!strcmp(mode,"record")) { // record only - if ((audio_fd = open(DEVICE_NAME, O_RDONLY, 0)) == -1) - { /* Opening device failed */ - fprintf(stderr,"Cannot open audio device: %s\n",DEVICE_NAME); - exit(0); - } - } - else if (!strcmp(mode,"duplex")) { // duplex mode - if ((audio_fd = open(DEVICE_NAME, O_RDWR, 0)) == -1) - { /* Opening device failed */ - fprintf(stderr,"Cannot open audio device: %s\n",DEVICE_NAME); - exit(0); - } - int caps; - if (ioctl(audio_fd, SNDCTL_DSP_GETCAPS, &caps)) - { - close(audio_fd); - fprintf(stderr,"Error getting device capabilities: %s\n",DEVICE_NAME); - exit(0); - } - if (!(caps & DSP_CAP_DUPLEX)) - { - close(audio_fd); - fprintf(stderr,"Audio device does not support duplex mode: %s\n",DEVICE_NAME); - exit(0); - } - if (ioctl(audio_fd, SNDCTL_DSP_SETDUPLEX, 0)) - { - close(audio_fd); - fprintf(stderr,"Error setting duplex mode: %s\n",DEVICE_NAME); - exit(0); - } - int cursrc, srcbit = SOUND_MASK_MIC; - ioctl(audio_fd, MIXER_READ(SOUND_MIXER_RECSRC),&cursrc); - srcbit = (srcbit & cursrc); - ioctl(audio_fd,MIXER_WRITE(SOUND_MIXER_RECSRC),&srcbit); - - // The following opens a direct analog line from the mic to the output - //srcbit = 99; - //ioctl(audio_fd,MIXER_WRITE(SOUND_MIXER_IMIX),&srcbit); - } - else { - fprintf(stderr,"Unsupported RTSoundIO mode: %s\n",mode); - exit(0); - } - - /* Size the output queue */ - nbuf = (channels == 2) ? lookaheadbuffers : lookaheadbuffers/2; - - fragsize = (nbuf << 16) + BUFFER_SIZE_LOG; - if (ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &fragsize)) - { - close(audio_fd); - fprintf(stderr,"Error setting audio buffer size!\n"); - exit(0); - } - - format = AFMT_S16_LE; - if (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &format)==-1) - { /* Fatal error */ - close(audio_fd); - fprintf(stderr,"SNDCTL_DSP_SETFMT error\n"); - exit(0); - } - - if (format != AFMT_S16_LE) - { - close(audio_fd); - fprintf(stderr,"Audio device doesn't support 16-bit signed LE format\n"); - exit(0); - } - - stereoset = stereo; - if (ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereoset)==-1) - { /* Fatal error */ - close(audio_fd); - fprintf(stderr,"SNDCTL_DSP_STEREO\n"); - exit(0); - } - - if (stereoset != stereo) - { - close(audio_fd); - fprintf(stderr,"The audio device did not set correct stereo mode: %s\n",DEVICE_NAME); - exit(0); - } - - speed = (int)srate; - if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &speed)==-1) - { /* Fatal error */ - close(audio_fd); - fprintf(stderr,"SNDCTL_DSP_SPEED\n"); - exit(0); - } - - if (ABS(speed - srate)>100) - { - close(audio_fd); - fprintf(stderr,"The device doesn't support the requested speed.\n"); - exit(0); - } -} - -RTSoundIO :: ~RTSoundIO() -{ - if(audio_fd) close(audio_fd); - audio_fd=0; -} - -int RTSoundIO :: playBuffer(short *buf, int bufsize) -{ - /* The OSS write() routine takes the buffer size in bytes, thus the - multiplication by two. - */ - int len; - - if ((len = write(audio_fd, buf, 2*bufsize)) == -1) - { - fprintf(stderr,"Audio write error!\n"); - return -1; - } - return 0; -} - -int RTSoundIO :: recordBuffer(short *buf, int bufsize) -{ - /* The OSS read() routine takes the buffer size in bytes, thus the - multiplication by two. - */ - int len; - - if ((len = read(audio_fd, buf, 2*bufsize)) == -1) - { - fprintf(stderr,"Audio read error!\n"); - return -1; - } - return 0; -} - - -#elif (defined(__STK_REALTIME_) && defined(__WINDS_API_) ) -/* - * AUDIO OUTPUT: - * - * There are two ways (or more) to go about handling sound output - * under DirectSound. For minimum latency, one should write new - * buffers in front of the read pointer (Method 1). The other - * method is to always write new buffers of data behind the read - * pointer (Method 2). Method 2 is very safe but inherently - * produces a delay equivalent to the entire sound buffer (plus - * any other delays that Microsloth provides). Even using - * Method 1, however, Microsloth requires that you leave about - * 15 ms of buffer between the read and write pointers. I've tried - * both methods and neither results in performance that can compare - * to either Linux or SGI sound output. In order to minimize - * latency, however, I'll go with Method 1 and leave Method 2 - * commented out below. - * - * If the primary sound buffer exists in hardware, I will write - * directly to it. If the primary sound buffer is emulated in - * software, this is not possible and we must use a secondary buffer. - * - * AUDIO INPUT: - * - * I didn't spend a lot of time doing the audio input code. I - * basically got it working, heard that it had noticeable delay, - * but didn't try screwing around to minimize that delay. I provide - * a single variable (at the beginning of the Capture initialization) - * which controls the size of the DirectSound Capture buffer, which - * in turn controls the latency. - * - * The DirectSoundCapture API is only available with DirectX versions - * 5.0 and higher. If you don't have such capabilities (ex. WinNT), - * then use the WinMM API code (uncomment the __WINMM_API_ define - * statement in Object.h and comment out the __WINDS_API_ flag). This - * will allow you to still compile STK, but without the audio input - * capabilities. - */ - -#define DS_WRITE_METHOD 1 - -#include - -RTSoundIO :: RTSoundIO(MY_FLOAT srate, int channels, char *mode) -{ - HRESULT result; - WAVEFORMATEX wfFormat; - BYTE *pAudioPtr; - DWORD dwDataLen; - - // Initialize the DirectSound object and buffer pointers to NULL - lpDirectSound = NULL; - lpDSBuffer = NULL; - lpDSCapture = NULL; - lpDSCBuffer = NULL; - - // Define the wave format structure (16-bit PCM, srate, channels) - ZeroMemory(&wfFormat, sizeof(WAVEFORMATEX)); - wfFormat.wFormatTag = WAVE_FORMAT_PCM; - wfFormat.nChannels = channels; - wfFormat.nSamplesPerSec = (unsigned long) srate; - wfFormat.wBitsPerSample = 8 * sizeof(short); - wfFormat.nBlockAlign = wfFormat.nChannels * wfFormat.wBitsPerSample / 8; - wfFormat.nAvgBytesPerSec = wfFormat.nSamplesPerSec * wfFormat.nBlockAlign; - - if ( (!strcmp(mode,"play")) || (!strcmp(mode,"duplex")) ) { - DSBUFFERDESC dsbdesc; - HWND hWnd; - - // If using Method 1: - // Define a maximum distance that the write pointer is - // allowed to lead safePos. The size of this zone is - // fairly critical to the behavior of this scheme. The - // value below is set for a 15 millisecond region. - zoneSize = (DWORD) (0.015 * srate * sizeof(short)); // bytes - - // Create the DS object - if ((result = DirectSoundCreate(NULL, &lpDirectSound, NULL)) != DS_OK) { - fprintf(stderr,"RTSoundIO: Cannot open default sound output device!!\n"); - exit(0); - } - - // Get DS device capabilites - DSCAPS dscaps; - ZeroMemory(&dscaps, sizeof(DSCAPS)); - dscaps.dwSize = sizeof(DSCAPS); - if ((result = lpDirectSound->GetCaps(&dscaps)) != DS_OK) { - fprintf(stderr,"RTSoundIO: Cannot get DS device capabilities!!\n"); - exit(0); - } - - // Determine whether primary buffer exists in hardware or software - if (dscaps.dwFlags & DSCAPS_EMULDRIVER) { // Write to secondary buffer - - // Number of buffers of size RT_BUFFER_SIZE to make secondary - // DS buffer. A larger secondary buffer does NOT produce more - // output delay when the write pointer is kept in front of the - // read pointer (Method 1). However, if you use Method 2, this - // variable will be more critical and you'll probably want to - // make it smaller. - int nBufs = 12; - - // Set coooperative level - hWnd = GetForegroundWindow(); - if ((result = lpDirectSound->SetCooperativeLevel(hWnd, DSSCL_EXCLUSIVE)) != DS_OK) { - fprintf(stderr,"RTSoundIO: Couldn't set EXCLUSIVE cooperative level!\n"); - exit(0); - } - - // Even though we will write to the secondary buffer, we need - // to access the primary buffer to set the correct output format. - // The default is 8-bit, 22 kHz! - LPDIRECTSOUNDBUFFER lpdsbPrimary; - - // Setup the DS primary buffer description. - ZeroMemory(&dsbdesc, sizeof(DSBUFFERDESC)); - dsbdesc.dwSize = sizeof(DSBUFFERDESC); - dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER; - - // Obtain the primary buffer - if ((result = lpDirectSound->CreateSoundBuffer(&dsbdesc, - &lpdsbPrimary, NULL)) != DS_OK) { - fprintf(stderr,"RTSoundIO: Cannot get the primary DS buffer address!\n"); - exit(0); - } - - // Set the primary DS buffer sound format. - if ((result = lpdsbPrimary->SetFormat(&wfFormat)) != DS_OK) { - fprintf(stderr,"RTSoundIO: Cannot set the primary DS buffer to proper sound format!\n"); - exit(0); - } - - // Setup the secondary DS buffer description. - dwDSBufSize = RT_BUFFER_SIZE * sizeof(short) * nBufs; - ZeroMemory(&dsbdesc, sizeof(DSBUFFERDESC)); - dsbdesc.dwSize = sizeof(DSBUFFERDESC); - dsbdesc.dwFlags = DSBCAPS_STICKYFOCUS | DSBCAPS_GETCURRENTPOSITION2; - dsbdesc.dwBufferBytes = dwDSBufSize; - dsbdesc.lpwfxFormat = &wfFormat; - - // Try to create the secondary DS buffer. - if ((result = lpDirectSound->CreateSoundBuffer(&dsbdesc, &lpDSBuffer, NULL)) != DS_OK) { - fprintf(stderr,"RTSoundIO: Couldn't create the DS sound buffer!\n"); - exit(0); - } - } - else { // Write to primary buffer - - // Setup the DS primary buffer description. - ZeroMemory(&dsbdesc, sizeof(DSBUFFERDESC)); - dsbdesc.dwSize = sizeof(DSBUFFERDESC); - dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_STICKYFOCUS; - // Buffer size is determined by sound hardware - dsbdesc.dwBufferBytes = 0; - dsbdesc.lpwfxFormat = NULL; // Must be NULL for primary buffer. - - // Obtain write-primary coooperative level. - hWnd = GetForegroundWindow(); - if ((result = lpDirectSound->SetCooperativeLevel(hWnd, DSSCL_WRITEPRIMARY)) != DS_OK) { - fprintf(stderr,"RTSoundIO: Couldn't set WRITEPRIMARY cooperative level!\n"); - exit(0); - } - - // Try to create the primary DS buffer. - if ((result = lpDirectSound->CreateSoundBuffer(&dsbdesc, &lpDSBuffer, NULL)) != DS_OK) { - fprintf(stderr,"RTSoundIO: Couldn't create the DS sound buffer!\n"); - exit(0); - } - - // Set primary DS buffer to desired format. - if ((result = lpDSBuffer->SetFormat(&wfFormat)) != DS_OK) { - fprintf(stderr,"RTSoundIO: Couldn't set correct format!\n"); - exit(0); - } - } - // Get the buffer size - DSBCAPS dsbcaps; - dsbcaps.dwSize = sizeof(DSBCAPS); - lpDSBuffer->GetCaps(&dsbcaps); - dwDSBufSize = dsbcaps.dwBufferBytes; - - // Lock the DS buffer - if ((result = lpDSBuffer->Lock(0, dwDSBufSize, (LPLPVOID) &pAudioPtr, &dwDataLen, NULL, NULL, 0)) != DS_OK) { - fprintf(stderr,"RTSoundIO: Couldn't lock DS sound buffer!\n"); - exit(0); - } - - // Zero the DS buffer - ZeroMemory(pAudioPtr, dwDataLen); - - // Unlock the DS buffer - if ((result = lpDSBuffer->Unlock(pAudioPtr, dwDataLen, NULL, 0)) != DS_OK) { - fprintf(stderr,"RTSoundIO: Couldn't unlock DS sound buffer!\n"); - exit(0); - } - } // end of play/duplex initialization - - if ( (!strcmp(mode,"record")) || (!strcmp(mode,"duplex")) ) { - // DirectSound Capture capabilities require DirectX 5.0 or higher - - // The following variable controls the size of the DS Capture - // buffer, which in turns controls the latency in the capture - // process. When dscbufscale = 1, the buffer is equivalent to - // one second of audio. A dscbufscale = 0.5 halves this value. - // Likewise, a dscbufscale = 2 doubles this value. It seems to - // work OK with dscbufscale = 0.5, but there is a periodic - // "clicking" which sometimes occurs. You can go lower, but - // the "clicking" gets worse. Good luck! Yet another reason - // why not to use Windoze. - float dscbufscale = 0.5; - - // Create the DS Capture object - if ((result = DirectSoundCaptureCreate(NULL, &lpDSCapture, NULL)) != DS_OK) { - fprintf(stderr,"RTSoundIO: Couldn't open DirectSoundCapture Object!\n"); - fprintf(stderr,"RTSoundIO: Requires DirectX 5 or later.\n"); - exit(0); - } - - // Setup the DS Capture buffer description - DSCBUFFERDESC dscbdesc; - ZeroMemory(&dscbdesc, sizeof(DSCBUFFERDESC)); - dscbdesc.dwSize = sizeof(DSCBUFFERDESC); - dscbdesc.dwFlags = 0; - // Control size of DS Capture buffer here - dwDSCBufSize = (DWORD)(wfFormat.nAvgBytesPerSec*dscbufscale); - dscbdesc.dwBufferBytes = dwDSCBufSize; - dscbdesc.dwReserved = 0; - dscbdesc.lpwfxFormat = &wfFormat; - - // Create the DS Capture buffer - if ((result = lpDSCapture->CreateCaptureBuffer(&dscbdesc, &lpDSCBuffer, NULL)) != DS_OK) { - fprintf(stderr,"RTSoundIO: Couldn't create DirectSoundCapture buffer!\n"); - if (result == DSERR_BADFORMAT) { - fprintf(stderr,"RTSoundIO: The input device could not support the desired\n"); - fprintf(stderr,"sample rate (%f), bits per sample (16),\n", srate); - fprintf(stderr,"and/or number of channels (%d).\n", channels); - } - exit(0); - } - - // Lock the DS Capture buffer - if ((result = lpDSCBuffer->Lock(0, dwDSCBufSize, (LPLPVOID) &pAudioPtr, &dwDataLen, NULL, NULL, 0)) != DS_OK) { - fprintf(stderr,"RTSoundIO: Couldn't lock DS Capture sound buffer!\n"); - exit(0); - } - - // Zero the DS Capture buffer - ZeroMemory(pAudioPtr, dwDataLen); - - // Unlock the DS Capture buffer - if ((result = lpDSCBuffer->Unlock(pAudioPtr, dwDataLen, NULL, 0)) != DS_OK) { - fprintf(stderr,"RTSoundIO: Couldn't unlock DS Capture sound buffer!\n"); - exit(0); - } - - // Start the DS Capture buffer input - if ((result = lpDSCBuffer->Start(DSCBSTART_LOOPING) != DS_OK)) { - fprintf(stderr,"RTSoundIO: Couldn't start DS Capture sound input!\n"); - exit(0); - } - } // end of record/duplex initialization - - if ( (!strcmp(mode,"play")) || (!strcmp(mode,"duplex")) ) { - // Start the DS buffer playback - if ((result = lpDSBuffer->Play(0, 0, DSBPLAY_LOOPING ) != DS_OK)) { - fprintf(stderr,"RTSoundIO: Couldn't play DS sound buffer!\n"); - exit(0); - } - } -} - -RTSoundIO :: ~RTSoundIO() -{ - // Cleanup the DS buffers - if (lpDSBuffer) { - lpDSBuffer->Stop(); - lpDSBuffer->Release(); - lpDSBuffer = NULL; - } - if (lpDSCBuffer) { - lpDSCBuffer->Stop(); - lpDSCBuffer->Release(); - lpDSCBuffer = NULL; - } - - // Cleanup the DS objects - if (lpDirectSound) { - lpDirectSound->Release(); - lpDirectSound = NULL; - } - if (lpDSCapture) { - lpDSCapture->Release(); - lpDSCapture = NULL; - } -} - -int RTSoundIO :: playBuffer(short *buf, int bufsize) -{ - HRESULT hr; - LPVOID lpbuf1 = NULL; - LPVOID lpbuf2 = NULL; - DWORD dwsize1 = 0; - DWORD dwsize2 = 0; - DWORD playPos, safePos; - static UINT nextWritePos = 0; - - // Find out where the read and "safe write" pointers are. - hr = lpDSBuffer->GetCurrentPosition(&playPos, &safePos); - if (hr != DS_OK) return -1; - - // METHOD 1: Keep write pointer in front of read pointer. - // - // Microsloth says that the safePos is about 15 ms ahead of - // playPos. I think this figure is somewhat hardware related, - // especially if you are writing to the primary buffer. With - // my shit-blaster 16, I found the safePos to be about 10 ms - // ahead of playPos. If you really need to reduce delay, you - // can try moving your "safePos" closer to the play pointer. - // You'll be treading on dangerous ground, but then again, - // you're obviously using Windoze so you're already familiar - // with such uncertainty! I've been able to lop off 2-5 ms - // in some circumstances. - //static DWORD backup = (DWORD) (0.005 * SRATE * sizeof(short)); - //safePos = (safePos + dwDSBufSize - backup) % dwDSBufSize; - - // Assume that the next write position is always in front - // of safePos. If not, the write pointer must have wrapped. - // NOTE: If safePos somehow gets ahead of the write pointer, - // then an underrun has occurred and there's not much we can - // do anyway. - DWORD deltaPos; - if( safePos > nextWritePos ) - deltaPos = nextWritePos + dwDSBufSize - safePos; - else - deltaPos = nextWritePos - safePos; - - // Check whether the write pointer is in the allowed region. - while ( deltaPos > zoneSize ) { - // If we are here, then we must wait until the write pointer - // is in the allowed region. For this, we can either - // continuously check the pointer positions until they are - // OK or we can use the Sleep() function to pause operations - // for a certain amount of time. Use of the Sleep() function - // would seem to be the better choice, however, there are - // reports that Sleep() often "sleeps" for much longer than - // requested. I'll let you choose which method to use. - static int sleep = 1; // 1 = sleep, 0 = don't sleep - - if (sleep) { - // Sleep until safePos catches up. Calculate number of - // milliseconds to wait as: - // time = distance * (milliseconds/second) * fudgefactor / - // ((bytes/sample) * (samples/second)) - // A "fudgefactor" less than 1 is used because it was found - // that sleeping too long was MUCH worse than sleeping for - // several shorter periods. - DWORD millis = (DWORD) ((deltaPos * 200.0) / ( sizeof(short) * SRATE)); - - // Sleep for that long - Sleep( millis ); - } - - // Wake up, find out where we are now - hr = lpDSBuffer->GetCurrentPosition( &playPos, &safePos ); - if( hr != DS_OK ) return -1; - - // Backup safePos? (See above) - //safePos = (safePos + dwDSBufSize - backup) % dwDSBufSize; - - if( safePos > nextWritePos ) - deltaPos = nextWritePos + dwDSBufSize - safePos; - else - deltaPos = nextWritePos - safePos; - } - // End of Method 1 - - /* - // METHOD 2: Keep write region behind of play pointer. - if( playPos < nextWritePos ) playPos += dwDSBufSize; // unwrap offset - DWORD endWrite = nextWritePos + bufsize * sizeof(short); - - // Check whether the write region is behind the play pointer. - while ( playPos < endWrite ) { - // If we are here, then we must wait until the play pointer - // gets beyond the write region. For this, we can either - // continuously check the pointer positions until they are - // OK or we can use the Sleep() function to pause operations - // for a certain amount of time. Use of the Sleep() function - // would seem to be the better choice, however, there are - // reports that Sleep() often "sleeps" for much longer than - // requested. I'll let you choose which method to use. - static int sleep = 1; // 1 = sleep, 0 = don't sleep - - if (sleep) { - // Sleep until safePos catches up. Calculate number of - // milliseconds to wait as: - // time = distance * (milliseconds/second) * fudgefactor / - // ((bytes/sample) * (samples/second)) - // A "fudgefactor" less than 1 is used because it was found - // that sleeping too long was MUCH worse than sleeping for - // several shorter periods. - DWORD millis = (DWORD) (((endWrite - playPos) * 200.0) / ( sizeof(short) * SRATE)); - - // Sleep for that long - Sleep( millis ); - } - - // Wake up, find out where we are now - hr = lpDSBuffer->GetCurrentPosition( &playPos, &safePos ); - if( hr != DS_OK ) return -1; - if( playPos < nextWritePos ) playPos += dwDSBufSize; // unwrap offset - } - // End of Method 2. - */ - - // Lock free space in the DS - hr = lpDSBuffer->Lock (nextWritePos, bufsize * sizeof(short), &lpbuf1, &dwsize1, &lpbuf2, &dwsize2, 0); - if (hr == DS_OK) { - // Copy the buffer into the DS - CopyMemory(lpbuf1, buf, dwsize1); - if(NULL != lpbuf2) CopyMemory(lpbuf2, buf+dwsize1, dwsize2); - - // Update our buffer offset and unlock sound buffer - nextWritePos = (nextWritePos + dwsize1 + dwsize2) % dwDSBufSize; - lpDSBuffer->Unlock (lpbuf1, dwsize1, lpbuf2, dwsize2); - return 0; - } - else return -1; -} - -int RTSoundIO :: recordBuffer(short *buf, int bufsize) -{ - HRESULT hr; - LPVOID lpbuf1 = NULL; - LPVOID lpbuf2 = NULL; - DWORD dwsize1 = 0; - DWORD dwsize2 = 0; - DWORD capPos, safePos; - static UINT nextReadPos = 0; - - // Find out where the write and "safe read" pointers are. - hr = lpDSCBuffer->GetCurrentPosition(&capPos, &safePos); - if (hr != DS_OK) return -1; - //printf("capPos = %d, safePos = %d\n", capPos, safePos); - - if( safePos < nextReadPos ) safePos += dwDSCBufSize; // unwrap offset - DWORD endRead = nextReadPos + bufsize * sizeof(short); - //printf("endRead = %d\n", endRead); - - // Check whether the read region is behind the capture pointer. - while ( safePos < endRead ) { - // If we are here, then we must wait until the read pointer - // gets beyond the write region. For this, we can either - // continuously check the pointer positions until they are - // OK or we can use the Sleep() function to pause operations - // for a certain amount of time. Use of the Sleep() function - // would seem to be the better choice, however, there are - // reports that Sleep() often "sleeps" for much longer than - // requested. I'll let you choose which method to use. - static int sleep = 1; // 1 = sleep, 0 = don't sleep - - if (sleep) { - // Sleep until safePos catches up. Calculate number of - // milliseconds to wait as: - // time = distance * (milliseconds/second) * fudgefactor / - // ((bytes/sample) * (samples/second)) - // A "fudgefactor" less than 1 is used because it was found - // that sleeping too long was MUCH worse than sleeping for - // several shorter periods. - DWORD millis = (DWORD) (((endRead - safePos) * 200.0) / ( sizeof(short) * SRATE)); - - // Sleep for that long - Sleep( millis ); - } - - // Wake up, find out where we are now - hr = lpDSCBuffer->GetCurrentPosition( &capPos, &safePos ); - if( hr != DS_OK ) return -1; - //printf("capPos = %d, safePos = %d\n", capPos, safePos); - if( safePos < nextReadPos ) safePos += dwDSCBufSize; // unwrap offset - } - //printf("how about here?\n"); - // Lock free space in the DS Capture buffer - hr = lpDSCBuffer->Lock(nextReadPos, bufsize * sizeof(short), &lpbuf1, &dwsize1, &lpbuf2, &dwsize2, 0); - if (hr == DS_OK) { - // Copy the DS Capture data to the buffer - CopyMemory(buf, lpbuf1, dwsize1); - if(NULL != lpbuf2) CopyMemory(buf+dwsize1, lpbuf2, dwsize2); - - // Update our buffer offset and unlock sound buffer - nextReadPos = (nextReadPos + dwsize1 + dwsize2) % dwDSCBufSize; - lpDSCBuffer->Unlock (lpbuf1, dwsize1, lpbuf2, dwsize2); - return 0; - } - else return -1; -} - -#elif (defined(__STK_REALTIME_) && defined(__WINMM_API_) ) - -#include - -#define FRAMETIME (long) (1000.0 * RT_BUFFER_SIZE / SRATE) - -RTSoundIO :: RTSoundIO(MY_FLOAT srate, int channels, char *mode) -{ - MMRESULT result; - WAVEFORMATEX wfx; - int bufferSize = RT_BUFFER_SIZE; - - audioPort = NULL; - - if ( (!strcmp(mode,"record")) || (!strcmp(mode,"duplex")) ) { - fprintf(stderr,"Sorry ... no audio input support under WinMM API!\n"); - exit(0); - } - - wfx.wFormatTag = WAVE_FORMAT_PCM; - wfx.nChannels = channels; - wfx.nSamplesPerSec = (unsigned long) srate; - wfx.nBlockAlign = sizeof(short) * channels; - wfx.nAvgBytesPerSec = (unsigned long) srate * wfx.nBlockAlign; - wfx.wBitsPerSample = 8 * sizeof(short); - wfx.cbSize = 0; - - /* Open a Wave Out device using the wave mapper to guide us */ - result = waveOutOpen(&audioPort,WAVE_MAPPER,&wfx,(DWORD)NULL,(DWORD)NULL,CALLBACK_NULL); - if (result != MMSYSERR_NOERROR) { - fprintf(stderr,"RTSoundIO: Cannot open audio port (WinMM API)!\n"); - exit(0); - } - - for( outBufNum = 0; outBufNum < (UINT)NUM_OUT_BUFFERS; outBufNum++ ) - { - /* set up a couple of wave headers */ - whOut[outBufNum].lpData = (LPSTR)calloc(channels*bufferSize, sizeof(short)); - if (whOut[outBufNum].lpData == NULL){ - waveOutClose( audioPort ); - fprintf(stderr,"RTSoundIO: Error initializing audio buffers (WinMM API)!\n"); - exit(0); - } - whOut[outBufNum].dwBufferLength = channels*bufferSize*sizeof(short); - whOut[outBufNum].dwBytesRecorded = 0; - whOut[outBufNum].dwUser = 1; - //whOut[outBufNum].dwFlags = 0; - whOut[outBufNum].dwFlags = WHDR_DONE; - whOut[outBufNum].dwLoops = 0; - whOut[outBufNum].lpNext = NULL; - whOut[outBufNum].reserved = 0; - } - - /* Write the first buffer out to get things going */ - outBufNum = 0; - result = waveOutPrepareHeader(audioPort, &whOut[outBufNum],sizeof(WAVEHDR)); - result = waveOutWrite(audioPort, &whOut[outBufNum], sizeof(WAVEHDR)); - - /* Keep track of time so that we know how long we can sleep */ - lastWriteTime = timeGetTime(); -} - -RTSoundIO :: ~RTSoundIO() -{ - MMRESULT result; - long timeToGo; - - /* Close Audio Port */ - if (audioPort != NULL) { - result = waveOutReset(audioPort); - for( outBufNum = 0; outBufNum < (UINT)NUM_OUT_BUFFERS; outBufNum++ ) - { - /* Loop until the next waveheader indicates that we are done */ - while( !(whOut[outBufNum].dwFlags & WHDR_DONE) ) - { - //printf("."); - timeToGo = (long) (FRAMETIME - (timeGetTime()-lastWriteTime)); - if( timeToGo > 0 ) Sleep( (long) timeToGo ); - } - /* Unprepare the header */ - result = waveOutUnprepareHeader(audioPort, &whOut[outBufNum],sizeof(WAVEHDR)); - if (whOut[outBufNum].lpData != NULL) { - free(whOut[outBufNum].lpData); - whOut[outBufNum].lpData = NULL; - } - } - result = waveOutClose(audioPort); - } -} - -int RTSoundIO :: playBuffer(short *buf, int bufsize) -{ - MMRESULT result; - long timeToGo; - - outBufNum++; - if( outBufNum >= (UINT)NUM_OUT_BUFFERS ) outBufNum = 0; - - /* Loop until the next waveheader indicates that we are done */ - while( !(whOut[outBufNum].dwFlags & WHDR_DONE) ) - { - //printf("."); - timeToGo = (long) (FRAMETIME - (timeGetTime()-lastWriteTime)); - //timeToGo = (long) (FRAMETIME * 0.5); - if( timeToGo > 0 ) Sleep( (long) timeToGo ); - } - result = waveOutUnprepareHeader(audioPort, &whOut[outBufNum], sizeof(WAVEHDR)); - - memcpy( whOut[outBufNum].lpData, buf, bufsize*sizeof(short)); - result = waveOutPrepareHeader(audioPort, &whOut[outBufNum], sizeof(WAVEHDR)); - result = waveOutWrite(audioPort, &whOut[outBufNum], sizeof(WAVEHDR)); - lastWriteTime = timeGetTime(); - - return 0; -} - -int RTSoundIO :: recordBuffer(short *buf, int bufsize) -{ - // There is no current support for audio input under the WinMM API ... sorry! - return -1; -} - -#endif diff --git a/STK/RTSoundIO.h b/STK/RTSoundIO.h deleted file mode 100644 index 7a2045d..0000000 --- a/STK/RTSoundIO.h +++ /dev/null @@ -1,71 +0,0 @@ -/******************************************/ -/* RTSoundIO.cpp */ -/* Realtime Sound I/O Object for STK, */ -/* by Gary P. Scavone, 1998-1999. */ -/* */ -/* The sound output sections of this */ -/* object were based in part on code */ -/* by Doug Scott (SGI), Tim Stilson */ -/* (Linux), Bill Putnam (Win Wav), and */ -/* R. Marsanyi (DirectSound). */ -/* */ -/* This object provides a standard API */ -/* across all platforms for STK realtime */ -/* audio input/output. The sound output */ -/* code is fairly robust. Audio input, */ -/* however, is more dependent on the */ -/* capabilities of the particular OS and */ -/* the soundcard being used. For the */ -/* moment, I'll try to provide 1 or 2 */ -/* channel support. */ -/* */ -/* 16-bit integer audio input/output */ -/* data is being assumed. */ -/******************************************/ - -#if !defined(__RTSOUNDIO_h) -#define __RTSOUNDIO_h - -#include "Object.h" - -#if defined(__OS_IRIX_) - #include -#elif defined(__WINDS_API_) - #include - #include -#elif defined(__WINMM_API_) - #include - #include - #define NUM_OUT_BUFFERS 6 -#endif - -class RTSoundIO : public Object -{ - protected: -#if (defined(__STK_REALTIME_) && defined(__OS_IRIX_)) - ALport audio_port_in; - ALport audio_port_out; -#elif (defined(__STK_REALTIME_) && defined(__OSS_API_)) - int audio_fd; -#elif (defined(__STK_REALTIME_) && defined(__WINDS_API_) ) - LPDIRECTSOUND lpDirectSound; - LPDIRECTSOUNDBUFFER lpDSBuffer; - DWORD dwDSBufSize; - DWORD zoneSize; - LPDIRECTSOUNDCAPTURE lpDSCapture; - LPDIRECTSOUNDCAPTUREBUFFER lpDSCBuffer; - DWORD dwDSCBufSize; -#elif (defined(__STK_REALTIME_) && defined(__WINMM_API_) ) - HWAVEOUT audioPort; - WAVEHDR whOut[NUM_OUT_BUFFERS]; - UINT outBufNum; - DWORD lastWriteTime; -#endif - public: - RTSoundIO(MY_FLOAT srate, int channels, char *mode); - ~RTSoundIO(); - int playBuffer(short *buf, int bufsize); - int recordBuffer(short *buf, int bufsize); -}; - -#endif diff --git a/STK/RTWvIn.cpp b/STK/RTWvIn.cpp deleted file mode 100644 index 194fb12..0000000 --- a/STK/RTWvIn.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/*******************************************/ -/* RTWvIn Input Class, */ -/* by Gary P. Scavone, 1999 */ -/* */ -/* This object inherits from WvIn and is */ -/* used to read in realtime 16-bit data */ -/* from a computer's audio port. */ -/* */ -/* NOTE: This object is NOT intended for */ -/* use in achieving simultaneous realtime */ -/* audio input/output (together with */ -/* RTWvOut). Under certain circumstances */ -/* such a scheme is possible, though you */ -/* should definitely know what you are */ -/* doing before trying. For safer "full- */ -/* duplex" operation, use the RTDuplex */ -/* class. */ -/*******************************************/ - -#include "RTWvIn.h" - -RTWvIn :: RTWvIn(MY_FLOAT srate, short chans) -{ - soundIO = new RTSoundIO(srate, chans, "record"); - channels = chans; - length = RT_BUFFER_SIZE/channels; - data = 0; - rtdata = (short *) new short[RT_BUFFER_SIZE+channels]; - - this->getMoreData(); - - rate = (MY_FLOAT) srate / SRATE; - if (fmod(rate, 1.0) > 0.0) interpolate = 1; - else interpolate = 0; - looping = 0; - time = (MY_FLOAT) 0.0; - phaseOffset = (MY_FLOAT) 0.0; - finished = 0; - lastOutput = (MY_FLOAT *) calloc(channels, sizeof(MY_FLOAT)); - gain = 0.00003052; -#if (defined(__STK_REALTIME_) && defined(__OS_IRIX_)) - // This is necessary under IRIX because it scales the input by 0.5 - // when using single-channel input. - if (channels == 1) gain *= 2; -#endif -} - -RTWvIn :: ~RTWvIn() -{ - delete soundIO; - if (rtdata) { - delete [ ] rtdata; - rtdata = 0; - } -} - -void RTWvIn :: normalize() -{ - /* Do nothing ... cannot normalize realtime input */ -} - -void RTWvIn :: normalize(MY_FLOAT newPeak) -{ - /* Do nothing ... cannot normalize realtime input */ -} - -void RTWvIn :: addPhaseOffset(MY_FLOAT anAngle) -{ - /* No phaseOffset for realtime input */ - phaseOffset = 0.0; -} - -void RTWvIn :: setLooping(int aLoopStatus) -{ - /* Cannot loop realtime input */ - looping = 0; -} - -void RTWvIn :: getMoreData() -{ - soundIO->recordBuffer(rtdata,RT_BUFFER_SIZE); - long temp = RT_BUFFER_SIZE; - for (int i=0;i= length) { - this->getMoreData(); - } - while (time >= length) /* Check for end of sound */ - time -= length; /* loop back to beginning */ - while (time < 0.0) /* Check for end of sound */ - time += length; /* loop back to beginning */ - - return finished; -} diff --git a/STK/RTWvOut.cpp b/STK/RTWvOut.cpp deleted file mode 100644 index af2b074..0000000 --- a/STK/RTWvOut.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/*******************************************/ -/* Real-Time Wave File Output Class, */ -/* by Perry R. Cook, 1996 */ -/* revised by Gary P. Scavone, 1999 */ -/* */ -/* This object opens a realtime soundout */ -/* device, and pokes buffers of samples */ -/* into it. */ -/*******************************************/ - -#include "RTWvOut.h" - -#if defined(__STK_REALTIME_) - -RTWvOut :: RTWvOut(MY_FLOAT srate, int chans) -{ - // We'll let RTSoundIO deal with channel and srate limitations. - channels = chans; - soundIO = new RTSoundIO(srate, channels, "play"); - counter = 0; -} - -RTWvOut :: ~RTWvOut() -{ - soundIO->playBuffer(data,counter); - counter = 0; - while (counterplayBuffer(data,counter); - soundIO->playBuffer(data,counter); // Are these extra writes necessary? - soundIO->playBuffer(data,counter); - delete soundIO; -} - -void RTWvOut :: tick(MY_FLOAT sample) -{ - for (int i=0;i= RT_BUFFER_SIZE) { - soundIO->playBuffer(data,counter); - counter = 0; - } -} - -void RTWvOut :: mtick(MY_MULTI samples) -{ - for (int i=0;i= RT_BUFFER_SIZE) { - soundIO->playBuffer(data,counter); - counter = 0; - } -} - -#endif diff --git a/STK/RawWvIn.cpp b/STK/RawWvIn.cpp deleted file mode 100644 index f1cc068..0000000 --- a/STK/RawWvIn.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/*******************************************/ -/* RawWvIn Input Class, */ -/* by Gary P. Scavone, 1999 */ -/* */ -/* This object inherits from WvIn and is */ -/* used to open raw 16-bit data (signed */ -/* integer) files for playback. */ -/* */ -/* STK RawWave files are assumed to be */ -/* monaural and big-endian. */ -/*******************************************/ - -#include "RawWvIn.h" -#include -#include - -#ifdef __LITTLE_ENDIAN__ - #include "swapstuf.h" -#endif - -RawWvIn :: RawWvIn(char *fileName, char *mode) -{ - // Use the system call "stat" to determine the file length - struct stat filestat; - if (stat(fileName, &filestat) == -1) - { /* Opening file failed */ - fprintf(stderr,"Cannot access or find rawwave file: %s !!!\n",fileName); - exit(0); - } - length = (long) filestat.st_size / 2; // length in 2-byte samples - - // Open the file and read samples into data[] - FILE *fd; - fd = fopen(fileName,"rb"); - if (!fd) { - printf("Couldn't open or find rawwave file %s !!!\n",fileName); - exit(0); - } - - channels = 1; // All STK rawwave files are mono - data = (MY_FLOAT *) new MY_FLOAT[(length+1)*channels]; - - long i = 0; - INT16 temp; - fseek(fd,0,SEEK_SET); // Only here to bypass bug in Linux glibc 2.1x (RedHat 6.0) - while (fread(&temp,2,1,fd)) { -#ifdef __LITTLE_ENDIAN__ - temp = SwapINT16 (temp); -#endif - data[i++] = (MY_FLOAT) temp; - } - fclose(fd); - - // Setup for looping or one-shot playback - if (!strcmp(mode,"looping")) { - looping = 1; - data[length] = data[0]; // extra sample for interpolation - } - else if (!strcmp(mode,"oneshot")) { - looping = 0; - data[length] = data[length-1]; // extra sample for interpolation - } - else { - fprintf(stderr,"ERROR: Unsupported RawWvIn mode: %s\n",mode); - free(data); - exit(0); - } - - time = (MY_FLOAT) 0.0; - phaseOffset = (MY_FLOAT) 0.0; - rate = (MY_FLOAT) 1.0; - interpolate = 0; - finished = 0; - lastOutput = (MY_FLOAT *) calloc(channels, sizeof(MY_FLOAT)); -} - -RawWvIn :: ~RawWvIn() -{ -} diff --git a/STK/SndWvIn.cpp b/STK/SndWvIn.cpp deleted file mode 100644 index 34ff51d..0000000 --- a/STK/SndWvIn.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/*******************************************/ -/* SndWvIn Input Class, */ -/* by Gary P. Scavone, 1999 */ -/* */ -/* This object inherits from WvIn and is */ -/* used to open NeXT/Sun .snd 16-bit data */ -/* (signed integer) files for playback. */ -/* */ -/* .snd files are always big-endian. */ -/*******************************************/ - -#include "SndWvIn.h" - -#ifdef __LITTLE_ENDIAN__ - #include "swapstuf.h" -#endif - -SndWvIn :: SndWvIn(char *fileName, char *mode) -{ - // Open the file and get header info - FILE *fd; - fd = fopen(fileName,"rb"); - if (!fd) { - printf("Couldn't open or find .snd file %s !!!\n",fileName); - exit(0); - } - - // Make sure this is a .snd format file - char magic[4]; - fseek(fd,0,SEEK_SET); // Locate magic number in header - fread(magic,4,1,fd); - if (strncmp(magic,".snd",4)) { - printf("This doesn't appear to be a .snd file %s !!!\n",fileName); - exit(0); - } - - // Get number of channels from the header - INT32 int32temp; - fseek(fd,20,SEEK_SET); - fread(&int32temp,4,1,fd); -#ifdef __LITTLE_ENDIAN__ - int32temp = SwapINT32(int32temp); -#endif - channels = int32temp; - - // Get length of data from the header - fseek(fd,8,SEEK_SET); - fread(&int32temp,4,1,fd); -#ifdef __LITTLE_ENDIAN__ - int32temp = SwapINT32(int32temp); -#endif - length = int32temp / 2 / channels; // channel length in 2-byte samples - data = (MY_FLOAT *) new MY_FLOAT[(length+1)*channels]; - - // Read samples into data[] - INT16 temp; - long i = 0; - fseek(fd,40,SEEK_SET); - while (fread(&temp,2,1,fd)) { -#ifdef __LITTLE_ENDIAN__ - temp = SwapINT16 (temp); -#endif - data[i++] = (MY_FLOAT) temp; - } - - // Get file sample rate from the header and set the default rate - fseek(fd,16,SEEK_SET); - fread(&int32temp,4,1,fd); -#ifdef __LITTLE_ENDIAN__ - int32temp = SwapINT32(int32temp); -#endif - rate = (MY_FLOAT) (int32temp/SRATE); - fclose(fd); - - // Setup for looping or one-shot playback - if (!strcmp(mode,"looping")) { - looping = 1; - for (int j=0; j 0.0) interpolate = 1; - else interpolate = 0; - time = (MY_FLOAT) 0.0; - phaseOffset = (MY_FLOAT) 0.0; - finished = 0; - lastOutput = (MY_FLOAT *) calloc(channels, sizeof(MY_FLOAT)); -} - -SndWvIn :: ~SndWvIn() -{ -} diff --git a/STK/SndWvOut.cpp b/STK/SndWvOut.cpp deleted file mode 100644 index 3040898..0000000 --- a/STK/SndWvOut.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/*******************************************/ -/* NeXT Soundfile Output Class */ -/* by Perry R. Cook, 1996 */ -/* revised by Gary P. Scavone, 1999 */ -/* */ -/* This one opens a NeXT .snd file, and */ -/* even knows how to byte-swap! */ -/*******************************************/ - -#include "SndWvOut.h" - -#ifdef __LITTLE_ENDIAN__ - #include "swapstuf.h" -#endif - -/******** NeXT Soundfile Header Struct *******/ -struct headerform { - char pref[4]; - INT32 hdr_length; - INT32 file_length; - INT32 mode; - INT32 samp_rate; - INT32 num_channels; - char comment[16]; -}; - -FILE *openNeXTFile(int chans,char *fileName) { - struct headerform hdr = {".sn",40,0,3,(INT32) SRATE,1,"Created by STK"}; - char tempName[128]; - FILE *fd; - - hdr.pref[3] = 'd'; - - strcpy(tempName,fileName); - if (strstr(tempName,".snd") == NULL) strcat(tempName,".snd"); - hdr.num_channels = chans; - fd = fopen(tempName,"wb"); - if (!fd) { - printf("Couldn't create soundfile %s !!!!!!!!\n",fileName); - exit(0); - } -#ifdef __LITTLE_ENDIAN__ - hdr.hdr_length = SwapINT32 (hdr.hdr_length); - hdr.file_length = SwapINT32 (hdr.file_length); - hdr.mode = SwapINT32 (hdr.mode); - hdr.samp_rate = SwapINT32 (hdr.samp_rate); - hdr.num_channels = SwapINT32 (hdr.num_channels); -#endif - printf("\nCreating soundfile %s\n\n", tempName); - fwrite(&hdr,4,10,fd); - return fd; -} - -SndWvOut :: SndWvOut(char *fileName) -{ - channels = 1; - fd = openNeXTFile(channels,fileName); - counter = 0; - totalCount = 0; -} - -SndWvOut :: SndWvOut(int chans, char *fileName) -{ - if (chans > 24) { - fprintf(stderr,"SndWvOut: Unsupported # of channels: %d\n", chans); - exit(0); - } - channels = chans; - fd = openNeXTFile(channels,fileName); - counter = 0; - totalCount = 0; -} - -SndWvOut :: ~SndWvOut() -{ - double temp; - - fwrite(data,2,counter,fd); - fseek(fd,8,SEEK_SET); - temp = (double) totalCount * ONE_OVER_SRATE; - printf("%f Seconds Computed\n",temp); - totalCount *= 2*channels; -#ifdef __LITTLE_ENDIAN__ - totalCount = SwapINT32 (totalCount); -#endif - fwrite(&totalCount,4,1,fd); - fclose(fd); -} - -long SndWvOut :: getCounter() -{ - return totalCount; -} - -MY_FLOAT SndWvOut :: getTime() -{ - return (MY_FLOAT) totalCount * ONE_OVER_SRATE; -} - -void SndWvOut :: tick(MY_FLOAT sample) -{ - INT16 isample; - - isample = (INT16) (sample * 32000.0); -#ifdef __LITTLE_ENDIAN__ - isample = SwapINT16 (isample); -#endif - for (int i=0;inormalize(); - wave->setRate((MY_FLOAT) 13.33); - vibr->setFreq((MY_FLOAT) 4.0); - onepole->setPole((MY_FLOAT) 0.2); - this->setRatioAndReson(0, (MY_FLOAT) 1.0,(MY_FLOAT) 0.99995); // Set - this->setRatioAndReson(1, (MY_FLOAT) 2.01,(MY_FLOAT) 0.99991); // our - this->setRatioAndReson(2, (MY_FLOAT) 3.9,(MY_FLOAT) 0.99992); // resonance - this->setRatioAndReson(3,(MY_FLOAT) 14.37,(MY_FLOAT) 0.99990); // values here - this->setFiltGain(0,(MY_FLOAT) 0.025); - this->setFiltGain(1,(MY_FLOAT) 0.015); - this->setFiltGain(2,(MY_FLOAT) 0.015); - this->setFiltGain(3,(MY_FLOAT) 0.015); - masterGain = (MY_FLOAT) 1.0; - directGain = (MY_FLOAT) 0.0; - vibrGain = (MY_FLOAT) 0.2; -} - -Vibraphn :: ~Vibraphn() -{ - delete wave; -} - -void Vibraphn :: setStickHardness(MY_FLOAT hardness) -{ - wave->setRate((MY_FLOAT) 2.0 + ((MY_FLOAT) 22.66 * hardness)); - masterGain = (MY_FLOAT) 0.2 + (hardness * (MY_FLOAT) 1.6); -} - -void Vibraphn :: setStrikePosition(MY_FLOAT position) -{ - MY_FLOAT temp,temp2; - temp2 = position * PI; - strikePosition = position; /* Hack only first three modes */ - temp = (MY_FLOAT) sin(strikePosition * PI); - this->setFiltGain(0,(MY_FLOAT) 0.025 * temp); - temp = (MY_FLOAT) sin(0.1 + (2.01 * temp2)); - this->setFiltGain(1,(MY_FLOAT) 0.015 * temp); - temp = (MY_FLOAT) sin(3.95 * temp2); - this->setFiltGain(2,(MY_FLOAT) 0.015 * temp); -} - -void Vibraphn :: controlChange(int number, MY_FLOAT value) -{ -#if defined(_debug_) - printf("Vibraphn : ControlChange: Number=%i Value=%f\n",number,value); -#endif - if (number == __SK_StickHardness_) - this->setStickHardness(value * NORM_7); - else if (number == __SK_StrikePosition_) - this->setStrikePosition(value * NORM_7); - else if (number == __SK_ModFrequency_) - vibr->setFreq((value * NORM_7 * (MY_FLOAT) 12.0)); - else if (number == __SK_ModWheel_) - vibrGain = (value * NORM_7); - else if (number == __SK_AfterTouch_Cont_) - this->strike(value * NORM_7); - else { - printf("Vibraphn : Undefined Control Number!!\n"); - } -} - diff --git a/STK/Vibraphn.h b/STK/Vibraphn.h deleted file mode 100644 index ebef735..0000000 --- a/STK/Vibraphn.h +++ /dev/null @@ -1,27 +0,0 @@ -/*******************************************/ -/* Vibraphone SubClass of Modal4 */ -/* Instrument, by Perry R. Cook, 1995-96 */ -/* */ -/* Controls: CONTROL1 = stickHardness */ -/* CONTROL2 = strikePosition*/ -/* CONTROL3 = vibFreq */ -/* MOD_WHEEL= vibAmt */ -/*******************************************/ - -#if !defined(__Vibraphn_h) -#define __Vibraphn_h - -#include "Modal4.h" - -class Vibraphn : public Modal4 -{ - protected: - public: - Vibraphn(); - ~Vibraphn(); - void setStickHardness(MY_FLOAT hardness); - void setStrikePosition(MY_FLOAT position); - virtual void controlChange(int number, MY_FLOAT value); -}; - -#endif diff --git a/STK/WavWvIn.cpp b/STK/WavWvIn.cpp deleted file mode 100644 index 4c6cb25..0000000 --- a/STK/WavWvIn.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/*******************************************/ -/* WavWvIn Input Class, */ -/* by Gary P. Scavone, 1999 */ -/* */ -/* This object inherits from WvIn and is */ -/* used to open DOS/Windows .wav 16-bit */ -/* data (signed integer) files for */ -/* playback. */ -/* */ -/* .wav files are always little-endian. */ -/*******************************************/ - -#include "WavWvIn.h" - -#ifndef __LITTLE_ENDIAN__ - #include "swapstuf.h" -#endif - -WavWvIn :: WavWvIn(char *fileName, char *mode) -{ - // Open the file and get header info - FILE *fd; - fd = fopen(fileName,"rb"); - if (!fd) { - printf("Couldn't open or find .wav file %s !!!\n",fileName); - exit(0); - } - - // Make sure this is a .wav format file - char wave[4]; - fseek(fd,8,SEEK_SET); // Locate wave id - fread(&wave,4,1,fd); - if (strncmp(wave,"WAVE",4)) { - printf("This doesn't appear to be a .wav file %s !!!\n",fileName); - exit(0); - } - - // Get number of channels from the header - INT16 temp; - fseek(fd,22,SEEK_SET); // Locate channels in header - fread(&temp,2,1,fd); -#ifndef __LITTLE_ENDIAN__ - temp = SwapINT16(temp); -#endif - channels = temp; - - // Get length of data from the header - INT32 bytes; - fseek(fd,40,SEEK_SET); // Locate data length in header - fread(&bytes,4,1,fd); -#ifndef __LITTLE_ENDIAN__ - bytes = SwapINT32(bytes); -#endif - length = bytes / 2 / channels; // length in 2-byte samples - data = (MY_FLOAT *) new MY_FLOAT[(length+1)*channels]; - - // Read samples into data[] - long i = 0; - while (fread(&temp,2,1,fd)) { -#ifndef __LITTLE_ENDIAN__ - temp = SwapINT16 (temp); -#endif - data[i++] = (MY_FLOAT) temp; - } - - // Get file sample rate from the header and set the default rate - INT32 srate; - fseek(fd,24,SEEK_SET); // Locate sample rate in header - fread(&srate,4,1,fd); -#ifndef __LITTLE_ENDIAN__ - srate = SwapINT32(srate); -#endif - rate = (MY_FLOAT) (srate/SRATE); // set default rate based on file sampling rate - fclose(fd); - - // Setup for looping or one-shot playback - if (!strcmp(mode,"looping")) { - looping = 1; - for (int j=0; j 0.0) interpolate = 1; - else interpolate = 0; - time = (MY_FLOAT) 0.0; - phaseOffset = (MY_FLOAT) 0.0; - finished = 0; - lastOutput = (MY_FLOAT *) calloc(channels, sizeof(MY_FLOAT)); -} - -WavWvIn :: ~WavWvIn() -{ -} diff --git a/STK/WvIn.cpp b/STK/WvIn.cpp deleted file mode 100644 index e5fd32d..0000000 --- a/STK/WvIn.cpp +++ /dev/null @@ -1,222 +0,0 @@ -/********************************************/ -/* Data Input Base Class */ -/* by Gary P. Scavone, 1999 */ -/* */ -/* This class can handle multi-channel */ -/* input. Multi-channel input is */ -/* interleaved in the vector "data". */ -/* Actual data input occurs in the */ -/* subclasses of WvIn. */ -/********************************************/ - -#include "WvIn.h" -#include - -WvIn :: WvIn() -{ -} - -WvIn :: ~WvIn() -{ - if (data) { - delete [ ] data; - data = 0; - } - if (lastOutput) { - free(lastOutput); - lastOutput = 0; - } -} - -void WvIn :: reset() -{ - finished = 0; - time = (MY_FLOAT) 0.0; - for (int i=0;inormalize((MY_FLOAT) 1.0); -} - -// Normalize all channels equally by the greatest magnitude in all of data -void WvIn :: normalize(MY_FLOAT newPeak) -{ - long i; - MY_FLOAT max = (MY_FLOAT) 0.0; - - for (i=0;i max) - max = (MY_FLOAT) fabs((double) data[i]); - } - if (max > 0.0) { - max = (MY_FLOAT) 1.0 / max; - max *= newPeak; - for (i=0;i<=channels*length;i++) - data[i] *= max; - } -} - -void WvIn :: setRate(MY_FLOAT aRate) -{ - rate = aRate; - if (fmod(rate, 1.0) > 0.0) interpolate = 1; - else interpolate = 0; -} - -void WvIn :: setFreq(MY_FLOAT aFreq) -{ - rate = length * (MY_FLOAT) ONE_OVER_SRATE * aFreq; - if (fmod(rate, 1.0) > 0.0) interpolate = 1; - else interpolate = 0; -} - -void WvIn :: addTime(MY_FLOAT aTime) /* Add an absolute time */ -{ /* in samples */ - time += aTime; -} - -void WvIn :: addPhase(MY_FLOAT anAngle) /* Add a time in cycles */ -{ /* Cycles here means */ - time += length * anAngle; /* 1.0 = length */ -} - -void WvIn :: addPhaseOffset(MY_FLOAT anAngle) -{ /* Add a phase offset */ - phaseOffset = length * anAngle; /* in cycles, where */ -} /* 1.0 = length */ - -void WvIn :: setInterpolate(int anInterpStatus) -{ - interpolate = anInterpStatus; -} - -void WvIn :: setLooping(int aLoopStatus) -{ - time = (MY_FLOAT) 0.0; - looping = aLoopStatus; - - if (looping) { - for (int i=0;iinformTick(); - if (channels > 1) { - MY_FLOAT tempout = 0.0; - for (int i=0;iinformTick(); - return lastOutput; -} - -int WvIn :: informTick() -{ - static MY_FLOAT temp_time, alpha; - static long temp; - - if (!finished) { - - temp_time = time; - - if (phaseOffset != 0.0) { - temp_time += phaseOffset; /* Add phase offset */ - if (looping) { - while (temp_time >= length) /* Check for end of sound */ - temp_time -= length; /* loop back to beginning */ - while (temp_time < 0.0) /* Check for end of sound */ - temp_time += length; /* loop back to beginning */ - } - else { - if (temp_time >= length) /* Check for end of sound */ - temp_time = length - (MY_FLOAT) 1; /* stick at end */ - else if (temp_time < 0.0) /* check for end of sound */ - temp_time = (MY_FLOAT) 0.0; /* stick at beginning */ - } - } - - temp = (long) temp_time; /* Integer part of time address */ - - if (interpolate) { - alpha = temp_time - (MY_FLOAT) temp; /* fractional part of time address */ - temp *= channels; - for (int i=0;i= length) /* Check for end of sound */ - time -= length; /* loop back to beginning */ - while (time < 0.0) /* Check for end of sound */ - time += length; /* loop back to beginning */ - } - else { /* OneShot */ - if (time >= length) { /* Check for end of sound */ - time = length-(MY_FLOAT) 1; /* stick at end */ - finished = 1; /* Information for one-shot use */ - } - else if (time < 0.0) /* Check for end of sound */ - time = (MY_FLOAT) 0.0; /* stick at beginning */ - } - } - - return finished; -} - -MY_FLOAT WvIn :: lastOut() -{ - if (channels > 1) { - MY_FLOAT tempout = 0.0; - for (int i=0;i - -WvOut :: WvOut() -{ -} - -WvOut :: ~WvOut() -{ -} - -void WvOut :: tick(MY_FLOAT sample) -{ -} - -void WvOut :: mtick(MY_MULTI samples) -{ -} diff --git a/STK/WvOut.h b/STK/WvOut.h deleted file mode 100644 index 38a0858..0000000 --- a/STK/WvOut.h +++ /dev/null @@ -1,27 +0,0 @@ -/********************************************/ -/* WvOut Abstract Class, */ -/* by Tim Stilson, 1996 */ -/* revised by Gary P. Scavone, 1999 */ -/* */ -/* This class can handle multi-channel */ -/* data via the mtick() method. */ -/********************************************/ - -#include "Object.h" - -#if !defined(__WvOut_h) -#define __WvOut_h - - - -class WvOut : public Object -{ - public: - WvOut(); - virtual ~WvOut(); - virtual void tick(MY_FLOAT sample); - virtual void mtick(MY_MULTI samples); -}; - - -#endif // defined(__WvOut_h) diff --git a/STK/swapstuf.cpp b/STK/swapstuf.cpp deleted file mode 100644 index 96a40a2..0000000 --- a/STK/swapstuf.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include "swapstuf.h" - -INT32 SwapINT32(INT32 inf) -{ - INT32 o; - unsigned char *inp,*outp; - inp=(unsigned char *)&inf; - outp=(unsigned char *)&o; - outp[0]=inp[3]; outp[1]=inp[2]; outp[2]=inp[1]; outp[3]=inp[0]; - return(o); -} - -INT16 SwapINT16(INT16 inf) -{ - INT16 o; - unsigned char *inp,*outp; - inp=(unsigned char *)&inf; - outp=(unsigned char *)&o; - outp[0]=inp[1]; outp[1]=inp[0]; - return(o); -} - -float SwapFloat(float inf) -{ - float o; - unsigned char *inp,*outp; - inp=(unsigned char *)&inf; - outp=(unsigned char *)&o; - outp[0]=inp[3]; outp[1]=inp[2]; outp[2]=inp[1]; outp[3]=inp[0]; - return(o); -} - -double SwapDouble(double inf) -{ - double o; - unsigned char *inp,*outp; - inp=(unsigned char *)&inf; - outp=(unsigned char *)&o; - outp[0]=inp[7]; outp[1]=inp[6]; outp[2]=inp[5]; outp[3]=inp[4]; - outp[4]=inp[3]; outp[5]=inp[2]; outp[6]=inp[1]; outp[7]=inp[0]; - return(o); -} diff --git a/STK/swapstuf.h b/STK/swapstuf.h deleted file mode 100644 index 9ff9e5e..0000000 --- a/STK/swapstuf.h +++ /dev/null @@ -1,6 +0,0 @@ -#include "Object.h" - -INT32 SwapINT32(INT32 inf); -INT16 SwapINT16(INT16 inf); -float SwapFloat(float inf); -double SwapDouble(float inf); diff --git a/Hierarchy.txt b/doc/Hierarchy.txt similarity index 69% rename from Hierarchy.txt rename to doc/Hierarchy.txt index 532de88..99e0121 100644 --- a/Hierarchy.txt +++ b/doc/Hierarchy.txt @@ -1,10 +1,10 @@ STK: A ToolKit of Audio Synthesis Classes and Instruments in C++ -Version 3.1 +Version 3.2 By Perry R. Cook, 1995-2000 and Gary P. Scavone, 1997-2000. -STK Classes, Version 3.1 +STK Classes, Version 3.2 Please read README.txt for more information. <--------Building Blocks---------->|<----------------Instruments------------------> @@ -17,41 +17,43 @@ Object-----------------------------------Instrmnt----------. Envelope| Filter Reverb BowTabl | .----------------------------------------. | | | | JetTabl | | | | | | | | | ADSR | OneZero PRCRev ReedTabl| Modal4 | FM4Op---.| | | | Shakers - | OnePole JCRev | | | | || | | | | - ._____| TwoZero NRev .____| Marimba | FM4Alg3 || Plucked Sampler | Maraca - | | TwoPole | Vibraphn| | || Clarinet | | Sekere -Noise | DCBlock LipFilt AgogoBel| HeavyMtl|| Brass SamplFlt| Cabasa - | | BiQuad | || Flute | | Bamboo -SubNoise| DlineL .____| .____|| Bowed Moog1 | Water Drops - | DLineA | | || BowedBar | Tambourine - ._____| DLineN VoicForm FM4Alg4 ||____. | SleighBells - | | FormSwep | | | | Guiro - WvIn | PoleZero PercFlut| Plucked2 | Wrench - | |____. | | | Coke Can -WavWvIn | | .____| Mandolin .____| Sticks -SndWvIn | TablLook | | | Crunch -RawWvIn | FM4Alg5 | DrumSynt Sand Paper -MatWvIn | | | -RTWvIn | Rhodey | - | Wurley | - ._____| TubeBell | - | | .____| -Modulatr| | | - | FM4Alg6 | - ._____| | | - | | FMVoices| -SingWave|_____. | - | | .____| - ._____| WvOut | + | OnePole JCRev | | | | || | | | + ._____| TwoZero NRev .____| ModalBar| FM4Alg3 || Plucked Sampler | + | | TwoPole | | | || Clarinet | | +Noise | DCBlock LipFilt | HeavyMtl|| Brass SamplFlt| + | | BiQuad | || Flute | | +SubNoise| DlineL .____| .____|| Bowed Moog1 | + | DLineA | | || BowedBar | + | DLineN VoicForm FM4Alg4 || BlowHole | + | FormSwep | ||____. | + | PoleZero PercFlut| | | + .____| FIR | Plucked2 | + | | .____| | .____| +TablLook| | | Mandolin | + | FM4Alg5 | DrumSynt + |____. | | + | | Rhodey | + | WvIn Wurley | + ._____| | TubeBell | + | | WavWvIn .____| +Modulatr| SndWvIn | | + | RawWvIn FM4Alg6 | + ._____| MatWvIn | | + | | AifWvIn FMVoices| +SingWave| StrmWvIn | + | .____| + ._____|_____. | | | | FM4Alg8 -VoicMang| WavWvOut | - | SndWvOut BeeThree - | RTWvOut - | MatWvOut - ._____| RawWvOut - | -MIDIIO - +VoicMang| WvOut | + | | BeeThree + | WavWvOut + ._____| SndWvOut + | | RawWvOut +RtMidi | MatWvOut + | AifWvOut + ._____| RtWvOut + | StrmWvOut +RtAudio ********** INSTRUMENTS AND ALGORITHMS ************** @@ -65,12 +67,11 @@ Mandolin.cpp My Own Mandolin <> Bowed.cpp Not Hideous Bowed String DlineL,BowTabl,OnePole,BiQuad,RawWave,ADSR Brass.cpp Not So Bad Brass Inst. DLineA,LipFilt,DCBlock,ADSR,RawWvIn Clarinet.cpp Pretty Good Clarinet DLineL,ReedTabl,OneZero,Envelope,Noise,RawWvIn +BlowHole.cpp Clarinet w/ tone/reghole DLineL,ReedTabl,OneZero,Envelope,Noise,RawWvIn,PoleZero Flute.cpp Pretty Good Flute JetTabl,DLineL,OnePole,DCBlock,Noise,ADSR,RawWvIn BowedBar.cpp Pretty Good Bowed Bar DLineN,BowTabl,ADSR,BiQuad Modal4.cpp 4 Resonances Envelope,RawWvIn,RawWvIn,BiQuad,OnePole -Marimba.cpp <> -Vibraphn.cpp <> -Agogobel.cpp <> +ModalBar.cpp Various presets <> FM4Op.cpp 4 Operator FM Master ADSR,RawWvIn,TwoZero FM4Alg3.cpp 3 Cascade w/ FB Mod. <> FM4Alg4.cpp Like Alg3 but diff. <> @@ -107,16 +108,24 @@ Inputs: TablLook.cpp Lookup Table (assumes given data in big-endian f SndWvIn.cpp .snd Input Class WavWvIn.cpp .wav Input Class MatWvIn.cpp Matlab MAT-file Input Class - RTWvIn.cpp Realtime Input Class + AifWvIn.cpp AIFF Input Class + RtWvIn.cpp Realtime Input Class + StrmWvIn.cpp Audio Streaming (socket server) Input Class Outputs: WvOut.cpp Output Master Class RawWvOut.cpp STK Raw-file Output Class SndWvOut.cpp .snd Output Class WavWvOut.cpp .wav Output Class - RTWvOut.cpp Realtime Output Class MatWvOut.cpp Matlab MaT-file Output Class + AifWvOut.cpp AIFF Output Class + RtWvOut.cpp Realtime Output Class + StrmWvOut.cpp Audio Streaming (socket client) Output Class -MIDI: MIDIIO.cpp MIDI I/O Class +Duplex: RtDuplex.cpp Realtime Input/Output Class + +MIDI: RtMidi.cpp MIDI I/O Class + +Audio I/O: RtAudio.cpp Multi-OS Audio I/O Routines Filters: Filter.cpp Filter Master Class OneZero.cpp One Zero Filter @@ -143,3 +152,5 @@ NonLin&Lookup: JetTabl.cpp Cubic Jet NonLinearity Derived: Modulatr.cpp Per. and Rnd. Vibrato: RawWave, SubNoise, OnePole SingWave.cpp Looping Wavetable with: Modulatr, Envelope + +Control: Controller.cpp Pipe, Socket, and MIDI control message handling \ No newline at end of file diff --git a/doc/README-Linux.txt b/doc/README-Linux.txt new file mode 100644 index 0000000..6912d48 --- /dev/null +++ b/doc/README-Linux.txt @@ -0,0 +1,28 @@ +STK: A ToolKit of Audio Synthesis Classes and Instruments in C++ +Version 3.2 + +By Perry R. Cook, 1995-2000 +and Gary P. Scavone, 1997-2000. + +Please read the file README.txt for more general STK information. + +STK for Linux is currently using either the Open Sound System (OSS) or the Advanced Linux Sound Architecture (ALSA) sound and MIDI APIs. The free version of OSS works as well (and in some cases better than the commercial OSS version ... such as with my Maestro 2e chipset). In general, the ALSA drivers seem to perform well though we have had some problems with them at CCRMA. You can read more about ALSA at http://www.alsa-project.org/. ALSA is open source and holds great promise for audio under Linux. Select (uncomment) the proper API #define statement in Object.h. + +STK should compile without much trouble under Linux ... afterall, it is primarily developed on Linux platforms. Since all Linux distributions typically include the GNU makefile utilities, you should be able to use the default Makefile. Typing "make" will initiate the compilation process. + +MIDIATOR SERIAL PORT MIDI SUPPORT: + +STK now has special support for the MIDIator serial port MIDI interface. This is of primary interest to us laptop users, whose computers usually don't have a gameport. If you want to buy one of these devices, make sure you get the MS-124w model (www.midiator.com). For it to work in STK, make sure you uncomment the MIDIATOR define statement in Object.h. This support currently only works within the OSS API framework, though I should be able to get it to work with ALSA in the future as well. + +There are a few things that need to be done on your system to get the MIDIator working. Add the following lines to your bootup sequence in /etc/rc.d/rc.local: + +setserial /dev/ttyS0 baud_base 57600 +setserial /dev/ttyS0 divisor 1 + +You may need to specify the full path to the setserial function, depending on how your PATH variable is set up. Also, you may need to modify the permissions of /dev/ttyS0 (chmod a+rwx). And finally, the MIDIator should be set for "single addresssed" mode (the S/A switch on S and the A/B switch on A), which puts identical output on all 4 MIDI output ports. It is possible to use the MIDIator in a "multi-port" mode, though I'm not currently supporting that in STK. + +NOTE REGARDING PTHREADS: + +There haven't been any problems with threads since the old days of RedHat Linux 5.0. STK uses the MIT pthreads API. + + diff --git a/doc/README-NeXT.txt b/doc/README-NeXT.txt new file mode 100644 index 0000000..66ad948 --- /dev/null +++ b/doc/README-NeXT.txt @@ -0,0 +1,14 @@ +STK: A ToolKit of Audio Synthesis Classes and Instruments in C++ +Version 3.2 + +By Perry R. Cook, 1995-2000 +and Gary P. Scavone, 1997-2000. + +Please read the file README.txt for more general STK information. + +STK has always worked under NeXTStep without realtime audio or MIDI support. In general, STK should compile in this way using any generic C++ compiler. C++ exception handling was added to STK with release 3.2. I have had some difficulty testing this release under NeXTStep because our NeXTStep compilers at CCRMA are very old. We tried a newer version of gcc-2.7.2.2 and that mostly worked, though it died trying to compile the BowedBar class. Also, I was unable to locate the correct header for the random() function. + +In summary, I _think_ STK will compile under NeXTStep with a fairly recent compiler, but you may have to do a little work to make it happen. If you do succeed, please let us know. + +Just for clarification, "realtime" support and the use of the __STK_REALTIME_ define statement includes audio and MIDI input/output routines, as well as socket and thread routines for realtime message acquisition (Controller) and internet audio streaming (StrmWvIn, StrmWvOut). + diff --git a/README-SGI.txt b/doc/README-SGI.txt similarity index 53% rename from README-SGI.txt rename to doc/README-SGI.txt index c0cde62..0873d3a 100644 --- a/README-SGI.txt +++ b/doc/README-SGI.txt @@ -1,5 +1,5 @@ STK: A ToolKit of Audio Synthesis Classes and Instruments in C++ -Version 3.1 +Version 3.2 By Perry R. Cook, 1995-2000 and Gary P. Scavone, 1997-2000. @@ -8,8 +8,8 @@ Please read the file README.txt for more general STK information. It seems that SGI systems are not distributed with the GNU Makefile utilities. The default Make utility has very limited functionality, so your safest bet is to download the GNU Makefile utilities from the Internet and use STK's default Makefile. If this is not possible, try using Makefile.sgi (make -f Makefile.sgi). -Aside from the Makefile issues, STK should compile and run on SGI platforms without any problems. +Another issue that has crept up with this release is proper compiler support for C++ error handling. If you experience problems, you probably don't have a recent version of the C++ compiler. Otherwise, STK should compile and run on SGI platforms without any problems. NOTE REGARDING PTHREADS: -With release 3.1, STK is now using the pthread API under Irix. It appears that pthread functionality is standard on SGI, so this change shouldn't cause any problems. If I'm wrong, let me know! +Since release 3.1, STK has used the pthread API under Irix. It appears that pthread functionality is standard on SGI, so this change shouldn't cause any problems. If I'm wrong, let me know! diff --git a/doc/README-Win.txt b/doc/README-Win.txt new file mode 100644 index 0000000..8909aa9 --- /dev/null +++ b/doc/README-Win.txt @@ -0,0 +1,69 @@ +STK: A ToolKit of Audio Synthesis Classes and Instruments in C++ +Version 3.2 + +By Perry R. Cook, 1995-2000 +and Gary P. Scavone, 1997-2000. + +Please read the file README.txt for more general STK information. + +DirectX and WindowsNT Issues: +----------------------------- + +STK is currently distributed with Visual C++ 6.0 project and workspace files. + +The STK realtime sound input capabilities under Windoze are only supported using the DirectSoundCapture API. The latency is pretty horrendous, but what do you expect? Also, there is a chance you don't have DirectSoundCapture support on your computer. If not, you should download the DirectX 6.0 (or higher) runtime libraries from Microsoft's WWW site (http://www.microsoft.com/directx/download.asp) in order to run the pre-compiled STK executables for Windoze. The last time I checked, there was no DirectSoundCapture support for WindowsNT ... you'll have to switch to Windows 2000. I stopped supporting the WinMM audio output code with this release. So, if you wish to compile STK under WindowsNT (without realtime audio input support), you'll have to download an older version of STK, uncomment the __WINMM_API_ flag (and comment out the __WINDS_API flag) in Object.h and recompile the source code. + +Realtime sound output under Windoze is supported using the DirectSound (dsound.lib) API. All new versions of Win95/98/NT come with the DirectSound library, but early versions did not. If you have trouble running the distributed executables, then you probably don't have DirectSound installed on your system. You can download the necessary DirectSound stuff from Microsoft's WWW pages (http://www.microsoft.com/directx/download.asp). + +Realtime MIDI input is supported using the winmm.lib API. + +Visual C++ 6.0 workspaces have been created for the various STK projects. Everything has already been configured for you. The intermediate .obj files will be written to either the "Release" or "Debug" directories, but the executable files will be written to the main project directories (where they need to be for proper execution). If you should somehow lose or hose the VC++ workspace file (STK.dsw), then you will have to do a LOT of configuring to recreate it ... it's probably easier just to download the distribution again from our WWW sites. Anyway, for your benefit and mine, here is a list of things that need to be added to the various "Project Settings": + +1. Under General: Set "Output files:" to (this will put the executable in the main project directory. + +2. Under C/C++ > Code Generation: Set "Use run-time library:" to Multithreaded (use "debug" versions for the debug configuration). + +3. Under Link > General: Add winmm.lib, dsound.lib, and Wsock32.lib to the end of the Object/library modules list. + +4. Under C/C++ > Preprocessor: Add "../../include" directory to the "extra include" field. + +5. Add all the necessary files to the project. + +Remember that items 1-3 above need to be done for each project and for each configuration. There might be an easy way to make global changes, but I couldn't figure it out. + +To use the Tcl/Tk GUIs, you will have to install Tcl/Tk. I got version 8.0 and it works very well (and installed easily). The distribution is available on the WWW and is free. + +In order for socketing to work, it is necessary to have the TCP protocol installed on your computer. This can be done from the "Network" control panel. + +Finally, to use it all - + + +PLAY SKINI SCOREFILES IN REALTIME: + + syntmono Clarinet -or < scores/streetsf.ski + + +USE TCL/TK GUIs FOR REALTIME CONTROL: + +1. Open a DOS console window and start syntmono (eg. syntmono Clarinet -or -is). + +2. Double click on a Tcl/Tk file in TCLSpecs (eg. TCLPhys.tcl) from the Windows Explorer to start the GUI. Select the "communications" menu item and "Socket" and make the connection. + +3. Start moving the sliders to control the instrument. + + +USE REALTIME MIDI INPUT FOR CONTROL: + +1. Open a DOS console window and start syntmono with MIDI input (eg. syntmono Clarinet -or -im). + + This assumes you already have MIDI setup correctly for your computer. + + +WINDOWS NT ONLY: + +Realtime piping seems to work under WindowsNT in much the same way as on Unix platforms. Thus, it is possible to pipe realtime control data to syntmono under WindowsNT as well. + + +WINDOWS 2000: + +I don't have Windows 2000 and I doubt I'll get it anytime soon. However, we briefly tested release 3.2 of STK on Perry's Win2000 machine and it worked fine. There is an advantage in using Windows 2000 over 95/98 in that piping works, just as under unix. Also, the scheduler in Win2000 seems to be much better, so socketed messages don't get clumped together like they do in Win 95/98. Since 2000 is supposed to ship with DirectX 7.0, the DirectSoundCapture functionality should work as well. \ No newline at end of file diff --git a/README.txt b/doc/README.txt similarity index 55% rename from README.txt rename to doc/README.txt index bfd45e0..08c1f91 100644 --- a/README.txt +++ b/doc/README.txt @@ -1,5 +1,5 @@ STK: A ToolKit of Audio Synthesis Classes and Instruments in C++ -Version 3.1 +Version 3.2 By Perry R. Cook, 1995-2000 and Gary P. Scavone, 1997-2000. @@ -9,9 +9,9 @@ Please read the Legal and Ethical notes near the bottom of this document. OVERVIEW: -STK is a set of audio signal processing C++ classes and instruments for music synthesis. You can use these classes to create programs which make cool sounds using a variety of synthesis techniques. This is not a terribly novel concept, except that STK is very portable (it's mostly platform-independent C and C++ code) AND it's completely user-extensible. So, the code you write using STK actually has some chance of working in another 5-10 years. STK currently runs on SGI (Irix), Linux, NeXTStep, and Windows computer platforms. Oh, and it's free for non-commercial use. The only parts of STK that are platform-dependent concern real-time sound and MIDI input and output ... but we've taken care of that for you. The interface for MIDI input and the simple Tcl/Tk graphical user interfaces (GUIs) provided is the same, so it's easy to voice and experiment in real time using either the GUIs or MIDI. +STK is a set of audio signal processing C++ classes and instruments for music synthesis. You can use these classes to create programs which make cool sounds using a variety of synthesis techniques. This is not a terribly novel concept, except that STK is very portable (it's mostly platform-independent C and C++ code) AND it's completely user-extensible. So, the code you write using STK actually has some chance of working in another 5-10 years. STK currently runs with "realtime" support (audio and MIDI) on SGI (Irix), Linux, and Windows computer platforms. Generic, non-realtime support has been tested under NeXTStep, but should work with any standard C++ compiler. STK is free for non-commercial use. The only parts of STK that are platform-dependent concern real-time sound, MIDI, and control input and output ... but we've taken care of that for you. The interface for MIDI input and the simple Tcl/Tk graphical user interfaces (GUIs) provided is the same, so it's easy to voice and experiment in real time using either the GUIs or MIDI. -STK isn't one particular program. Rather, STK is a set of C++ classes that you can use to create your own programs. We've provided a few example applications that demonstrate some of the ways that you could use these classes. But if you have specific needs you will probably have to either modify the example programs or write a new program altogether. Further, the example programs don't have a fancy GUI wrapper. If you feel the need to have a "drag and drop" GUI, you probably don't want to use STK. Spending hundreds of hours making platform-dependent GUI code would go against one of the fundamental design goals of STK - platform independence. STK can generate simultaneous .snd, .wav, and .mat output soundfile formats (beside realtime sound output), so you can view your results using one of the numerous sound/signal analysis tools already available over the WWW (e.g. Snd, Cool Edit, Matlab). For those instances where a simple GUI with sliders and buttons is helpful, we use Tcl/Tk (which is freely distributed for all the STK supported platforms). A number of Tcl/Tk GUI scripts are distributed with the STK release. +STK isn't one particular program. Rather, STK is a set of C++ classes that you can use to create your own programs. We've provided a few example applications that demonstrate some of the ways that you could use these classes. But if you have specific needs you will probably have to either modify the example programs or write a new program altogether. Further, the example programs don't have a fancy GUI wrapper. If you feel the need to have a "drag and drop" GUI, you probably don't want to use STK. Spending hundreds of hours making platform-dependent GUI code would go against one of the fundamental design goals of STK - platform independence. STK can generate simultaneous .snd, .wav, .aif, and .mat output soundfile formats (as well as realtime sound output), so you can view your results using one of the numerous sound/signal analysis tools already available over the WWW (e.g. Snd, Cool Edit, Matlab). For those instances where a simple GUI with sliders and buttons is helpful, we use Tcl/Tk (which is freely distributed for all the STK supported platforms). A number of Tcl/Tk GUI scripts are distributed with the STK release. SYSTEM REQUIREMENTS: @@ -21,33 +21,38 @@ See the individual README's (eg. README-linux) for platform specific information WHAT'S NEW: -STK has undergone several key revisions, changes, and additions since its last release in 1998. Despite being available in one form or another since 1996, we still consider STK to be alpha software. Thus, backward compatability has not been a priority. Please read the ReleaseNotes to see what has changed since the last release. +STK has undergone several key revisions, changes, and additions since its last release. Despite being available in one form or another since 1996, we still consider STK to be alpha software. Thus, backward compatability has not been a priority. Please read the ReleaseNotes to see what has changed since the last release. -Realtime audio input capabilities were added to STK with release 3.0, though the behavior of such is very hardware dependent. Under Linux and Irix, audio input and output are possible with very low latency. Using the Windoze DirectSound API, minimum dependable output sound latency seems to be around 15 milliseconds, while input sound latency is on the order of several hundred milliseconds! It is also possible to generate simultaneous .snd, .wav, .raw, and .mat (Matlab MAT-file) output file types, as well as SKINI scorefiles using MD2SKINI. Finally, STK should compile with non-realtime functionality on any platform with a generic C++ compiler. +The control message handling scheme has been simplified greatly with release 3.2 through the use of the Controller 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. -Socketing capabilities were extended in release 3.0 to function under Unix platforms, as well as Windoze platforms. Further, the socket server thread was updated to accept multiple simultaneous socket connections. Thus, it is now possible to have several different socket clients sending SKINI control messages to the server at the same time. Under Linux and Irix, it is also possible to pipe GUI messages through MD2SKINI, enabling both MIDI and GUI control via piping at the same time. +Realtime audio input capabilities were added to STK with release 3.0, though the behavior of such is very hardware dependent. Under Linux and Irix, audio input and output are possible with very low latency. Using the Windoze DirectSound API, minimum dependable output sound latency seems to be around 20 milliseconds or so, while input sound latency is on the order of a hundred milliseconds or more! +As mentioned above, it is possible to record the audio ouput of an STK program to .snd, .wav, .raw, .aif, and .mat (Matlab MAT-file) output file types. Though somewhat obsolete, the program MD2SKINI can be used to write SKINI scorefiles from realtime MIDI input. Finally, STK should compile with non-realtime functionality on any platform with a generic C++ compiler. + +For those who wish to make a library from the core STK classes, there is a Makefile in the src directory that will accomplish that (Linux and SGI only). GETTING STARTED: -A number of example executables are provided with this distribution. The effects directory contains a program that demonstrates realtime duplex mode (simultaneous audio input and output) operation, as well as several simple delay-line based effects algorithms. The MUS151 directory contains a simple two-oscillator program that can be used to demonstrate psychoacoustic masking effects. RagaMatic is a totally cool application for achieving inner piece. The syntmono directory offers a program for monophonic STK instrument playback and manipulation. Syntmono is the primary STK synthesis server and is used to demonstrate all the current STK instruments. MD2SKINI is an executable (currently compiles from the syntmono project) which takes raw MIDI input, converts it to SKINI format, and outputs the result to stdout or any socket host and port ID. Control data (in the form of SKINI messages) can be fed to syntmono through three principal means - SKINI scorefiles, MD2SKINI output, and Tcl/Tk GUIs. A variety of SKINI scorefiles are distributed with STK and can be found in the "scores" directory of the syntmono project. +A number of example "projects" are provided with this distribution. The effects directory contains a program that demonstrates realtime duplex mode (simultaneous audio input and output) operation, as well as several simple delay-line based effects algorithms. RagaMatic is a totally cool application for achieving inner peace. The examples directory contains several simple programs which demonstrate audio input/output, as well as the use of the audio internet streaming classes. The syntmono directory offers a program for monophonic STK instrument playback and manipulation. Syntmono is used to demonstrate most of the current STK instruments. Control data (in the form of MIDI or SKINI messages) is acquired by syntmono through pipe, socket, or MIDI connections. Tcl/Tk GUIs are provided which output SKINI formatted messages. A variety of SKINI scorefiles are distributed with STK and can be found in the "scores" directory of the syntmono project. MD2SKINI is an executable (currently compiles from the syntmono project) which takes raw MIDI input, converts it to SKINI format, and outputs the result to stdout or any socket host and port ID. -Unless you downloaded the distribution with precompiled Windoze binaries, it is necessary to first compile the sources. Under Linux or Irix, simply typing "make" in any of the particular project directories will begin the compilation process. If your Unix system does not have the GNU Makefile utilities, you will have to use one of the platform specific Makefiles (eg. make -f Makefile.sgi). To compile the projects under Windoze, you should use the VC++ project files provided with the STK distribution. +Unless you downloaded the distribution with precompiled Windoze binaries, it is necessary to first compile the sources. Under Linux or Irix, simply typing "make" in any of the particular project directories will begin the compilation process. If your Unix system does not have the GNU Makefile utilities, you will have to use one of the platform specific Makefiles (eg. make -f Makefile.sgi). To compile the projects under Windoze, you should use the VC++ 6.0 project files provided with the STK distribution. SYNTMONO: -Syntmono is the primary STK synthesis server and is used to demonstrate all the current STK instruments. Syntmono can take realtime control (SKINI) input via pipes or sockets, or it can be fed SKINI scorefile (non-realtime) input. Syntmono can output data in realtime, .wav, .snd, .mat (Matlab MAT-file), and/or .raw formats. Assuming you have successfully compiled the syntmono executable, a scorefile can be redirected to syntmono and the output heard in realtime in the following way: +Syntmono is used to demonstrate most of the current STK instruments. Syntmono can take realtime control input via MIDI and/or SKINI format via pipes or sockets, or it can be fed SKINI scorefile (non-realtime) input. Syntmono can output data in realtime, .wav, .snd, .aif, .mat (Matlab MAT-file), and/or .raw formats. Assuming you have successfully compiled the syntmono executable, a scorefile can be redirected to syntmono and the output heard in realtime in the following way: - syntmono Clarinet -r < scores/streetsf.ski + syntmono Clarinet -or < scores/streetsf.ski -The "-r" flag specifies the realtime output option. Typing syntmono without arguments will provide a brief description of the instruments possible and the various input/output option flags. Tcl/Tk GUIs are provided in the "tcl" directory of each project, though you will have to install Tcl/Tk version 8.0 or higher on your system to use them (older versions of Tcl/Tk under Linux seem to be more forgiving than under IRIX). Realtime SKINI control data (via MD2SKINI or GUIs) can be piped to syntmono on Unix platforms and WinNT in the following way: +The "-or" flag specifies the realtime output option. Typing syntmono without arguments will provide a brief description of the instruments possible and the various input/output option flags. Tcl/Tk GUIs are provided in the "tcl" directory of each project, though you will have to install Tcl/Tk version 8.0 or higher on your system to use them (older versions of Tcl/Tk under Linux seem to be more forgiving than under IRIX). Realtime SKINI control data can be piped to syntmono from a Tcl/Tk GUI on Unix platforms and WinNT in the following way: - MD2SKINI | syntmono Clarinet -r -ip -or - wish < TCLSpecs/TCLPhys.tcl | syntmono Clarinet -r -ip + wish < TCLSpecs/TCLPhys.tcl | syntmono Clarinet -or -ip -The "-ip" flag specifies piped realtime input. It is not possible to use realtime pipes under Windoze95/98, so socket communication must be used instead. For socket communication, it is necessary to first start the syntmono socket server using the "-is" flag (socketed realtime input). For the time being, a default (hardwired) socket port of 2001 is being used by syntmono. After syntmono is running (and waiting for a socket client connection), either MD2SKINI or a Tcl/Tk GUI can be started. When using the GUI, it is necessary to invoke the "communications" menu item and select "socket" to establish the connection. The same procedure is also possible on Unix platforms. +The "-ip" flag specifies piped realtime input. It is not possible to use realtime pipes under Windoze95/98, so socket communication must be used instead. For socket communication, it is necessary to first start the syntmono socket server using the "-is" flag (socketed realtime input). For the time being, a default (hardwired) socket port of 2001 is being used by syntmono. After syntmono is running (and waiting for a socket client connection), a Tcl/Tk GUI can be started. When using the GUI, it is necessary to invoke the "communications" menu item and select "socket" to establish the connection. The same procedure is also possible on Unix platforms. Finally, realtime MIDI control input can be used to control syntmono by typing: + + syntmono Clarinet -or -im + +The "-im" flag specifies realtime MIDI input. It is possible to use piped, socketed, and/or MIDI control input simultaneously. DISCLAIMER: @@ -68,7 +73,7 @@ The good news is that large hunks of the techniques used here are public domain. FURTHER READING: -For more documentation on this ToolKit, the classes, etc., read the file HIERARCH.txt and the individual class definitions. Also check the platform specific README's for specific system requirements. +For more documentation on this ToolKit, the classes, etc., read the file Hierarchy.txt and the individual class definitions. Also check the platform specific README's for specific system requirements. PERRY'S NOTES FROM THE ORIGINAL DISTRIBUTION: diff --git a/ReleaseNotes.txt b/doc/ReleaseNotes.txt similarity index 80% rename from ReleaseNotes.txt rename to doc/ReleaseNotes.txt index b96219b..96eaf48 100644 --- a/ReleaseNotes.txt +++ b/doc/ReleaseNotes.txt @@ -1,9 +1,28 @@ STK: A ToolKit of Audio Synthesis Classes and Instruments in C++ -Release 3.1 +Release 3.2 By Perry R. Cook, 1995-2000 and Gary P. Scavone, 1997-2000 +v3.2: (13 November 2000) +- new control handling class (Controller) +- added AIFF file input/output support +- stklib.a Makefile in src directory +- added C++ error handling capabilities +- added input/output internet streaming support (StrmWvIn/StrmWvOut) +- added native ALSA support for linux +- added optional "device" argument to all "Rt" classes (audio and MIDI) and printout of devices when argument is invalid +- WvIn classes rewritten to support very big files (incremental load from disk) +- changed WvIn/WvOut classes to work with sample frame buffers +- fixed looping and negative rate calculations in WvIn classes +- fixed interpolation bug in RtWvIn +- windoze RtAudio code rewritten (thanks Dave!) +- simplified byte-swapping functions (in-place swapping) +- new FIR filter class (thanks Julius!) +- "stereo-ized" RagaMatic +- probably a bunch more fixes that I've long since forgotten about + + v3.1: (13 March 2000) - new RagaMatic project!!! - added "microphone position" to Mandolin in STKdemo diff --git a/SKINI11.txt b/doc/SKINI11.txt similarity index 100% rename from SKINI11.txt rename to doc/SKINI11.txt diff --git a/effects/effects.cpp b/effects/effects.cpp deleted file mode 100644 index cbd2574..0000000 --- a/effects/effects.cpp +++ /dev/null @@ -1,165 +0,0 @@ -/************** Test Effects Program *********************/ - -#include "../STK/RTSoundIO.h" -#include "../STK/RTDuplex.h" -#include "../STK/SKINI11.h" -#include "../STK/SKINI11.msg" -#include "../STK/Envelope.h" -#include "../STK/PRCRev.h" -#include "../STK/JCRev.h" -#include "../STK/NRev.h" -#include "Echo.h" -#include "PitShift.h" -#include "Chorus.h" - -// The input command pipe and socket threads are defined in threads.cpp. -#include "threads.h" - -int numStrings = 0; -int notDone = 1; -char **inputString; - -void usage(void) { - /* Error function in case of incorrect command-line argument specifications */ - printf("\nuseage: effects flag \n"); - printf(" where flag = -ip for realtime SKINI input by pipe\n"); - printf(" (won't work under Win95/98),\n"); - printf(" and flag = -is for realtime SKINI input by socket.\n"); - exit(0); -} - -int main(int argc,char *argv[]) -{ - MY_FLOAT inSample = 0.0; - MY_FLOAT lastSample = 0.0; - MY_FLOAT byte3; - long i, synlength; - int type, j, outOne = 0, effect = 0, useSocket = 0; - - if (argc != 2) usage(); - - if (!strcmp(argv[1],"-is") ) - useSocket = 1; - else if (strcmp(argv[1],"-ip")) { - usage(); - } - - RTDuplex *inout = new RTDuplex(SRATE,1); - Echo *echo = new Echo(SRATE); // one second delay - PitShift *shifter = new PitShift(); - Chorus *chorus = new Chorus(5000.0); - PRCRev *prcrev = new PRCRev(2.0); - JCRev *jcrev = new JCRev(2.0); - NRev *nrev = new NRev(2.0); - SKINI11 *score = new SKINI11(); - Envelope *envelope = new Envelope; - - // Start the input thread - if (useSocket) - startSocketThread(); - else - startPipeThread(); - - /* Finally ... the runtime loop begins! */ - notDone = 1; - synlength = RT_BUFFER_SIZE; - while(notDone || numStrings) { - if (numStrings > 1) synlength = (long) RT_BUFFER_SIZE / numStrings; - else synlength = RT_BUFFER_SIZE; - for ( i=0; itick(envelope->tick() * echo->tick(lastSample)); - else if (effect == 1) - inSample = inout->tick(envelope->tick() * shifter->tick(lastSample)); - else if (effect == 2) - inSample = inout->tick(envelope->tick() * chorus->tick(lastSample)); - else if (effect == 3) - inSample = inout->tick(envelope->tick() * prcrev->tick(lastSample)); - else if (effect == 4) - inSample = inout->tick(envelope->tick() * jcrev->tick(lastSample)); - else if (effect == 5) - inSample = inout->tick(envelope->tick() * nrev->tick(lastSample)); - lastSample = inSample; - } - if (numStrings) { - score->parseThis(inputString[outOne]); - type = score->getType(); - if (type > 0) { - switch(type) { - case __SK_NoteOn_: - // check to see if velocity is zero ... really a NoteOff - if (( byte3 = score->getByteThree() ) == 0) { // NoteOff - envelope->setRate(0.001); - envelope->setTarget(0.0); - } - else { // really a NoteOn - envelope->setRate(0.001); - envelope->setTarget(1.0); - } - break; - - case __SK_NoteOff_: - envelope->setRate(0.001); - envelope->setTarget(0.0); - break; - - case __SK_ControlChange_: - j = (int) score->getByteTwo(); - byte3 = score->getByteThree(); - if (j == 20) effect = (int) byte3; // effect change - else if (j == 21) { // effects mix - echo->setEffectMix(byte3*NORM_7); - shifter->setEffectMix(byte3*NORM_7); - chorus->setEffectMix(byte3*NORM_7); - prcrev->setEffectMix(byte3*NORM_7); - jcrev->setEffectMix(byte3*NORM_7); - nrev->setEffectMix(byte3*NORM_7); - } - else if (j == 22) { // effect1 parameter change - echo->setDelay(byte3*NORM_7*SRATE*0.95 + 2); - shifter->setShift(byte3*NORM_7*3 + 0.25); - chorus->setModFreq(byte3*NORM_7); - } - else if (j == 23) { // effect1 parameter change - chorus->setModDepth(byte3*NORM_7*0.2); - } - break; - } - } - outOne += 1; - if (outOne == MAX_IN_STRINGS) outOne = 0; - numStrings--; - } - } - - envelope->setRate(0.001); - envelope->setTarget(0.0); - for (i=0;itick(envelope->tick() * echo->tick(lastSample)); - else if (effect == 1) - inSample = inout->tick(envelope->tick() * shifter->tick(lastSample)); - else if (effect == 2) - inSample = inout->tick(envelope->tick() * chorus->tick(lastSample)); - else if (effect == 3) - inSample = inout->tick(envelope->tick() * prcrev->tick(lastSample)); - else if (effect == 4) - inSample = inout->tick(envelope->tick() * jcrev->tick(lastSample)); - else if (effect == 5) - inSample = inout->tick(envelope->tick() * nrev->tick(lastSample)); - lastSample = inSample; - } - - delete inout; - delete echo; - delete shifter; - delete chorus; - delete prcrev; - delete jcrev; - delete nrev; - delete score; - delete envelope; - - printf("effects finished ... goodbye.\n"); - return 0; -} diff --git a/effects/effects.opt b/effects/effects.opt deleted file mode 100644 index c79140393840425f0d68b251fd347516e7c4de7b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 48640 zcmeI5Npl-T7=~MpoybY-D2Zc-eG;-k7D&PxAUKv{P>5q=6B~jlYAm&F;qi=WX6#^2 z=D>}8D~{nnapo70Dt-VQIff$?#UG%8dB0g?$#_!?#aQ*W>YZs#f7AWV)2%st)!q8( z$KAKS{_gHy)RJ^wZBc(Mw5qLD*Hg%gf|OAxUs#ZQe3m>eF>N9Ox8bXSe%k^yLoJZ> z`8FsGwL;sW9gy^M8_w;}E(k+F?S}S1d!Y_!A0&2NIPZt}@uHrlljX9zN}fM99YO1^ zno^!BD^nGeh9^Vt!-RBfw945~O~DwIu`7P8Vp=H*{FK3p)PvR?bsg<%dzH2&t*4GoF^bwxq5s79ZF+oM7kuwf_T1>C zGp$D_Om}Y7^QT6mg7|!@=#}LLaQ`oo`{}PwibK=TFq-H@J9}`fO5Kvr;4?27aYJ52 zMv%ub@@rmlY1M5=p(urK8JKk=Uw?}Innd+~K=OVJ-;VXywdx%ydFwXg0|4EtS_Xwy z#A^oz;d>CqgW4Iqq1V2*K8t1iYRaUWr59530siXx%8_5+h)?)&{u{iS-<|J9Ya2>2 zuY2H=3GD>0?Ksw-GDhW|(63A?g+5~<0TLhq5+DH*AOR8}0TLjAgc3+Ks~bOmdtJSs ze=DIL(k&8bECL@Wb)(!~QYX~p|N3Ab|2~Vjehr1ud0Ycv8$ivKOQ{(1x}l5MO@mUYoo?=J*Sr4t_%iLUzr|Y1 z?RU`r<5lfvm4&tL9zMgMu0h3PE?eZA$`i~WP= ztB<>)W#C3ZY_u1aEq^uLTe9?GH3vo6bj2G+hev|Fx*blx6!7Tu_Rnmsu^t1YLjU1Pv?iZfXF9u}`y5Ed_avS8x>*e+c!(L zcB5Kb(jB==Bh|-c1A~nJasH}@BWXkRJAYJji!3{pWJABOYh%E z``hvVKVjOBQ;SM*Rf7!<+@A-P2*}?e6`2b=2TpQb=vd$a;9(kb7gJxl|0ib zP1w`g_T@ei`sHTkLZP5N&loN_mg$!qJ1*Rc!nV9^444zzxahi$8<%vUr1gqp^yz8G zor|yDhpT(@mZc|5%gEcF?_%f1s`?J2eE${4F5n4D_KZ1Zq1v|#x?F8^B&fumg{ws) zSMth^SE??5ALaWlxUM;8^f)ti(F>~3MO}>D!0-2FXRqa$zLC?m<4(hye(WV_+7*)z zVbT$qlx9msZH&zs*R<=zb$qmFkhk^QX2HjbdvC_7fcqE*U11IR$l0KcYF9sjO?zn5 zKdaqw%efxc|0#-gheboaS(q}ile#b!mwtxQU18}}EQ_zX^K+DS=51e3V0X;ivd(`2 zlT2)~wB;}5{s9*^qMvkexqiA0llIW9rFTD`!jQ;azHD4^e4|(R$3FL<_%N(I;PoN?dC9zXui5g?" with flags "" - -Creating temp file "C:\WINDOWS\TEMP\RSP1050.TMP" with contents -Creating command line "cl.exe @C:\WINDOWS\TEMP\RSP1050.TMP" -Creating temp file "C:\WINDOWS\TEMP\RSP1051.TMP" with contents -Creating command line "link.exe @C:\WINDOWS\TEMP\RSP1051.TMP" -Compiling... -Chorus.cpp -DLineL.cpp -DLineN.cpp -Echo.cpp -effects.cpp -Envelope.cpp -Filter.cpp -JCRev.cpp -NRev.cpp -Object.cpp -PitShift.cpp -PRCRev.cpp -RawWvIn.cpp -Reverb.cpp -RTDuplex.cpp -RTSoundIO.cpp -SKINI11.cpp -swapstuf.cpp -WvIn.cpp -Linking... - - - -effects.exe - 0 error(s), 0 warning(s) diff --git a/effects/threads.cpp b/effects/threads.cpp deleted file mode 100644 index 4313af0..0000000 --- a/effects/threads.cpp +++ /dev/null @@ -1,279 +0,0 @@ -// Thread functions for use with syntmono. -// -// No mutexes are currently being used when accessing -// the global variables shared between these threads -// and the main() routine. In a single processor -// environment, no problems have resulted from such data -// sharing. However, if STK is to be run on a true parallel -// processing platform, it is likely that mutexes will be -// necessary. While the mutex calls are simple to code, I -// am trying to keep the code as generic as possible. A -// quick investigation of threads under Windoze indicates -// that mutex functionality is not available, at least with -// the standard libraries. -// -// Gary P. Scavone, 2000. - -#include "threads.h" - -#if defined(__STK_REALTIME_) - -// Default STK socket port ID number -#define SERVICE_PORT 2001 - -// Do OS dependent declarations and includes -#if (defined(__OS_IRIX_) || defined(__OS_Linux_)) -#include -#include -#include -#include -#include -#include - -pthread_t string_thread; - -#elif defined(__OS_Win_) -#include -#include - -unsigned long string_thread; - -#endif - - -// The thread function protocols are slightly different -// under Windoze ... but of course! - -#if (defined(__OS_IRIX_) || defined(__OS_Linux_)) - -void *newStringByPipe(void *) - -#elif defined(__OS_Win_) - -void newStringByPipe(void *) - -#endif - -{ - extern int numStrings, notDone; - extern char **inputString; - int i; - - // Malloc inputString. - inputString = (char **) malloc(MAX_IN_STRINGS * sizeof(char *)); - for ( i=0;i MAX_IN_STRINGS) { - fprintf(stderr,"Losing MIDI data ... try increasing MAX_IN_STRINGS.\n"); - numStrings--; - } - inOne++; - if (inOne == MAX_IN_STRINGS) inOne = 0; - } - } - - // Free inputString. - for ( i=0;i maxfd) maxfd = accept_id; - FD_CLR(soc_id, &rmask); - } - for (fd=0;fd<=maxfd;fd++) { // look for other sockets with data - if (FD_ISSET(fd, &rmask)) { // process the data - parsing = 1; - while (parsing) { - i = recv(fd, socBuf, STRING_LEN,0); - if (i==0) { - printf("Closing a socket connection.\n"); - FD_CLR(fd, &mask); -#if defined(__OS_Win_) - closesocket(fd); -#else - close(fd); -#endif - parsing = 0; - } - n = 0; - while (n < i) { - inputString[inOne][m++] = socBuf[n]; - if (socBuf[n++] == '\n') { - if (inputString[inOne][2] == 'i' && inputString[inOne][3] == 't' - && inputString[inOne][1] == 'x' && inputString[inOne][0] == 'E') { - notDone = 0; - n = i; - parsing = 0; - } - else { - m = 0; - if (n >= i) parsing = 0; - numStrings++; - if (numStrings > MAX_IN_STRINGS) { - fprintf(stderr,"Losing MIDI data ... try increasing MAX_IN_STRINGS.\n"); - numStrings--; - } - inOne++; - if (inOne == MAX_IN_STRINGS) inOne = 0; - memset(inputString[inOne], 0, STRING_LEN); - } - } - } - } - } - } - } -#if defined(__OS_Win_) // Stupid Windoze only stuff - closesocket(soc_id); - WSACleanup(); -#else - shutdown(soc_id,0); -#endif - - // Free inputString. - for ( i=0;i +#include +#include +#include +#include +#include +#include +#include +#include + +void *stdinHandler(void *); + +#elif defined(__OS_Win_) +#include +#include + +void stdinHandler(void *); + +#endif + +#endif // __STK_REALTIME + +#define STK_MIDI 0x0001 +#define STK_PIPE 0x0002 +#define STK_SOCKET 0x0004 +#define STK_SCOREFILE 0x0008 + +#define MESSAGE_LENGTH 128 +#define MAX_MESSAGES 25 +#define STK_SOCKET_PORT 2001 + +class Controller : public Object +{ + protected: + int source; + long default_ticks; + int type; + MY_FLOAT channel; + MY_FLOAT byte2; + MY_FLOAT byte3; + char message[MAX_MESSAGES][MESSAGE_LENGTH]; + int msg_index; + int num_messages; + SKINI11 *score; + +#if defined(__STK_REALTIME_) + fd_set mask; + int maxfd; + int fd[16]; + int local_socket; + RtMidi *midi_input; + int parseSocketData(int fd); +#if (defined(__OS_IRIX_) || defined(__OS_Linux_)) + pthread_t stdin_thread; +#elif defined(__OS_Win_) + unsigned long stdin_thread; +#endif +#endif // __STK_REALTIME + + public: + Controller(int inputMask); + ~Controller(); + void setDefaultTicks(long nSamples); + int getNextMessage(); + int getType(); + MY_FLOAT getByte2(); + MY_FLOAT getByte3(); + MY_FLOAT getChannel(); +}; + +#endif // defined(__Controller_h) diff --git a/STK/DCBlock.h b/include/DCBlock.h similarity index 100% rename from STK/DCBlock.h rename to include/DCBlock.h diff --git a/STK/DLineA.h b/include/DLineA.h similarity index 100% rename from STK/DLineA.h rename to include/DLineA.h diff --git a/include/DLineL.h b/include/DLineL.h new file mode 100644 index 0000000..403344e --- /dev/null +++ b/include/DLineL.h @@ -0,0 +1,45 @@ +/*******************************************/ +/* + Linearly Interpolating Delay Line + Object by Perry R. Cook 1995-96. + Added methods by Julius Smith, 2000. + + This one uses a delay line of maximum + length specified on creation, and + linearly interpolates fractional + length. It is designed to be more + efficient if the delay length is not + changed very often. +*/ +/*******************************************/ + +#if !defined(__DLineL_h) +#define __DLineL_h + +#include "Filter.h" + +class DLineL : public Filter +{ + protected: + long inPoint; + long outPoint; + long length; + MY_FLOAT alpha; + MY_FLOAT omAlpha; + MY_FLOAT currentDelay; + public: + DLineL(); + DLineL(long max_length); + ~DLineL(); + void clear(); + void setDelay(MY_FLOAT length); + MY_FLOAT delay(void); + MY_FLOAT energy(void); + long currentInPoint(void); + long currentOutPoint(void); + MY_FLOAT contentsAt(int n); + MY_FLOAT contentsAtNowMinus(int n); + MY_FLOAT tick(MY_FLOAT sample); +}; + +#endif diff --git a/include/DLineN.h b/include/DLineN.h new file mode 100644 index 0000000..be7b65e --- /dev/null +++ b/include/DLineN.h @@ -0,0 +1,45 @@ +/*******************************************/ +/* + Non-Interpolating Delay Line + Object by Perry R. Cook 1995-96. + Revised by Gary Scavone, 1999. + Added methods by Julius Smith, 2000. + + This one uses either a delay line of + maximum length specified on creation + or a default length of 2047 samples. + A non-interpolating delay line is + typically used in non-time varying + (reverb) applications. + */ +/*******************************************/ + +#if !defined(__DLineN_h) +#define __DLineN_h + +#include "Filter.h" + +class DLineN : public Filter +{ +protected: + long inPoint; + long outPoint; + long length; + MY_FLOAT currentDelay; +public: + DLineN(); + DLineN(long max_length); + ~DLineN(); + void clear(); + void setDelay(MY_FLOAT length); + MY_FLOAT energy(void); + long currentInPoint(void); + long currentOutPoint(void); + MY_FLOAT contentsAt(int n); + MY_FLOAT contentsAtNowMinus(int n); + MY_FLOAT delay(void); + MY_FLOAT tick(MY_FLOAT sample); +}; + +#endif + diff --git a/STK/DrumSynt.h b/include/DrumSynt.h similarity index 100% rename from STK/DrumSynt.h rename to include/DrumSynt.h diff --git a/STK/Envelope.h b/include/Envelope.h similarity index 100% rename from STK/Envelope.h rename to include/Envelope.h diff --git a/include/FIR.h b/include/FIR.h new file mode 100644 index 0000000..8b9df30 --- /dev/null +++ b/include/FIR.h @@ -0,0 +1,34 @@ +/********************************************/ +/* + General Finite-Impulse-Response (FIR) + Digital Filter Class + by Julius Smith, 1997 +*/ +/********************************************/ + +#if !defined(__FIR_h) +#define __FIR_h + +#include "Object.h" + +class FIR : public Object +{ +protected: + int length; + MY_FLOAT *coeffs; + MY_FLOAT *pastInputs; + int piOffset; + MY_FLOAT delay; +public: + FIR(int length); + FIR(const char *filterFile); + ~FIR(); + void clear(void); + void setCoeffs(MY_FLOAT *theCoeffs); + MY_FLOAT tick(MY_FLOAT input); + MY_FLOAT lastOutput; + MY_FLOAT getDelay(MY_FLOAT freq); + int getLength(void); +}; + +#endif diff --git a/STK/FM4Alg3.h b/include/FM4Alg3.h similarity index 100% rename from STK/FM4Alg3.h rename to include/FM4Alg3.h diff --git a/STK/FM4Alg4.h b/include/FM4Alg4.h similarity index 100% rename from STK/FM4Alg4.h rename to include/FM4Alg4.h diff --git a/STK/FM4Alg5.h b/include/FM4Alg5.h similarity index 100% rename from STK/FM4Alg5.h rename to include/FM4Alg5.h diff --git a/STK/FM4Alg6.h b/include/FM4Alg6.h similarity index 100% rename from STK/FM4Alg6.h rename to include/FM4Alg6.h diff --git a/STK/FM4Alg8.h b/include/FM4Alg8.h similarity index 100% rename from STK/FM4Alg8.h rename to include/FM4Alg8.h diff --git a/STK/FM4Op.h b/include/FM4Op.h similarity index 100% rename from STK/FM4Op.h rename to include/FM4Op.h diff --git a/STK/FMVoices.h b/include/FMVoices.h similarity index 100% rename from STK/FMVoices.h rename to include/FMVoices.h diff --git a/STK/Filter.h b/include/Filter.h similarity index 100% rename from STK/Filter.h rename to include/Filter.h diff --git a/STK/Flute.h b/include/Flute.h similarity index 100% rename from STK/Flute.h rename to include/Flute.h diff --git a/STK/FormSwep.h b/include/FormSwep.h similarity index 100% rename from STK/FormSwep.h rename to include/FormSwep.h diff --git a/STK/HeavyMtl.h b/include/HeavyMtl.h similarity index 100% rename from STK/HeavyMtl.h rename to include/HeavyMtl.h diff --git a/STK/Instrmnt.h b/include/Instrmnt.h similarity index 100% rename from STK/Instrmnt.h rename to include/Instrmnt.h diff --git a/STK/JCRev.h b/include/JCRev.h similarity index 100% rename from STK/JCRev.h rename to include/JCRev.h diff --git a/STK/JetTabl.h b/include/JetTabl.h similarity index 100% rename from STK/JetTabl.h rename to include/JetTabl.h diff --git a/STK/LipFilt.h b/include/LipFilt.h similarity index 100% rename from STK/LipFilt.h rename to include/LipFilt.h diff --git a/STK/Mandolin.h b/include/Mandolin.h similarity index 100% rename from STK/Mandolin.h rename to include/Mandolin.h diff --git a/STK/MatWvIn.h b/include/MatWvIn.h similarity index 87% rename from STK/MatWvIn.h rename to include/MatWvIn.h index 19bd5bb..1caa60d 100644 --- a/STK/MatWvIn.h +++ b/include/MatWvIn.h @@ -25,9 +25,13 @@ class MatWvIn : public WvIn { - public: - MatWvIn(char *fileName, char *mode); - ~MatWvIn(); +public: + MatWvIn(char *fileName, char *mode); + ~MatWvIn(); +protected: + void getData(long index); + int doSwap; + int interleaved; }; #endif diff --git a/STK/MatWvOut.h b/include/MatWvOut.h similarity index 78% rename from STK/MatWvOut.h rename to include/MatWvOut.h index 9c3fba0..cfbcdce 100644 --- a/STK/MatWvOut.h +++ b/include/MatWvOut.h @@ -15,28 +15,20 @@ /* specifications. */ /*******************************************/ -#include "Object.h" -#include "WvOut.h" - #if !defined(__MatWvOut_h) #define __MatWvOut_h -#define MAT_BUFFER_SIZE 1024 +#include "Object.h" +#include "WvOut.h" class MatWvOut : public WvOut { protected: FILE *fd; - double data[MAT_BUFFER_SIZE]; /* not MY_FLOAT because MAT-file uses doubles */ - INT32 counter; - INT32 totalCount; - int channels; + double *matdata; /* not MY_FLOAT because MAT-file uses doubles */ public: - MatWvOut(char *infileName); - MatWvOut(int chans, char *infileName); + MatWvOut(char *infileName, int chans = 1); ~MatWvOut(); - INT32 getCounter(); - MY_FLOAT getTime(); void tick(MY_FLOAT sample); void mtick(MY_MULTI samples); }; diff --git a/include/Modal4.h b/include/Modal4.h new file mode 100644 index 0000000..502f578 --- /dev/null +++ b/include/Modal4.h @@ -0,0 +1,55 @@ +/*******************************************/ +/* + Four Resonance Modal Synthesis Instrument + by Perry R. Cook, 1995-2000 + + This instrument contains an excitation + wavetable, an envelope, an oscillator, + and four resonances (Non-Sweeping BiQuad + Filters). +*/ +/*******************************************/ + +#if !defined(__Modal4_h) +#define __Modal4_h + +#include "Instrmnt.h" +#include "Envelope.h" +#include "RawWvIn.h" +#include "BiQuad.h" +#include "OnePole.h" + +class Modal4 : public Instrmnt +{ +protected: + Envelope *envelope; + RawWvIn *wave; + BiQuad *filters[4]; + OnePole *onepole; + RawWvIn *vibr; + MY_FLOAT vibrGain; + MY_FLOAT masterGain; + MY_FLOAT directGain; + MY_FLOAT stickHardness; + MY_FLOAT strikePosition; + MY_FLOAT baseFreq; + MY_FLOAT ratios[4]; + MY_FLOAT resons[4]; +public: + Modal4(); + virtual ~Modal4(); + void clear(); + virtual void setFreq(MY_FLOAT frequency); + void setRatioAndReson(int whichOne, MY_FLOAT ratio, MY_FLOAT reson); + void setMasterGain(MY_FLOAT aGain); + void setDirectGain(MY_FLOAT aGain); + void setFiltGain(int whichOne, MY_FLOAT gain); + virtual void strike(MY_FLOAT amplitude); + virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp); + virtual void noteOff(MY_FLOAT amp); + void damp(MY_FLOAT amplitude); + virtual void controlChange(int number, MY_FLOAT value); + virtual MY_FLOAT tick(); +}; + +#endif diff --git a/include/ModalBar.h b/include/ModalBar.h new file mode 100644 index 0000000..24feb4c --- /dev/null +++ b/include/ModalBar.h @@ -0,0 +1,30 @@ +/*******************************************/ +/* + ModalBar SubClass of Modal4 Instrument + by Perry R. Cook, 1999-2000 + + Controls: CONTROL1 = stickHardness + CONTROL2 = strikePosition + CONTROL3 = Mode Presets +*/ +/*******************************************/ + +#if !defined(__ModalBar_h) +#define __ModalBar_h + +#include "Modal4.h" + +class ModalBar : public Modal4 +{ +private: +public: + ModalBar(); + ~ModalBar(); + void setStickHardness(MY_FLOAT hardness); + void setStrikePosition(MY_FLOAT position); + void setModalPreset(int which); + void setModulationDepth(MY_FLOAT mDepth); + virtual void controlChange(int number, MY_FLOAT value); +}; + +#endif diff --git a/STK/Modulatr.h b/include/Modulatr.h similarity index 100% rename from STK/Modulatr.h rename to include/Modulatr.h diff --git a/STK/Moog1.h b/include/Moog1.h similarity index 100% rename from STK/Moog1.h rename to include/Moog1.h diff --git a/STK/NRev.h b/include/NRev.h similarity index 100% rename from STK/NRev.h rename to include/NRev.h diff --git a/STK/Noise.h b/include/Noise.h similarity index 100% rename from STK/Noise.h rename to include/Noise.h diff --git a/STK/Object.h b/include/Object.h similarity index 62% rename from STK/Object.h rename to include/Object.h index 68ea5a3..ec57871 100644 --- a/STK/Object.h +++ b/include/Object.h @@ -33,56 +33,34 @@ class Object #elif defined(__OS_Linux_) /* For Linux */ #define __STK_REALTIME_ #define __OSS_API_ /* Use OSS API */ +// #define __MIDIATOR_ /* Use special MIDIator support */ +// #define __ALSA_API_ /* Use ALSA API */ #define __LITTLE_ENDIAN__ #define RANDLIMIT 2147483647 #elif defined(__OS_Win_) /* For WindowsXX or NT */ #define __STK_REALTIME_ - #define __WINDS_API_ /* For DirectSound API */ -// #define __WINMM_API_ /* For Win MM API */ #define __LITTLE_ENDIAN__ #define RANDLIMIT 32767 #endif -/* Real-time audio input and output buffer size. The value of - * this buffer should be an integer multiple of the number of - * channels your application plans to support, in order that - * multi-channel data is not split across multiple buffers. If - * clicks are occuring in the input or output sound stream, a - * larger buffer size may help. Larger buffer sizes, however, - * produce more latency between input and output. - * - * NOTE FOR WINDOZE USERS: Given inherent delays in the audio - * input and output mechanism under Windoze, there is a trade-off - * between smoothness of fast SKINI parameter updates and input/output - * latency as discussed above. You can use buffer sizes as low - * as 100 (maybe lower) for delay critical applications, but in - * this case SKINI parameter updates will be clumped together - * and sound unnatural. If you want smoother parameter updates - * and you can live with more delay, try using buffer sizes - * closer to 1000. If you need smooth parameter updates AND - * low delay, don't use Windoze! +/* + Real-time audio input and output buffer size. If clicks + are occuring in the input or output sound stream, a + larger buffer size may help. Larger buffer sizes, however, + produce more latency between input and output. */ #define RT_BUFFER_SIZE 256 -/* This sets the maximum number of simultaneous - * (within a buffer) MIDI messages that can be - * serviced before messages begin to be lost or - * overwritten. It should be a function of - * RT_BUFFER_SIZE - */ -#define MAX_IN_STRINGS 25 - -/* The following definition is concatenated to the - * beginning of all references to rawwave files in - * the various STK core classes (ex. Clarinet.cpp). - * If you wish to move the rawwaves directory to a - * different location in your file system, you will - * need to set this path definition appropriately. - * The current definition is a relative reference - * that will work "out of the box" for the STK - * distribution. - */ -#define RAWWAVE_PATH "../" +/* + The following definition is concatenated to the beginning + of all references to rawwave files in the various STK core + classes (ex. Clarinet.cpp). If you wish to move the + rawwaves directory to a different location in your file + system, you will need to set this path definition + appropriately. The current definition is a relative reference + that will work "out of the box" for the STK distribution. +*/ +#define RAWWAVE_PATH "../../" /* Sampling Rate */ #define SRATE (MY_FLOAT) 22050.0 @@ -96,8 +74,8 @@ class Object #if !defined(PI) #define PI (MY_FLOAT) 3.14159265359 #endif -#define TWO_PI (MY_FLOAT) 6.28318530718 -#define ONE_OVER_TWO_PI (MY_FLOAT) 0.15915494309 +#define TWO_PI (MY_FLOAT) (MY_FLOAT) (2 * PI) +#define ONE_OVER_TWO_PI (MY_FLOAT) (1.0 / PI) #define SQRT_TWO 1.414213562 /* Useful random number generator values */ @@ -141,7 +119,11 @@ typedef MY_FLOAT *MY_MULTI; typedef signed short INT16; /* INT32 is just that ... a 32-bit signed integer. */ -typedef signed long INT32; +typedef int INT32; + +/* Boolean values */ +#define FALSE 0 +#define TRUE 1 /* Debugging define, causes massive printf's to come out. * Also enables timing calculations in WaveOut class, other stuff. diff --git a/include/OnePole.h b/include/OnePole.h new file mode 100644 index 0000000..caeecd5 --- /dev/null +++ b/include/OnePole.h @@ -0,0 +1,44 @@ +/*******************************************/ +/* + One Pole Filter Class, + by Perry R. Cook, 1995-96. + Added methods by Julius Smith, 2000. + + The parameter gain is an additional + gain parameter applied to the filter + on top of the normalization that takes + place automatically. So the net max + gain through the system equals the + value of gain. sgain is the combina- + tion of gain and the normalization + parameter, so if you set the poleCoeff + to alpha, sgain is always set to + gain * (1.0 - fabs(alpha)). +*/ +/*******************************************/ + +#if !defined(__OnePole_h) +#define __OnePole_h + +#include "Filter.h" + +class OnePole : public Filter +{ +protected: + MY_FLOAT poleCoeff; + MY_FLOAT sgain; +public: + OnePole(); + OnePole(MY_FLOAT thePole); + ~OnePole(); + void clear(); + void setB0(MY_FLOAT aValue); /* set numerator b0 in b0/(1+a1/z) */ + void setNum(MY_FLOAT *values); + void setA1(MY_FLOAT aValue); /* set denominator a1 in b0/(1+a1/z) */ + void setDen(MY_FLOAT *values); + void setPole(MY_FLOAT aValue); + void setGain(MY_FLOAT aValue); + MY_FLOAT tick(MY_FLOAT sample); +}; + +#endif diff --git a/STK/OneZero.h b/include/OneZero.h similarity index 100% rename from STK/OneZero.h rename to include/OneZero.h diff --git a/STK/PRCRev.h b/include/PRCRev.h similarity index 100% rename from STK/PRCRev.h rename to include/PRCRev.h diff --git a/STK/PercFlut.h b/include/PercFlut.h similarity index 100% rename from STK/PercFlut.h rename to include/PercFlut.h diff --git a/STK/Plucked.h b/include/Plucked.h similarity index 100% rename from STK/Plucked.h rename to include/Plucked.h diff --git a/STK/Plucked2.h b/include/Plucked2.h similarity index 100% rename from STK/Plucked2.h rename to include/Plucked2.h diff --git a/STK/PoleZero.h b/include/PoleZero.h similarity index 80% rename from STK/PoleZero.h rename to include/PoleZero.h index 1f273db..31dab14 100644 --- a/STK/PoleZero.h +++ b/include/PoleZero.h @@ -15,14 +15,16 @@ class PoleZero : public Filter { protected: - MY_FLOAT poleCoeff; - MY_FLOAT zeroCoeff; + MY_FLOAT a1Coeff; + MY_FLOAT b0Coeff; + MY_FLOAT b1Coeff; public: PoleZero(); ~PoleZero(); void clear(); - void setPoleCoeff(MY_FLOAT coeff); - void setZeroCoeff(MY_FLOAT coeff); + void setA1(MY_FLOAT coeff); + void setB0(MY_FLOAT coeff); + void setB1(MY_FLOAT coeff); void setGain(MY_FLOAT aValue); MY_FLOAT tick(MY_FLOAT sample); }; diff --git a/STK/RawWvIn.h b/include/RawWvIn.h similarity index 79% rename from STK/RawWvIn.h rename to include/RawWvIn.h index ca79e23..9ffd02e 100644 --- a/STK/RawWvIn.h +++ b/include/RawWvIn.h @@ -1,6 +1,6 @@ /*******************************************/ /* RawWvIn Input Class, */ -/* by Gary P. Scavone, 1999 */ +/* by Gary P. Scavone, 2000 */ /* */ /* This object inherits from WvIn and is */ /* used to open raw 16-bit data (signed */ @@ -18,9 +18,11 @@ class RawWvIn : public WvIn { - public: - RawWvIn(char *fileName, char *mode); - ~RawWvIn(); +public: + RawWvIn(char *fileName, const char *mode); + ~RawWvIn(); +protected: + void getData(long index); }; #endif diff --git a/STK/RawWvOut.h b/include/RawWvOut.h similarity index 76% rename from STK/RawWvOut.h rename to include/RawWvOut.h index 9d96e3d..f91a0df 100644 --- a/STK/RawWvOut.h +++ b/include/RawWvOut.h @@ -9,28 +9,19 @@ /* monaural and big-endian. */ /*******************************************/ -#include "Object.h" -#include "WvOut.h" - #if !defined(__RawWvOut_h) #define __RawWvOut_h -#define RAW_BUFFER_SIZE 1024 +#include "Object.h" +#include "WvOut.h" class RawWvOut : public WvOut { protected: FILE *fd; - INT16 data[RAW_BUFFER_SIZE]; - long counter; - long totalCount; - int channels; public: - RawWvOut(char *fileName); - RawWvOut(int chans, char *fileName); + RawWvOut(char *fileName, int chans = 1); ~RawWvOut(); - long getCounter(); - MY_FLOAT getTime(); void tick(MY_FLOAT sample); void mtick(MY_MULTI samples); }; diff --git a/STK/ReedTabl.h b/include/ReedTabl.h similarity index 100% rename from STK/ReedTabl.h rename to include/ReedTabl.h diff --git a/STK/Reverb.h b/include/Reverb.h similarity index 100% rename from STK/Reverb.h rename to include/Reverb.h diff --git a/STK/Rhodey.h b/include/Rhodey.h similarity index 100% rename from STK/Rhodey.h rename to include/Rhodey.h diff --git a/include/RtAudio.h b/include/RtAudio.h new file mode 100644 index 0000000..035eb47 --- /dev/null +++ b/include/RtAudio.h @@ -0,0 +1,155 @@ +/******************************************/ +/* + RtAudio.cpp + Realtime Sound I/O Object for STK + by Gary P. Scavone, 1998-2000. + + The sound output sections of this object + were originally based in part on code by + Doug Scott (SGI), Tim Stilson (Linux), + Bill Putnam (Win Wav), and R. Marsanyi + (DirectSound). The latest DirectSound + code was re-written by Dave Chisholm at + CCRMA. + + This object provides a standard API + across all platforms for STK realtime + audio input/output. Multi-channel + support is supported when provided by + the soundcard. + + Only 16-bit integer input/output + routines are written for the moment + though it would be simple to overload + the methods for other data types. +*/ +/******************************************/ + +#if !defined(__RtAudio_h) +#define __RtAudio_h + +#include "Object.h" +#include "StkError.h" + +#if defined(__OS_IRIX_) + #include + #include + #include + +#elif defined(__ALSA_API_) + #include + #include + +#elif defined(__OSS_API_) + #include + #include + #include + #include + #include + +#elif defined(__OS_Win_) + #include + #include + #include + #include "mmsystem.h" + + // this is how often we check for new audio input (milliseconds) + #define TIMER_PERIOD 20 + // the resolution which we tell windows we are willing to tolerate (milliseconds) + #define TIMER_RESOLUTION 5 + // in seconds, doesn't have a real effect on latency + #define DS_CAPTURE_BUFFER_SIZE 2 + // this controls the inherent latency of the output ... more fragments produce + // a more stable, though slower, response + #define NUM_FRAGMENTS 10 + #define MAX_DEVICES 10 + + typedef struct DeviceInfo { + LPGUID guid; + char* description; + char* moduleName; + } DeviceInfo; + +#endif + +class RtAudio : public Object +{ +protected: +#if (defined(__STK_REALTIME_) && defined(__OS_IRIX_)) + int stk_chans; + ALport audio_port_in; + ALport audio_port_out; + +#elif (defined(__STK_REALTIME_) && defined(__OSS_API_)) + int audio_fd; + +#elif (defined(__STK_REALTIME_) && defined(__ALSA_API_)) + snd_pcm_t *ohandle; + snd_pcm_t *ihandle; + int stk_chans; // the number of channels we want to use + int dev_ichans; // the number of input channels the device needs + int dev_ochans; // the number of output channels the device needs + int ifragsize; + int ofragsize; + int bytes_per_sample; + unsigned int direction; + unsigned char *outbuf; + unsigned char *inbuf; + +#elif (defined(__STK_REALTIME_) && defined(__OS_Win_) ) + + DeviceInfo devices[MAX_DEVICES]; + int numDevices; + char errormsg[256]; + long inputBufferSize; + BYTE *inputBuffer; + UINT nextRecordRead, nextRecordWrite; + MY_FLOAT sampleRate; + + //these are the variable relating to direct sound output + LPDIRECTSOUND directSoundObject; + LPDIRECTSOUNDBUFFER directSoundBuffer; + DWORD directSoundBufferSize; + UINT nextWritePos; + + //direct sound input + LPDIRECTSOUNDCAPTURE directSoundCaptureObject; + LPDIRECTSOUNDCAPTUREBUFFER directSoundCaptureBuffer; + DWORD directSoundCaptureBufferSize; + + // our periodic function will set this flag if something goes wrong + bool internalError; + bool playing, recording; + UINT timerID; + + static void CALLBACK PeriodicCallbackFn(UINT uID, UINT uMsg, DWORD dwUser, + DWORD dw1, DWORD dw2); + static bool CALLBACK SoundDeviceEnumCallback(LPGUID lpguid, + LPCSTR lpcstrDescription, + LPCSTR lpcstrModule, + LPVOID lpContext); + + void addDevice(LPGUID guid, char* description, char* moduleName); + void getInputSamples(); + static char* getErrorMessage(int code); + +#endif + +public: + RtAudio(int channels, MY_FLOAT srate, const char *mode, int device = -1); + ~RtAudio(); + int playBuffer(INT16 *buf, int bufsize); + int recordBuffer(INT16 *buf, int bufsize); + +#if (defined(__STK_REALTIME_) && defined(__OS_Win_) ) + // Sets the pointer to its own internal buffer, returning + // amount of data available ... slightly more efficient. + int recordBuffer(INT16**); + void stopPlay(); + void startPlay(); + void stopRecord(); + void startRecord(); +#endif +}; + +#endif diff --git a/STK/RTDuplex.h b/include/RtDuplex.h similarity index 68% rename from STK/RTDuplex.h rename to include/RtDuplex.h index 0f95785..8ddd36b 100644 --- a/STK/RTDuplex.h +++ b/include/RtDuplex.h @@ -11,29 +11,29 @@ /* Windows95/98 platforms. */ /*******************************************/ -#if !defined(__RTDuplex_h) -#define __RTDuplex_h +#if !defined(__RtDuplex_h) +#define __RtDuplex_h #include "Object.h" -#include "RTSoundIO.h" +#include "RtAudio.h" -class RTDuplex : public Object +class RtDuplex : public Object { protected: - RTSoundIO *soundIO; - // Add an extra 10 samples to indata[] and outdata[] just to be safe - short indata[RT_BUFFER_SIZE+10]; - short outdata[RT_BUFFER_SIZE+10]; + RtAudio *sound_dev; + INT16 *indata; + INT16 *outdata; + long data_length; long readCounter; long writeCounter; int channels; MY_FLOAT gain; MY_FLOAT *insamples; public: - RTDuplex(MY_FLOAT srate, int chans); - ~RTDuplex(); + RtDuplex(int chans = 1, MY_FLOAT srate = SRATE, int device = -1); + ~RtDuplex(); MY_FLOAT tick(MY_FLOAT outsample); MY_MULTI mtick(MY_MULTI outsamples); }; -#endif // defined(__RTDuplex_h) +#endif // defined(__RtDuplex_h) diff --git a/include/RtMidi.h b/include/RtMidi.h new file mode 100644 index 0000000..662a6e3 --- /dev/null +++ b/include/RtMidi.h @@ -0,0 +1,66 @@ +/******************************************/ +/* + RtMidi.cpp + Realtime MIDI I/O Object for STK, + by Gary P. Scavone, 1998-2000. + Based in part on code by Perry + Cook (SGI), Paul Leonard (Linux), + the RoseGarden team (Linux), and + Bill Putnam (Win95/NT). + + At the moment, this object only + handles MIDI input, though MIDI + output code can go here when someone + decides they need it (and writes it). + + This object opens a MIDI input device + and parses MIDI messages into a MIDI + buffer. Time stamp info is converted + to deltaTime. MIDI data is stored as + MY_FLOAT to conform with SKINI. + + An optional argument to the constructor + can be used to specify a device or card. + When no argument is given, a default + device is opened or a list of available + devices is printed to allow selection + by the user. +*/ +/******************************************/ + +#if !defined(__RtMidi_h) +#define __RtMidi_h + +#include "Object.h" +#include "StkError.h" + +class RtMidi : public Object +{ + protected: + int messageType; + int channel; + float byteTwo; + float byteThree; + MY_FLOAT deltaTime; + public: + RtMidi(int device = -1); + ~RtMidi(); + void printMessage(); + int nextMessage(); + int getType(); + int getChannel(); + MY_FLOAT getByteTwo(); + MY_FLOAT getByteThree(); + MY_FLOAT getDeltaTime(); +}; + +#if defined(__OS_Win_) + +#include +#include + +static void CALLBACK midiInputCallback( HMIDIOUT hmin, UINT inputStatus, + DWORD instancePtr, DWORD midiMessage, DWORD timestamp); + +#endif +#endif diff --git a/STK/RTWvIn.h b/include/RtWvIn.h similarity index 58% rename from STK/RTWvIn.h rename to include/RtWvIn.h index 8078dbf..3a8a71f 100644 --- a/STK/RTWvIn.h +++ b/include/RtWvIn.h @@ -1,6 +1,6 @@ /*******************************************/ -/* RTWvIn Input Class, */ -/* by Gary P. Scavone, 1999 */ +/* RtWvIn Input Class, */ +/* by Gary P. Scavone, 1999-2000 */ /* */ /* This object inherits from WvIn and is */ /* used to read in realtime 16-bit data */ @@ -9,35 +9,36 @@ /* NOTE: This object is NOT intended for */ /* use in achieving simultaneous realtime */ /* audio input/output (together with */ -/* RTWvOut). Under certain circumstances */ +/* RtWvOut). Under certain circumstances */ /* such a scheme is possible, though you */ /* should definitely know what you are */ /* doing before trying. For safer "full- */ -/* duplex" operation, use the RTDuplex */ +/* duplex" operation, use the RtDuplex */ /* class. */ /*******************************************/ -#if !defined(__RTWvIn_h) -#define __RTWvIn_h +#if !defined(__RtWvIn_h) +#define __RtWvIn_h #include "Object.h" -#include "RTSoundIO.h" +#include "RtAudio.h" #include "WvIn.h" -class RTWvIn : public WvIn +class RtWvIn : public WvIn { - protected: - RTSoundIO *soundIO; - short *rtdata; +protected: + RtAudio *sound_dev; + INT16 *rtdata; + INT16 *lastSamples; MY_FLOAT gain; - public: - RTWvIn(MY_FLOAT srate, short chans); - ~RTWvIn(); - void normalize(); - void normalize(MY_FLOAT newPeak); - void addPhaseOffset(MY_FLOAT anAngle); + void getData(long index); +public: + RtWvIn(int chans = 1, MY_FLOAT srate = SRATE, int device = -1); + ~RtWvIn(); + void setRate(MY_FLOAT aRate); + void addTime(MY_FLOAT aTime); void setLooping(int aLoopStatus); - void getMoreData(); + long getSize(); int informTick(); }; diff --git a/STK/RTWvOut.h b/include/RtWvOut.h similarity index 52% rename from STK/RTWvOut.h rename to include/RtWvOut.h index 5146930..c2d080c 100644 --- a/STK/RTWvOut.h +++ b/include/RtWvOut.h @@ -1,33 +1,36 @@ /*******************************************/ -/* Real-Time Wave File Output Class, */ +/* Real-Time Audio Output Class, */ /* by Perry R. Cook, 1996 */ -/* revised by Gary P. Scavone, 1999 */ +/* Revised by Gary P. Scavone, 2000 */ /* */ /* This object opens a realtime soundout */ /* device, and pokes buffers of samples */ /* into it. */ /*******************************************/ +#if !defined(__RtWvOut_h) +#define __RtWvOut_h + #include "Object.h" #include "WvOut.h" -#include "RTSoundIO.h" +#include "RtAudio.h" -#if !defined(__RTWvOut_h) -#define __RTWvOut_h - -class RTWvOut : public WvOut +class RtWvOut : public WvOut { protected: - RTSoundIO *soundIO; - // Add an extra 10 samples to data[] just to be safe - short data[RT_BUFFER_SIZE+10]; - long counter; - int channels; + RtAudio *sound_dev; public: - RTWvOut(MY_FLOAT srate, int chans); - ~RTWvOut(); + RtWvOut(int chans = 1, int device = -1); + ~RtWvOut(); void tick(MY_FLOAT sample); void mtick(MY_MULTI samples); + +#if (defined(__OS_Win_) ) + void stopPlay(); + void startPlay(); + void stopRecord(); + void startRecord(); +#endif }; -#endif // defined(__RTWvOut_h) +#endif // defined(__RtWvOut_h) diff --git a/STK/SKINI11.h b/include/SKINI11.h similarity index 100% rename from STK/SKINI11.h rename to include/SKINI11.h diff --git a/STK/SKINI11.msg b/include/SKINI11.msg similarity index 96% rename from STK/SKINI11.msg rename to include/SKINI11.msg index 0b4602e..1869510 100644 --- a/STK/SKINI11.msg +++ b/include/SKINI11.msg @@ -90,8 +90,9 @@ #define __SK_FilterSweepRate_ __SK_FootControl_ #define __SK_ShakerInst_ 1071 -#define __SK_ShakerDamping_ __SK_Breath_ -#define __SK_ShakerNumBeans_ __SK_FootControl_ +#define __SK_ShakerEnergy_ __SK_Breath_ +#define __SK_ShakerDamping_ __SK_ModFrequency_ +#define __SK_ShakerNumObjects_ __SK_FootControl_ #define __SK_Strumming_ 1090 #define __SK_NotStrumming_ 1091 diff --git a/STK/SamplFlt.h b/include/SamplFlt.h similarity index 100% rename from STK/SamplFlt.h rename to include/SamplFlt.h diff --git a/STK/Sampler.h b/include/Sampler.h similarity index 100% rename from STK/Sampler.h rename to include/Sampler.h diff --git a/STK/Shakers.h b/include/Shakers.h similarity index 100% rename from STK/Shakers.h rename to include/Shakers.h diff --git a/STK/Simple.h b/include/Simple.h similarity index 100% rename from STK/Simple.h rename to include/Simple.h diff --git a/STK/SingWave.h b/include/SingWave.h similarity index 98% rename from STK/SingWave.h rename to include/SingWave.h index 7fc3329..61a7a7c 100644 --- a/STK/SingWave.h +++ b/include/SingWave.h @@ -16,6 +16,7 @@ #include "Object.h" #include "Modulatr.h" #include "Envelope.h" +#include "StkError.h" class SingWave : public Object { diff --git a/STK/SndWvIn.h b/include/SndWvIn.h similarity index 78% rename from STK/SndWvIn.h rename to include/SndWvIn.h index 5884e2e..9944093 100644 --- a/STK/SndWvIn.h +++ b/include/SndWvIn.h @@ -1,6 +1,6 @@ /*******************************************/ /* SndWvIn Input Class, */ -/* by Gary P. Scavone, 1999 */ +/* by Gary P. Scavone, 2000 */ /* */ /* This object inherits from WvIn and is */ /* used to open NeXT/Sun .snd 16-bit data */ @@ -17,9 +17,11 @@ class SndWvIn : public WvIn { - public: - SndWvIn(char *fileName, char *mode); - ~SndWvIn(); +public: + SndWvIn(char *fileName, const char *mode); + ~SndWvIn(); +protected: + void getData(long index); }; #endif diff --git a/include/SndWvOut.h b/include/SndWvOut.h new file mode 100644 index 0000000..7e5c143 --- /dev/null +++ b/include/SndWvOut.h @@ -0,0 +1,29 @@ +/***********************************************/ +/* + NeXT (.snd) and Sun (.au) Soundfile Output Class + by Perry R. Cook, 1996 + Revised by Gary P. Scavone, 1999-2000 + + This one opens a NeXT .snd file, and + even knows how to byte-swap! +*/ +/***********************************************/ + +#if !defined(__SndWvOut_h) +#define __SndWvOut_h + +#include "Object.h" +#include "WvOut.h" + +class SndWvOut : public WvOut +{ + protected: + FILE *fd; + public: + SndWvOut(char *fileName, int chans = 1); + ~SndWvOut(); + void tick(MY_FLOAT sample); + void mtick(MY_MULTI samples); +}; + +#endif // defined(__SndWvOut_h) diff --git a/include/StkError.h b/include/StkError.h new file mode 100644 index 0000000..86d367a --- /dev/null +++ b/include/StkError.h @@ -0,0 +1,46 @@ +/*************************************************/ +/* + STK Error Handling Class + by Gary P. Scavone, 2000. + + This is a fairly abstract exception handling + class. There could be sub-classes to take + care of more specific error conditions ... or not. +*/ +/*************************************************/ + +#if !defined(__StkError_h) +#define __StkError_h + +#include "Object.h" + +class StkError : public Object +{ +public: + enum TYPE { UNSPECIFIED, + FUNCTION_SYNTAX, + FILE_NOT_FOUND, + FILE_ERROR, + PROCESS_THREAD, + PROCESS_SOCKET, + PROCESS_SOCKET_IPADDR, + SOUNDCARD_NOT_FOUND, + SOUNDCARD_CAPS, + SOUNDCARD_CONTROL, + MIDICARD_NOT_FOUND, + MIDICARD_CAPS, + MIDICARD_CONTROL + }; + +protected: + char errormsg[256]; + TYPE type; + +public: + StkError(const char *p, TYPE tipe = StkError::UNSPECIFIED); + virtual ~StkError(void); + virtual void printMessage(void); + virtual const TYPE& getType(void) { return type; } +}; + +#endif diff --git a/include/StrmWvIn.h b/include/StrmWvIn.h new file mode 100644 index 0000000..f8058ed --- /dev/null +++ b/include/StrmWvIn.h @@ -0,0 +1,40 @@ +/******************************************/ +/* + StrmWvIn Audio Input Class, + by Gary P. Scavone, 2000 + + This object inherits from WvIn and is used + to accept 16-bit data (signed integer) via + a socket connection (streamed audio). + Streamed data must be in big-endian format, + which conforms to network byte ordering. + + This class starts a socket server, which + waits for a remote connection. Actual data + reading and buffering takes place in a thread. +*/ +/******************************************/ + +#if !defined(__StrmWvIn_h) +#define __StrmWvIn_h + +#include "Object.h" +#include "WvIn.h" + +class StrmWvIn : public WvIn +{ +protected: + INT16 *strmdata; + INT16 *lastSamples; + void getData(long index); +public: + StrmWvIn(int chans = 1, MY_FLOAT srate = SRATE); + ~StrmWvIn(); + void setRate(MY_FLOAT aRate); + void addTime(MY_FLOAT aTime); + void setLooping(int aLoopStatus); + long getSize(); + int informTick(); +}; + +#endif diff --git a/include/StrmWvOut.h b/include/StrmWvOut.h new file mode 100644 index 0000000..56cb8ec --- /dev/null +++ b/include/StrmWvOut.h @@ -0,0 +1,36 @@ +/******************************************/ +/* + StrmWvOut Audio Output Class, + by Gary P. Scavone, 2000 + + This object inherits from WvOut and is used + to send 16-bit data (signed integer) via + a socket connection (streamed audio). + Streamed data must be in big-endian format, + which conforms to network byte ordering. + + This class connects to a socket server, the + port and IP address of which must be specified + as constructor arguments. Actual data writing + and buffering takes place in a thread. +*/ +/******************************************/ + +#if !defined(__StrmWvOut_h) +#define __StrmWvOut_h + +#include "Object.h" +#include "WvOut.h" + +class StrmWvOut : public WvOut +{ + protected: + int local_socket; + public: + StrmWvOut(int port, const char *hostname = "localhost", int chans = 1); + ~StrmWvOut(); + void tick(MY_FLOAT sample); + void mtick(MY_MULTI samples); +}; + +#endif // defined(__StrmWvOut_h) diff --git a/STK/SubNoise.h b/include/SubNoise.h similarity index 100% rename from STK/SubNoise.h rename to include/SubNoise.h diff --git a/STK/TablLook.h b/include/TablLook.h similarity index 97% rename from STK/TablLook.h rename to include/TablLook.h index d01891f..efa9e21 100644 --- a/STK/TablLook.h +++ b/include/TablLook.h @@ -10,6 +10,7 @@ /********************************************/ #include "Object.h" +#include "StkError.h" #if !defined(__TablLook_h) #define __TablLook_h diff --git a/STK/TubeBell.h b/include/TubeBell.h similarity index 100% rename from STK/TubeBell.h rename to include/TubeBell.h diff --git a/STK/TwoPole.h b/include/TwoPole.h similarity index 100% rename from STK/TwoPole.h rename to include/TwoPole.h diff --git a/STK/TwoZero.h b/include/TwoZero.h similarity index 100% rename from STK/TwoZero.h rename to include/TwoZero.h diff --git a/STK/VoicForm.h b/include/VoicForm.h similarity index 100% rename from STK/VoicForm.h rename to include/VoicForm.h diff --git a/STK/VoicMang.h b/include/VoicMang.h similarity index 100% rename from STK/VoicMang.h rename to include/VoicMang.h diff --git a/STK/WavWvIn.h b/include/WavWvIn.h similarity index 79% rename from STK/WavWvIn.h rename to include/WavWvIn.h index 0ad3078..5bd8fde 100644 --- a/STK/WavWvIn.h +++ b/include/WavWvIn.h @@ -1,6 +1,6 @@ /*******************************************/ /* WavWvIn Input Class, */ -/* by Gary P. Scavone, 1999 */ +/* by Gary P. Scavone, 2000 */ /* */ /* This object inherits from WvIn and is */ /* used to open DOS/Windows .wav 16-bit */ @@ -18,9 +18,11 @@ class WavWvIn : public WvIn { - public: - WavWvIn(char *fileName, char *mode); - ~WavWvIn(); +public: + WavWvIn(char *fileName, const char *mode); + ~WavWvIn(); +protected: + void getData(long index); }; #endif diff --git a/STK/WavWvOut.h b/include/WavWvOut.h similarity index 75% rename from STK/WavWvOut.h rename to include/WavWvOut.h index 4fb2473..0fe70dc 100644 --- a/STK/WavWvOut.h +++ b/include/WavWvOut.h @@ -8,28 +8,19 @@ /* poke buffers of samples into it. */ /*******************************************/ -#include "Object.h" -#include "WvOut.h" - #if !defined(__WavWvOut_h) #define __WavWvOut_h -#define WAV_BUFFER_SIZE 1024 +#include "Object.h" +#include "WvOut.h" class WavWvOut : public WvOut { protected: FILE *fd; - INT16 data[WAV_BUFFER_SIZE]; - long counter; - long totalCount; - int channels; public: - WavWvOut(char *fileName); - WavWvOut(int chans, char *fileName); + WavWvOut(char *fileName, int chans = 1); ~WavWvOut(); - long getCounter(); - MY_FLOAT getTime(); void tick(MY_FLOAT sample); void mtick(MY_MULTI samples); }; diff --git a/STK/Wurley.h b/include/Wurley.h similarity index 100% rename from STK/Wurley.h rename to include/Wurley.h diff --git a/include/WvIn.h b/include/WvIn.h new file mode 100644 index 0000000..70a2144 --- /dev/null +++ b/include/WvIn.h @@ -0,0 +1,81 @@ +/********************************************/ +/* + Audio Data Input Base Class + by Gary P. Scavone, 1999-2000 + + This class can handle multi-channel + input. Multi-channel input is + interleaved in the vector "data". + Actual data input occurs in the + subclasses of WvIn. + + Currently, STK is only supporting a few data + types (16-bit integer .snd, .wav, .raw, and + .aif files and 64-bit double MAT-files). In + order to support more formats AND to make the + writing of subclasses easier, a format ENUM + could be defined and a generalized getData() + function written within this WvIn class. Then, + most subclasses of WvIn would only have to + setup the appropriate parameters and all + other processing would happen here. +*/ +/********************************************/ + +#if !defined(__WvIn_h) +#define __WvIn_h + +/* "Oneshot" files larger than MAX_FILE_LOAD_SIZE will be + copied into memory in RT_BUFFER_SIZE chunks, rather than + completely loaded into a buffer at instantiation. +*/ +#define MAX_FILE_LOAD_SIZE 5000000 + +// Buffer size, in sample frames, when incrementally loading from disk +#define LOAD_BUFFER_SIZE 1024 + +#include "Object.h" +#include "StkError.h" + +class WvIn : public Object +{ +protected: + long fileSize; + long bufferSize; + long readPointer; + long dataOffset; + int channels; + int looping; + int finished; + int chunking; + int interpolate; + MY_FLOAT *data; + MY_FLOAT time; + MY_FLOAT rate; + MY_FLOAT phaseOffset; + MY_FLOAT *lastOutput; + FILE *fd; + virtual void getData(long index); +public: + WvIn(); + virtual ~WvIn(); + void reset(); + void normalize(); + void normalize(MY_FLOAT newPeak); + virtual void setRate(MY_FLOAT aRate); + void setFreq(MY_FLOAT aFreq); + virtual void addTime(MY_FLOAT aTime); + void addPhase(MY_FLOAT anAngle); + void addPhaseOffset(MY_FLOAT anAngle); + void setInterpolate(int anInterpStatus); + virtual void setLooping(int aLoopStatus); + long getSize(); + int isFinished(); + virtual int informTick(); + MY_FLOAT tick(); + MY_MULTI mtick(); + MY_FLOAT lastOut(); + MY_MULTI mlastOut(); +}; + +#endif // defined(__WvIn_h) diff --git a/include/WvOut.h b/include/WvOut.h new file mode 100644 index 0000000..b3077e8 --- /dev/null +++ b/include/WvOut.h @@ -0,0 +1,43 @@ +/********************************************/ +/* WvOut Abstract Class, */ +/* by Tim Stilson, 1996 */ +/* revised by Gary P. Scavone, 1999-2000 */ +/* */ +/* This class can handle multi-channel */ +/* data via the mtick() method. */ +/* */ +/* Currently, WvOut and its subclasses are */ +/* non-interpolating. Thus, the output */ +/* rate is always SRATE (defined in */ +/* Object.h). A future upgrade could add */ +/* interpolation functionality to allow */ +/* output rates different than the STK */ +/* internal processing rate (SRATE). */ +/********************************************/ + +#if !defined(__WvOut_h) +#define __WvOut_h + +#include "Object.h" +#include "StkError.h" + +#define FILE_BUFFER_SIZE 1024 + +class WvOut : public Object +{ + protected: + INT16 *data; + long data_length; + long counter; + long totalCount; + int channels; + public: + WvOut(); + virtual ~WvOut(); + long getCounter(); + MY_FLOAT getTime(); + virtual void tick(MY_FLOAT sample) = 0; + virtual void mtick(MY_MULTI samples) = 0; +}; + +#endif // defined(__WvOut_h) diff --git a/STK/mandplyr.h b/include/mandplyr.h similarity index 100% rename from STK/mandplyr.h rename to include/mandplyr.h diff --git a/ragamatic/miditabl.h b/include/miditabl.h similarity index 97% rename from ragamatic/miditabl.h rename to include/miditabl.h index 8938646..8240175 100644 --- a/ragamatic/miditabl.h +++ b/include/miditabl.h @@ -1,4 +1,4 @@ -#include "../STK/Object.h" +#include "Object.h" double __MIDI_To_Pitch[128] = { 8.18,8.66,9.18,9.72,10.30,10.91,11.56,12.25, diff --git a/STK/phontabl.h b/include/phontabl.h similarity index 100% rename from STK/phontabl.h rename to include/phontabl.h diff --git a/mus151/Debug/.placeholder b/mus151/Debug/.placeholder deleted file mode 100644 index e69de29..0000000 diff --git a/mus151/GUITwoOsc b/mus151/GUITwoOsc deleted file mode 100755 index 516b651..0000000 --- a/mus151/GUITwoOsc +++ /dev/null @@ -1 +0,0 @@ -wish < tcl/TwoWaves.tcl | MUS151 TwoOsc -ip \ No newline at end of file diff --git a/mus151/MUS151.cpp b/mus151/MUS151.cpp deleted file mode 100644 index ee207fa..0000000 --- a/mus151/MUS151.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/******** Psychoacoustic Interface Program for MUS151 ************/ -/******** Center for Computer Research in Music & Acoustics ******/ -/******** Stanford University, by Gary P. Scavone, 1998 **********/ - -#include "../STK/WvOut.h" -#include "../STK/RTWvOut.h" -#include "../STK/SKINI11.h" -#include "../STK/SKINI11.msg" -#include "TwoOsc.h" -#include "miditabl.h" - -int numStrings = 0; -int notDone = 1; -char **inputString; - -// The input command pipe and socket threads are defined in threads.cpp. -#include "threads.h" - -/* Error function in case of incorrect command-line argument specifications */ -void usage(char *func) { - printf("\nuseage: %s Instr flag\n",func); - printf(" where Instr = TwoOsc (only one available for now)\n"); - printf(" and flag = -ip for realtime SKINI input by pipe\n"); - printf(" (won't work under Win95/98),\n"); - printf(" or flag = -is for realtime SKINI input by socket.\n"); - exit(0); -} - -int main(int argc,char *argv[]) -{ - long i, j, synlength, useSocket = 0; - int type; - int outOne = 0; - MY_FLOAT settleTime = 0.5; /* in seconds */ - MY_FLOAT temp, byte3, lastPitch; - - if (argc == 3) { - if (strcmp(argv[1],"TwoOsc")) usage(argv[0]); - if (!strcmp(argv[2],"-is")) useSocket = 1; - else if (strcmp(argv[2],"-ip")) usage(argv[0]); - } else usage(argv[0]); - - TwoOsc *instrument = new TwoOsc; - WvOut *output = new RTWvOut(SRATE,1); - SKINI11 *score = new SKINI11(); - - // Start the input thread. - if (useSocket) - startSocketThread(); - else - startPipeThread(); - instrument->noteOn(200.0,0.1); - - // The runtime loop begins here: - notDone = 1; - synlength = RT_BUFFER_SIZE; - while(notDone || numStrings) { - if (numStrings > 1) synlength = (long) RT_BUFFER_SIZE / numStrings; - else synlength = RT_BUFFER_SIZE; - for ( i=0; itick(instrument->tick()); - } - if (numStrings) { - score->parseThis(inputString[outOne]); - type = score->getType(); - if (type > 0) { - switch(type) { - - case __SK_NoteOn_: - // check to see if velocity is zero ... really a NoteOff - if (( byte3 = score->getByteThree() ) == 0) - instrument->noteOff(0.0); - else { // really a NoteOn - j = (int) score->getByteTwo(); - lastPitch = __MIDI_To_Pitch[j]; - instrument->noteOn(lastPitch,byte3*NORM_7); - } - break; - - case __SK_NoteOff_: - instrument->noteOff(NORM_7*score->getByteThree()); - break; - - case __SK_ControlChange_: - instrument->controlChange((int)score->getByteTwo(), - score->getByteThree()); - break; - - case __SK_AfterTouch_: - instrument->controlChange(128,score->getByteTwo()); - break; - - case __SK_PitchBend_: - temp = score->getByteTwo(); - j = (int) temp; - temp -= j; // floating-point remainder - lastPitch = __MIDI_To_Pitch[j] * pow(2.0,temp / 12.0) ; - instrument->setFreq(1, lastPitch); /* change osc1 pitch for now */ - break; - } - } - outOne += 1; - if (outOne == MAX_IN_STRINGS) outOne = 0; - numStrings--; - } - } - - for (i=0;itick(instrument->tick()); - } - - delete output; - delete score; - delete instrument; - - printf("MUS151 finished.\n"); - return 0; -} diff --git a/mus151/MUS151.ncb b/mus151/MUS151.ncb deleted file mode 100644 index f753034bf4c03d60c178af10156978a893362fdf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 107520 zcmeHweRy2edFMN0*&f-lJ+l0TWs56egDh;zUl=nObB!g%!nSNA8DlU}M$*U{7|p0N zBP(_S5o`)>*li&tTavb$&<#%r$tI-vSe}+_vxPQkpxyLI{~&F?mZ!T9={Chl*pd_$ z_V+sTj6C-1}tygS4(L0_woEz9Y?0jJYDQ#rw)(hr^&xPeJYX4j3%aucDVnx#6W)998I*!uiPCUKbXmkPMesGH*IRi z;-?ZbNlnF@Cbiz4%vgG`^YHZPc`>I;QGbT%K2~?{Og>l7fzGbZtFwK`?nEj91zi5BSQ@1*(LZ)lM>v(p z=8~DTs+{$x%R6vUsn49Be&PPtU&RgJZg{MK`*~aoaNUKg8rSov{AlA9K*g72AP3gK zRc$xi9e8dT+<(IbZ9(!ygg3xV<2m#lp0sqBtzm01l zuKBp;;`#-`FM@jl?sB-_g1ZXtWw;op2Ui4F2h!s^F|B#HJ`8*<+#1BMgBw7=fq(;V zj0680b#v)9aptQUC!+fEN5!dDk|JbffOEARKn7K&e=g1z*$#Z3?w_N|UoM-0SDXI0 zIO}Bt@EYA8NBG5Z3GgMRKQ7J{aux8X?vEc9XO*hawW=@d?^pA_v_Eb8&(=TaOM{gG z1RQt+9N2<3bm@RN^Hj?!axHPEAP>5T=fzo|dJH0$5RZ#9SGC}1e~F`hS5Y}AK*f}E;jP(Q17Y0pg?EndLUBR}&lzF_K0uOod{$t3C?)Q!R zr^XF~Mm}fb(hX!Km=M4P=YXx>w!c20>L>fJ>=A?{Yw$YNKM#B5`GOM?Bp7fY;J`1P z1E#%qqL}XsBlkZ=edqXkG1^k%zfTSXkzaFDqkqsK>P+#F{e6U%!_Y7Z- zaLNa^_r$e)(EI7?Jo%u<>zqN<^1;REyb1A*d=OV0{OTYdI*=a6>)g**2l=4n#rO4m zLLJ7_zhlBVey@W}+G=p_AFM+kM9U8s`xVvzU*zGOZ>YnYoiXt_zORGidbh#3->?oj zYkA|U`HVWenUXi4kMj?tNy{5OpHYWCl9o4m{-6$Nrc8Rv5mpBpwfu20`>-1LMWW{q z*mvUG0rnKCei8dtoGaiQ0sBRqUqFBAIQmeBmtwym=N7mp5q+f)=NQP@>S<+JFKDrI z277UDWf^6g^|yYd@-2{YEb;F=Q1v-fSkL=2lpD71^HqN!B+Ib@CyMpIdbQ&xELRdo z`@LS8!K^v*6BA$056qS44X)=8=1CRfqy1i~cKSqQ197D9sQm!d@+}iz?=D{8%`dP# zvaI^s<)AHo=atXkjo(@hnDKv_=8|8Dr=Xv3OCEJjHwZ>l(=kCxKf!D|n z&GQ{{J>oCX_*rqjqI$$j3*n(Nh`(IpbH(}F(2szxl5g^P#NQEW1AdXlLEo1{{{#4H z4|k;v>DOx<{Cix!1bmH>MV~_&U&Y1w&Y9f*E8>R1C&r)2J>%I6w*dqkm@x-b``;^3 z9^BzWA40j~e84)1p~Wq<|0^-pC4QT!&m3P9zr)~;I12AIILE&Xf49Lop7!G$uM^kx z+m$QvTa5aB2nQ25AFx%n0k4uT;Q3ldnp?2nZZX>S2Z?Vo!d!n4P=|_!7C@ zgm1(C=f&vLDEaV`E4%Pp49XxB&<8Pl0Tyvwk1_u)u8m;K---T77GwDc$M;-6VZVjz zBuk5ALqGCheSQqI{Uz?VnyU)#58y}KFB{%(a6A$~z=8APzzZllY@bTX_A`+JFd~3}18*}9bfP}9y>FDu(R!NwzpBdX zGk9wJkM%*y2ZpQh0`}*#{U&}bo?q&4ez0EQT7I~g9c%`U^Fs({dwnTR^>MU5V(|5H zDeyURgTdEf{b4@jiIz7mTK5*<^R&E4x>$YO0GuguKOWmnq!z>2e?IpUa4ta4k8|Gp zeMqw(S0I<(W`!{z_m|Fr|BiaX_Mh{2gmVVx{#?Re184hRkN!UU0~TMV#_My$#erXj zuMIiq1ysq625$Jp8@w*G0{A@HVDMET*3S9zA`TSu`RY&&@QBPY;fq7Hz^ml} z;u!C547CDZAQ=;WS*Qj0LixUVzA7{yc#ZrO@%iGM!^#=Y=X}M4-y{D5`j^N*o9Ero zL4@Nx4sne4w}+@nq)xui_l11BSQ-(3nXJI`2*CNFtAVeO*APy;1>*_M4>XwYYt(** z)$)0yhb;rn*3foDtCyW7{CfES;ybFp#6A=EByf#`^2)mQ{ywC^i@3cmLpt=U#-NGr z^SGGKT=*}<<#!qPt0tWHdvTq?^>JJQ1RU^lz|Q|$zbz zF2cn%6RxGK!Lr$Tao-&LVamGD^_uh|-I4>*1tgN#x;|6fyIM9vGKgx`=3}t{NXS2bz=8Y=Z zWAFv4e=tu@0Pn}e@30dt+nxPz0|+<}aNzC70agFgtodOO@6~_vBBuV2Q%1053F`mb z?+XVM2OKER0Xu(Z^?#`IKIjiveL(uWKhFnX;0qb>wK?c7U(55rb-?X;f9?lnCm>i4 zD9`C2B;dg8eyb{3$J6qp!*V^xK@zz{Zp9|JBN9Bk;?$?TrS zMSa59@(#eRf=VzAU2dgkXBhU~wVJMu-M9Lf3(;|?=q-ongu@pw`TX?Rk6l6JyP%1BAGv#g zIu#A*ceL0{+$t3*5+Z~n5uPb^$f9uQyk72{p=&>AqJBG&2RMIn)MNb9ba`m;jro?v zo>O9$Uw4Bh>fz#USG_K$qQ40Or^*g=IaQ5Qg_Qa|f0?O|po#i9^h}}m9ZREMAbc-A zuFKDhrN@v|;kFd+Z(pzE#4DhQdP2DCg*rFhFjV}GUaFJns;Uh|CR}I2M0x4d^@^_l z44QZzTFWmSthjJs1TH>cG(4kk$gH1SroZEU&_uepvxhT11Xul6`kPtt(-raj==yU* zS3e%+`B2V0YYQ}$=&2ayRt)9wHk7BR-tt;D>dg=AQ{QnHXyQ3D?xx}yFM_N7EB(!k zUnMCxqziC=emx7CxL;lu+nE*K;*{Pz)s5P+f+WNY=~1f#En)>G@FizrRx#U#Qk(D)l=o4Et}|h1^m|ipI{cw2P2JD zjS+OCbk*>sq3N0{D3fXfZlMm7gI1q4P7IWaW z7hijkGT<3@3(8m^E%DY?N2jy;+q8Let7qzT80tTPdnRq0L|X?IZ86tiu~@>G;}!d4 zix-s14TyQZ#ks}V=G^K9rQ*3fO#P0I<>k=vzK(;3_d>gnvOXM(#YaYSo^Q!>hK6K1 z??u1U_}RyEiF`*k@f&g~lN=O8bU;RWY^0Fl5JJZi>4DQ;5_n|q$Y>!3DDcA4nSA1K zx)8>vivx#-JUpKqxZOhrGU*Cw$XJueGp2c@OwD+dI&aS?m-tNw>cl9{8 z!mG0jSl_|+E)QXmT_TDD0(4q*v$q|19g%(Fp zX3TwQ^lFcyNH?n5Q^-f-g(!-t1(bG{vm?E%p#@JPhbDbXpY?Ek8;cpaXVE(iURoiw zH@?yCTz)W_(bXeAm`e7WTUIA^I}*`ggb2vFdUZhR}fKhBMi`)8h1x4Jq*qH^=g;+Nfm4wn{?- zY1=-b?aF1w(t`u>tRk=cTcP5{$85z#D>9fFS1n3YGChzQ8%(qgs)X3G?ml#==X5Tg z7%6&T|C^|k`bI&m>^-O)-wWx$p+WxxBYmT7$!uaE-$QEU;E}e@?)H7XJ%^8WwUx%} zG2AGMbluU8j&^8bv^>>>Up5xl=!I9KKWytw4|vt(L&TCpDPJn*6;N9gSymiQeI4uJEd)`4D<> zarBwJcqbG2UUWT+Jn&+a97TR@i4+95|FP>%ql}Gbrt<5=AYxKf^gfHTQ3=quG zWlTlmh=UcaT!9<5X;>H1;dBRj4ARkgu-!-ei2eY@JjaN@_bP_?okgU>v-q2!BR=Syg@yL+yXg%Qfn7ZJxBC0MXP^HkV`c}AAhpGvwcGtoW_4AV_YMnrpi-cqeKa{FfyvybAr`c7SBKb1zsd9)*K2!@twHh=zPM~QgngK5bnj0l> z`JL)rXkwMezUG;@G=Xm6KHTtll^>|Wm1a*Y(1bh9w9~Y#1^WoiwfKSR=D9V9K-EeX zXl9PUV_Yx5rCGUBco=DM>69jD{6I733y~qWIS?MhJ=NCwfof;`K$RnG=qs=!Slj9V(c1DDIpT+XFwjZ&bx89z{6o&~Brq1rmCiYCy!`@?Xb zMtMFbuwM>?UD0bi@zJLB%QxEaKGHMW7%ePW@s8HXg*S zJpxu};Ar5U2=QHwogoafCsd_=2PswM1!(ITMM_Gjaz8%1;Jp8b- zPcT>GI8RLbV%#}P0gqR3z93h^sTMYV#CIBdg%)28ePKMGZ1G^|E2n2h&lTx2{r+jG zv+*j^R@9xZM4T6~a(Xj+Q?HxOPP@ug&#t$YEVFedQVC9RR*0fk;#7oFiEJ*JNpq48 zd&oqUc6@G`^V2Wf|N5)A0o)A_?yY1^p{%?Mm#we1zP|uJRB5N$od4J70%))E079yS zjV8mlK>r-;3p=XBwY|-1VP~28GuK1E9d{hDBgXKHmA$Ves(~VYg|hbyEV4GO6LllA~<^+L-JH%xmWi?B12gXh|q zG*hR*BFK-&i6cJs3oOEJVJ%*r;`3BrC;rZv_?uY*i#{D_m_W+OlOsBUB?q=Z4#@z)MuPOWC?t%=d!#ISthB!XB z0yYOON57u7fodTuXw#SDf{P$~sNa`5iK(}kx{9fvmo^M8gPns7O1BXb4Itpa+l&LM z{ePAE{Gj_8v~v=V?K|yr66a(R@fy_*V*F`vw!IAJWGKU_KaBYMfM7la6QU`F-(~QO zWE7q?cv6xI=fp1h{}GP=!xB=92EZ4vKf$w)N?$cbBX%r{qyq>z5OClEalqR5wexkR zKBE5foTFDC9c|w`9Mr=L#P=YXfCICE19tpxY2hNrk`(oSu2kn3m3+W_9&K@>saA_d z(Z6@mZ>|F#l0QLv&ha(d>$#Y3=K@PK=7!mx(`Gmq$D+O39yqlNh7uTW!!z6tEfq10 zwYL^@27euCah&`to(bmh>=y~#fCFzG2e?TC^M7dHFJ(VmtUTZvC~@0As6~H(xQoFv z=g&Al7e)Qo`hi`HhSveN`hi`HlpBCs{lG59&TD~N{lMB@P!#fki~O~xq?x1aDC7e- zC@_863yw-e>k9_nh+h=*aNL~2a0kCA#w1!_u!|9S6Y#~t4F#M}vn8y|Kte!m15LQFVE`Uutfh0S~+b=8D2)WL!`JBIO1p0;y1?xD>b+QFfw9nKfh z#tyX|aGsF!g&aG+^_@`9aI9x@yic&}@m60rCi*3c%D7CfN9Y`BCw?{8`@4Yaww;?Su7ZD1hRMMI z0uIa`4xB-~Wc$Aq?cW@bb+^W0LR0H~QSCqKH|GNx{u>Bi+QRVxTX!_9z}X(Nzdr{* zRsUP`dLT85({7MnPn)aie;^CMv;YDQ%n}Z812EfruAdVgVf_Zq{x^Y}>WP0w?WZ&A z0jU4%&lBwW!23e)LyxwAKPrzB^}^fdv{PKDP0LL0)ADJeYO^Kr&&p>N&dtHZACt!l z_?S2xPY}4-9ODq@j!<8i{R@jX%2|X)Jp6OA1N78*c;}oCApfX3$iU}!hdL2n=i$FA zzlY~nc=#XA`7+{Pt*@h|i6yXO2p(recEhq2!<6vOiyGgK zU*i9SKh{^u3*xUBoa1rgJSf3%&JXx;j^~N%`s<mjTaL~{LNU$uS5O+OM~x}D}h(b_Y8g|>3w)t;GyJeLbN#;#^5Q`g{|fBC<&LCbgL8L49p)FVA`W}R+%ZrGPH~fZ?T@8- zw_F3<$`@Cz!;f>MT3)!a55GFd7api!{#VOx;49_-n)G)`4EQP|4_w)cA9a~R2%!JO zxdpoqiS~IhACa)OcrhQ*fw_qk?Dy`&Jj4*!acTP(a}eX0uec6&ev@2VT`@^^@K6)$ zEDss*;-LV0@xZ}nK-&j!@qiQ$h?SEUJnX^e7#_geivv6~!TM?U_wzs!+sDNyLmUCL zVp~4(&8Sb*Y{PTn zjrN@f_1NBWzMU(IJZQ#n?zO8%`>y4Ui{8c>;1PA$v9?8;xf_pbkXrt@YW;yWN#`ng z10Di4G zz(bL2|CjO~z=M>;*}o_7Ksej?dNtk;dH6EaZ}tydEDJDvZOB25sZxhDi8qDT1D~r7 z&l0Z-tpGkxDH|ZZD#RK#UmeybULC3d9uXdpCcZdS3%pt#KqbC0)CzooIz&qRvQP`~ zg~9{2#H&K{f!C-**~HJmCv@jx{3d*ok0?-F&$p12!2h;W?8Gx==~@gzZ=I;hI< zi&cMSnL6N%0GuDZ8qcp#ht!F;VAn8@jq>m{@oUuiz|~4AKo!ROTSMF7U9S$~GyHn_ z0OC8Ue?*zXdC;feQubKa-cwlvFXHy%;c)u#kS|>-9$-2=%*uoQewT51(3au6=izT2 zn4XCe20RkLJBR~0ysLlwPo*A99G-{00;RXm{&RkxxRwVlX0k2?Zsmbq&##9(;9-8Y z=iDV<4|%}D=ES*Uz8>;`iUf#rAALRK0TnS2=brj{$O9g>uDwN?x!1lP@<1v0Ksa~a z*Fzp?dE;XAzZv)fBX3-c{MXylEHJ^Y)1*BE)@VuyY!@I^-6xY*}^Iq=0=-u&3b zXl5gDoZm&g;d;h4{J6t`ht`R2#jhTeYI);gCawkeQlZj-+K4psd_X{51n#r4&c-d7dw*hm56C5XRquA5(aS zIOyGuA7wHR)-(Jv{AfEMG|2e^?w#fw0LT5@o521M`$F8Sz&#A?6JcHe-$(CdSOXXH z2k4X0f{Nb1fH{T(m|NJ&J`?wLv;So09O`kux}q$j?4ew#WPT0bDo^sP+CZDx-n_h5kC*D+lG1C5g&xh_6ud?^W`*CcH+?56qLV z8k}W}?e{t0FXN)J3@Xgwd4PWa&T{}?hZ{h^fq(+^oZcS2zZ$HR;H zkDkEq8vF*OuV#+?k-=}2;|QNCziIG;au_%|ax3-o8OZ{V$S#Bb2YCi~wL}e`mvP_= zq|@MkEzbd8D8~%`_wqg9HL}s*_sV_17s+vx-zKc5aU^5$%g{e(&WB8RgPPB%m2rc& ztNn^~@?Q;pi@Y20m&*?f{vH_tzEY9~--Go#?gwZz`Ja~G1io7Kn((FQ|8u1M@5-FUF%HMY{I7%izx4`_fq_z>z(t;21D%aC3~ zzCj%0U9Jx_KpuRG_^@6NXyBLvxE(JyKptrM;f6WBZ-6}big}*v3Dj7k<%u4jH(=bV zWyv`E}cMwl&{UZ&aQIy==p*Myn~iE zt~mHLKz>-9`x_cS(~p=Q);l=Joj)hF3uI$`324$a4rFJ3LTtJ;2gthT$m#`&Upu( zm!M@s&MVltgrybb;nKJ0th%T z%Q!%VvZ$$O?{Ncg(Z6JUr#=wY_eM+uMB4=_<>SEZ`9ALdxeT~H-^cyHjlj+MKIr2d zkRjl6&3QiVC)@&jzB$iFeS+5luQuoT#M!3w0WLJ>`NY{P9SC2f&+8o*XTRJ6e6c>C zhx5o6p?zV0pYp}Z7|Izd_bZ*Pdne0#uq%Lo10DxBCBG7Dc^ofW-B+!ss|B4{+)29& zwUaw?0|+<}aNyU813~@&b^4mYy969KKMtVFjMdsI%1_TI z^t)>{T{J32J0Y9_rHzg^1Fm|QEDcRy8{Y&t8geDf%@kZNoiKbyjtX~`Tk==qXu4>; zi1V@B-DmBw6r$o#)>{tI35PFW^7-krAG?AG4Ykq87k3X*r;-8vjuxAVTcsjJLWFQ6 zLLC$iSriVP*UOzVbkRr_jnsiW!1;%R`HA%(pD|oD#GAqOmXP;hhiW>3uaS z`kNqds_a0QQ`Iy@0K z@huug<0=);%)Vi$_#M4eC(~6`8;VT0&V-5b(y8keT{ON%qi|Y&aew3m10!(p0i)p= zeM9E_C;e}E_YheW>)-kMLa*c{@l>jkB4b|iz`XgweTjut^BOBPEekr zT%xJ~H$SjXeMcHiye2x9;z^?*9a{a6TAmtZIy)8>Op;FGEe&TxG>_KLTyu3RaGR~IBmr9k1&C~Y({=P zGZRwIKZiH>1U|+;&QiKw0bR7mIMuiVtPQvy`sTG*czNyh`ZH3H7mlmeRF-meO@# zmeLiUrF5O1rF8wyET!wwSxVQRfv(v!?`!)x-veE=f63j_dY=3fjgh_UCL9{j`{h8< z7qfJ=PBV}3%OR~K7qFy#meO?`bn!g$0(4&W{OUvr@ulegiI!5YH;rQ=!oW7ukG>Z) z&8GQiOV=NPF7Er*8U#2GFkwmexf7SZ#kIh-nOVA?15LAOU15v)jz0rk)Pt>OOeW0( zOqvH$?=@lH?gF|K%T(quL)S6T#PdB|AEIvVsbOMj?+fZ1tr|vpmacn26ZPD3M=y2U z&HyGR$Jrlhn|O0;aVpJEM8%e`zX46u&&ks)dR<}Crz>CN-H9rhxZgotiQYe%*orDO$SrfF|mDYVw(aq$x{Rr z7svf~-{Vddsj}Zh$upL&+d$K7n)kKk{vOaZo92BjzdixFs0Uz%v6S{pYyRNX#m(GNjc=?-| z#PL7vT4aZ5A1?)6vuU2(_9rZzZ-wjQ@mrC6kY>PvfCICb1FyaK+KZF{`?v}C(9xc) zS8R1QImeRe?c1F0L@E)_B}%>968&Q*r7d>iWITKNL{IO5t9G5*c4A~Khi6apj%N<% z1~v~%)8@^s?demARAw}>c^KvZfOp5o4`wo>M0Gql+<#kQAaAf(EMXoH`(%q3l*tW< zdA`ND#o2}vi8_r~EEUh?50B+X$MSOMcwfiC!+U$Zu=vPm&hssK&d`ud7YMl1_}Qd$ ziF`*k@f&g~lN=O8bU;RWY^0Fl5JJZi>4DQ;j(BA6$Y>!3DDcA4nSA1Kx)8>vivx#- zJUpKqxZOhrGU3 zzS>A~Fqx0{r|efeb_&e4NOx}$+H;_@t8?pC8*0&!+{q>Z!9DqGGJP^9yK|>=t@+cV ziQMMlJsKO$4&;#qvE<2gT-}0QZJ9J*7vEMtD+9yvEWYERy*KrBcJ=l2c6WBYtH-$& zUY%XQ`VO{tp=jh(Mt%9=Y$84=qshU(yrdK3CJlZ~r$u&;>Tu?2ZV`=v49jK)5;;xZ zcru;K4BXCmV`-9?7<5vZ^hrz1)=Bv%ve`^_NQbvLLu2Uy8Hp#;>chpeCkJc@?oWaA zTPJ-A!&Pb0HG~XRUiv>4D?;up!c@7j6~W1&{G}$B3tPd|*UI;&ngp+v$tEN>oXO@j zd2y7stPCbn$&n=4_ujnnP+y?Mi5q6-#`^VLPCu2)j3kT)-mI^$=RhAnR!3+1!M2`0 z#VOCTr}O4^cqz898gs&J! zo$)+RCi1-~dPN?1v2;3-D)MVfr1J41pX*NN6R15?`E^2w_;XNEQTmFr@qA08cbB{r zdE8Qzpm_~aZW(`jUp_H1YB2RxZgIA5*|q}=^+*{Xj^}e^ih5-hT8H&+iU|9(gh@fB zsA!ZpT@ZDpLc$~s5pV9S8;gyc?nt7nb#xwV_Yps$KR_|hArXA9Vu;^aL^?c+zX?iW zKHi%g@loGj`bCsSG2cy`B9?p6ihN6pR_Uwf#^a;8{Me8ZjXgm4bP}yXGCd^3dsO97 zRmk(}NM+)A87lm%kg`b+Phz+h1(e3657|nrMYV_dBzrD@`w7qApF~kWAy0anmb|1D zKs!IFC7_?C4q38+r$=dv057k|6k=H~)iT)kV(v!XmC|a(pvMEowf%|G$kxC3z2JK+ zek!4u<G`Cu8b2H)W&vy$j!Xn4OnHM-TRPN@rK^ z)}8#{zO7vB(wFE#LN){CLjKsMPbF%azTBh)3$HmT$h@MiP!_?fs}4&pA4k7ukL5!w zW+K>@X(Th4CP@FHZhRN4qi7l zGz96L8O!$#4OU2ISauJNBnFf5*7(?9Ql+(fFvrqflB^2u8%2kp4}F*JLVmsg5G{fO#V~cvt`O5#iC+Y?xEpA zMAM>8E|IpyP^Pnjf!bZQbelwPnWo(M}KgouXEWVyh^J z$(gI7%Zz!${wPYWzC~};yU!*t95VjsUXH|5{1!SMLb~I5AEriHIxIdos2X|?J2K3X zXfb+tXsD1n?$8=1vZI+46Xj=$r?pQH>g`yrkSoWa7>4LLM2aGydw4LBKA9gj4!sXUaU|&)F+3Cd`nnv7ut3 z@V?%=>j;B!^j`ICo_!{Ln=NpBlq@acp>H5PnMw}&rYfJFG-cplU_ps0=BT!gs`Y5z zXC}a9BMUSM_!l^G!R-T_CZ-92UtleQCh4fo&w|~)LQ`V|9v`ur>}kf}oLSuB@^!C1 zgQL{vG451bL#axS=8Q{$W;O|r_!h5tbgUdur7F#P5V+;-6}VhdnGU#(<7Ho@`+YOx zG|R~23vOZ8fESY{Tc-mqV_M*Gyz>F7fV9A)Rx~$a;YG8G%&iM4qn3|LlZ0=YFy1c( zzq*kQmn3L1lFPk2kq*rxaN9h$TvIiogYrv22{~Lm9z@_VG^)%~fcNK;LZ9zD(w|3m?3OSdWw1aK2T9O*ky%iq>CAFl z?RZ3x25YE}bE8S0Tc%2ZOP@56#id5VYq+QSM4Gkq1I=Ms=mO8U4Du8_Xx5P?E-lQn z?*G4W}- zrUuVnjXYjJ+yT7*)3|{B1CGgvSeLuA~v);X%Y3pMpQ1M_ii5DF-x>S#Dc2 zO?i%jo|}>Ga?rd9iFClN2kncI-;IV2rcE`at3W@^k#f242GC`J<`D=~{Ym&XzW+?N z7Sr^?r}1u7tw=K|R25A1r@svz^2o;_(6<5iJc`9v=dv4tDo5W9I%(#N=1$Jwp1|Y7 zTk!396r5_`9){odkv@+La%&~G$x^NHj}V8)Q)x2P!gp{((?kxQok0A1nV|t5HKZBo z)p(Y`Ehs$ZHxr;45DN=^X`TdKG#PRq0;vMD6lhk(!pnFs0#z&%sGgo?WO;m!N7ZO5 zsS-SkK$ ze-&xdtVuao?)!%2;#mJ*piZ4J-rIkY%GJ(=OqZICSDCh=`IAc7 zdJ!w9H?ueOik$Znx}LR`S$$W8O&vwA#H$FW64_iblP+61IioW<=aO1k6lv;rWt7Pa z1XD4OF{i0Fz9{8$v-QAZ*AztCI2BW=SWifbtxFYB@k)I~YP?vLQmR~96g?H|1Y_88 zUWpnTr#vlQ@vfAN7pZ(Y#mfqn5-W~bKE>&Iq+^s%p{Gy^XB4Rt)l6$9`FZuMa*ix+ zoco(DOB-*R)VxABZF*kJ=~A4Y{bY%^;5TIxs*34Mi>fbPW!k*bINi&75i6%RqYt4X zO_z?HCM_ot$uX~hkoxP;^STokd;OhH{OgIX*Z=2J^Y%nP@Z?SZZWp{{9lEbu;C>z# zd-qSHD||8B@1ncA8EzU~H;f3R5iWbU5bfuF^5&jJ5C z_`d-69PppRod6#B=^f$E0$&A}rKK4z{dd9L2><CH-31pPRQAJ# zBfHJ}K8W{Wx=+KU|Cfw=(1ib;!T-^?FB$if#$99LrHuQ2$`xWpK&gb#O<4?|}P$xNUH6LJGZbkH8%? z;d!{+Q2#-=e9s5rl7F8x;a@WD({L#%BFK*uuB+g_7wI;`<@ebI_bPc0tU>g{;v2QZ z-wewPC*)SxPwSH|SbaMpH%K>XajzVe8|4^e&N9>&+GnB-BHBTsZDiVWc2MtW7kVA) zF*VR1#Pq>UDD%`ePi^zNAwTw@PP?f8*P+h0L5_9EyJWv~!g|{QP!mAFfq(-62LcWR p90)iNa3J77z=41R0S5vO1RMxB5O5&iK)`{30|5sD4wU1-{|A|y! zKZ1JarJukHue`D!q2BiR4Lpkf*-c<+p|CAd;QWX4CzH&Rc_zQf=HfYdCJ+8N@$koA zPW>q!E5o8i{JY#C+8T~0P}i!J;{xr=%eo$KbsdLT_7H)8Fjk3qYk>|zt&pDcm!Nj2 z1L}khL3*B#V0#og2H_SEC!mwi%TO2e3Z(5`#r8Gmb?6lI2J|NM7W6js4y5hIu{EIg zp!cB83~^bw?OKgRYv)B`1o)cK$Fl7XbQRseGN@R8A#jBV0#6(Mou9=3s4!U(rsx^c(E*K%N!(;ohO?)P&?eog4>k4>}i9*6}I zin1_;B@{-I!8lAv#YRurN^ziekLr6@kK-w(D^0a=>YEj11m1nI2>%MT=F4$$AfbOd z`nkAO|A)1k$p5IYg@bF=6rQCVg@65f)xLGvN*~?YDDt1c{OPf`m8xOig+3!SG*|RX zYOY`gOLJjmVXl6BZgM7r=ALxsrnWBXpIWWxy?!}8Ix%`RGumCZlILaC@dj{MxylTc z=KZKuTk6{1wHhj->oN1R%2x}k#@eKTeY@#rLSij{~I!ymPT%JB$bJ(xv5MJ@N(E4D;p8OWJJGg6>)s_4%+;cHf?FI z*-Oi$C5_IGjt(Q9htRJEmXayIRK}$RhFo+iMLF-9g-{wvSN7f??7b|Lwlr>}M@MF^ z8PWM8fxj54K&DL~z*NdfbK!~8J>T^UzD)W?G|qfz#T}%k#>V7?` z*SbfOr`&=59@ojsD!fJ2g6%}LMaK)vzVFs7EWc#Cg{Z}}@0sP;EG#NF?#FjkWP+Mm ztwcN3s$S(qRt)4H>$L*v*~eSUKYmwt z8s#64Ba41qYj4_GLn;T2EJXjDv{3(8=@}PUez@7znTBd{O{(ToU|qZ5+DH*AOR8} z0TLhq64+@1jQ{R5arz^H-9bRde`kNIzxcVqii(}}a9n-e$99oIluQTeHn85{@amF| zyK4Q%#)TN`b;kd={v+3a+#L@mj)DY8fCNZ@1W14cNPq-LVA}~W{iYr8D~O3*&#&!+igb-+!rp?S|ifS$RgVLINZ}0wh2JBtQZrKmsJN zCkQb9wO*VX4O&8|QBy#5|P|9Sj( z;`=}K64N_~-L|Y*v5I|hr9Z9=#FfE#4EkNsemSjNWrm9R-<7R?cW+9YD(v`jU2YWBeq|N+q=6}aOZEi_`1W14cNPq-L zfCNZ@1ojyL#(($Ogz|DoV2cEF{I{)Udl&y1|I2dyN5=mc|J&lzgJvW^0wh2JBtQZr aKmsH{0(*@B<9~Z?#yDOQ*d78p{`ViqO%m4t diff --git a/mus151/Makefile b/mus151/Makefile deleted file mode 100644 index ed3f757..0000000 --- a/mus151/Makefile +++ /dev/null @@ -1,64 +0,0 @@ -# MUS151 Makefile - Global version for Unix systems which have GNU -# Makefile utilities installed. If you do not have the GNU Makefile -# utilities, I suggest you download them. If that is not possible, -# look at syntmono/Makefile.sgi to see what has to be done to get -# things to compile. -# -# by Gary P. Scavone -# CCRMA, Stanford University, 1998. - -OS = $(shell uname) - -# You will have to modify this path to correspond to the correct -# location in your system. The following definition corresponds -# to an STK project directory that is a subdirectory of the core -# STK distribution. -STK_PATH = ../STK/ - -O_FILES = Object.o Envelope.o WvIn.o RawWvIn.o \ - SKINI11.o swapstuf.o WvOut.o \ - RTWvOut.o RTSoundIO.o \ - \ - TwoOsc.o threads.o - -RM = /bin/rm - -ifeq ($(OS),IRIX) # These are for SGI - INSTR = MUS151 - CC = CC -O2 -D__OS_IRIX_ # -g -fullwarn -D__SGI_CC__ - LIBRARY = -L/usr/sgitcl/lib -laudio -lm -lpthread -endif - -ifeq ($(OS),Linux) # These are for Linux - INSTR = MUS151 - CC = g++ -O3 -D__OS_Linux_ # -g - LIBRARY = -lpthread -lm -endif - -%.o : $(STK_PATH)%.cpp - $(CC) -c $(<) -o $@ - -MUS151: MUS151.cpp $(O_FILES) - $(CC) -o MUS151 MUS151.cpp $(O_FILES) $(LIBRARY) - -# Personal $(O_FILES) : - -TwoOsc.o : TwoOsc.cpp - $(CC) -c TwoOsc.cpp - -threads.o : threads.cpp - $(CC) -c threads.cpp - -all: $(INSTR) - -clean : - rm *.o - rm $(INSTR) - -cleanIns : - rm $(INSTR) - -strip : - strip $(INSTR) - - diff --git a/mus151/README-mus151.txt b/mus151/README-mus151.txt deleted file mode 100644 index 38d46ef..0000000 --- a/mus151/README-mus151.txt +++ /dev/null @@ -1,22 +0,0 @@ -STK: A ToolKit of Audio Synthesis Classes and Instruments in C++ -Version 3.0 - -By Perry R. Cook, 1995-99 -and Gary P. Scavone, 1997-99. - -MUS151: An example project using STK - -By Gary P. Scavone -CCRMA, Stanford University, 1999. - -This directory contains a simple two-oscillator program that can be used to demonstrate psychoacoustic masking effects. It is highly recommended that you keep your personal STK projects separate from the STK core distribution, to make upgrading to newer releases more simple. The files in this directory demonstrate how one might manage this. - -This simple project, named MUS151 for the pyschoacoustics class taught at CCRMA, plays two sine waves and allows independent control of their amplitudes and frequencies. The file MUS151.cpp is essentially the same as syntmono.cpp, though simplified to a great extent because of its more specific use. In particular, only one "instrument" is currently supported (TwoOsc) and only real-time output is used (thus, this project cannot be compiled for NeXTStep). A simple Tcl/Tk GUI has been created to control the instrument. The GUI and STK project can be run under Linux and SGI using the simple GUITwoOsc executable script. - -The mus151 project directory has been distributed as a separate directory from the core STK file directory. In this location, the project should compile without any problems (on Linux, SGI, and Win platforms). Should you choose to relocate this directory, several path variables will need to be updated as described below. - -Three "personal" STK files were created for this project: MUS151.cpp and the TwoOsc class files TwoOsc.h and TwoOsc.cpp. A specific Tcl/Tk GUI script was written (TwoOsc.tcl) and is located in the "tcl" subdirectory. Depending on where you choose to locate the mus151 directory, several #include statements may need to be updated to reflect the location of the STK core distribution. For example, mus151/ is currently outside the STK core files directory, so the various core STK header files are referenced in TwoOsc.h as: #include "../STK/Instrmnt.h". You could move the mus151 files to a completely different point on your directory tree, but you would have to update those statements to correctly reference your core files. Likewise, the RAWWAVE_PATH define statement in Object.h must be properly set for the "sinewave.raw" file to be correctly referenced in TwoOsc.cpp. - -The unix Makefile must also be updated to correctly reference the STK core distribution. A variable, STK_PATH, has been created to simplify this procedure. Note that all STK core object files are referenced with a single, general statement. All personal object files need their own dependency definitions. - -Finally, it is simple to create a VC++ project directory that is completely separate from the STK core distribution. However, it appears that there is no simple way to redefine the location of the project files should you choose to relocate the project after it is created. You will probably have to manually "Add" all the core STK files to the VC++ project after moving the project directory. \ No newline at end of file diff --git a/mus151/Release/.placeholder b/mus151/Release/.placeholder deleted file mode 100644 index e69de29..0000000 diff --git a/mus151/TwoOsc.cpp b/mus151/TwoOsc.cpp deleted file mode 100644 index 9a938da..0000000 --- a/mus151/TwoOsc.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/********************************************/ -/* Two oscillator instrument for use */ -/* with MUS151 Psychoacoustics course. */ -/* by Gary P. Scavone & Oded Ben-Tal, 1998 */ -/* CCRMA, Stanford Unviversity */ -/********************************************/ - -#include "TwoOsc.h" - -TwoOsc :: TwoOsc() -{ - int i; - - envelope = new Envelope; /* Envelope to avoid clicks */ - - // Concatenate the STK RAWWAVE_PATH to the rawwave file - char file[128]; - strcpy(file, RAWWAVE_PATH); - for (i=0; i<2; i++) { - osc[i] = new RawWvIn(strcat(file,"rawwaves/sinewave.raw"),"looping"); - strcpy(file, RAWWAVE_PATH); - osc[i]->normalize(); - osc[i]->setFreq((MY_FLOAT) 200.0); - amps[i] = 0.2; - } - lastOutput = 0; -} - -TwoOsc :: ~TwoOsc() -{ - int i; - for (i=0; i<2; i++) delete osc[i]; - delete envelope; -} - -void TwoOsc :: setFreq(int oscnum, MY_FLOAT frequency) -{ - if (oscnum == 1) osc[0]->setFreq(frequency); - else if (oscnum == 2) osc[1]->setFreq(frequency); -} - -void TwoOsc :: setAmp(int oscnum, MY_FLOAT amp) -{ - if (oscnum == 1) amps[0] = amp; - else if (oscnum == 2) amps[1] = amp; -} - -void TwoOsc :: noteOn(MY_FLOAT freq, MY_FLOAT amp) -{ - envelope->keyOn(); -} - -void TwoOsc :: noteOff(MY_FLOAT amp) -{ - envelope->keyOff(); -} - -MY_FLOAT TwoOsc :: tick() -{ - lastOutput = 0.5 * envelope->tick() * (amps[0]*osc[0]->tick() + amps[1]*osc[1]->tick()); - return lastOutput; -} - -void TwoOsc :: controlChange(int number, MY_FLOAT value) -{ - switch (number) { - case 20: - osc[0]->setFreq(value); - break; - case 21: - osc[1]->setFreq(value); - break; - case 22: - amps[0] = value * NORM_7; - break; - case 23: - amps[1] = value * NORM_7; - break; - } -} diff --git a/mus151/TwoOsc.h b/mus151/TwoOsc.h deleted file mode 100644 index 53d1ad7..0000000 --- a/mus151/TwoOsc.h +++ /dev/null @@ -1,33 +0,0 @@ -/******************************************/ -/* Two oscillator instrument for use */ -/* with MUS151 Psychoacoustics course. */ -/* by Gary P. Scavone, 1998 */ -/* CCRMA, Stanford Unviversity */ -/******************************************/ - -#if !defined(__TwoOsc_h) -#define __TwoOsc_h - -#include "../STK/Envelope.h" -#include "../STK/RawWvIn.h" - -class TwoOsc : public Object -{ - protected: - Envelope *envelope; - RawWvIn *osc[2]; - MY_FLOAT lastOutput; - MY_FLOAT amps[2]; - - public: - TwoOsc(); - ~TwoOsc(); - virtual void setFreq(int oscnum, MY_FLOAT frequency); - virtual void setAmp(int oscnum, MY_FLOAT amp); - virtual void noteOn(MY_FLOAT freq, MY_FLOAT amp); - virtual void noteOff(MY_FLOAT amp); - virtual MY_FLOAT tick(); - virtual void controlChange(int number, MY_FLOAT value); -}; - -#endif diff --git a/mus151/miditabl.h b/mus151/miditabl.h deleted file mode 100644 index 8938646..0000000 --- a/mus151/miditabl.h +++ /dev/null @@ -1,19 +0,0 @@ -#include "../STK/Object.h" - -double __MIDI_To_Pitch[128] = { -8.18,8.66,9.18,9.72,10.30,10.91,11.56,12.25, -12.98,13.75,14.57,15.43,16.35,17.32,18.35,19.45, -20.60,21.83,23.12,24.50,25.96,27.50,29.14,30.87, -32.70,34.65,36.71,38.89,41.20,43.65,46.25,49.00, -51.91,55.00,58.27,61.74,65.41,69.30,73.42,77.78, -82.41,87.31,92.50,98.00,103.83,110.00,116.54,123.47, -130.81,138.59,146.83,155.56,164.81,174.61,185.00,196.00, -207.65,220.00,233.08,246.94,261.63,277.18,293.66,311.13, -329.63,349.23,369.99,392.00,415.30,440.00,466.16,493.88, -523.25,554.37,587.33,622.25,659.26,698.46,739.99,783.99, -830.61,880.00,932.33,987.77,1046.50,1108.73,1174.66,1244.51, -1318.51,1396.91,1479.98,1567.98,1661.22,1760.00,1864.66,1975.53, -2093.00,2217.46,2349.32,2489.02,2637.02,2793.83,2959.96,3135.96, -3322.44,3520.00,3729.31,3951.07,4186.01,4434.92,4698.64,4978.03, -5274.04,5587.65,5919.91,6271.93,6644.88,7040.00,7458.62,7902.13, -8372.02,8869.84,9397.27,9956.06,10548.08,11175.30,11839.82,12543.85}; diff --git a/mus151/tcl/TwoWaves.tcl b/mus151/tcl/TwoWaves.tcl deleted file mode 100644 index e8a41e8..0000000 --- a/mus151/tcl/TwoWaves.tcl +++ /dev/null @@ -1,221 +0,0 @@ -# Tcl/Tk Demo GUI for the Synthesis Toolkit (STK) -# by Gary P. Scavone, CCRMA, Stanford University, 1999. - -# Set initial control values -set pitch 64.0 -set osc1on 1 -set osc2on 1 -set freq1 200.0 -set freq2 200.0 -set amp1 20 -set amp2 20 -set outID "stdout" -set commtype "stdout" - -# Configure main window -wm title . "MUS152 Two Oscillator Controller" -wm iconname . "TwoOsc" -. config -bg black - -# Configure "communications" menu -menu .menu -tearoff 0 -menu .menu.communication -tearoff 0 -.menu add cascade -label "Communication" -menu .menu.communication \ - -underline 0 -.menu.communication add radio -label "Console" -variable commtype \ - -value "stdout" -command { setComm } -.menu.communication add radio -label "Socket" -variable commtype \ - -value "socket" -command { setComm } -. configure -menu .menu - -# Configure title display -label .title -text "MUS151 Two Oscillator Controller" \ - -font {Times 14 bold} -background white \ - -foreground darkred -relief raised - -label .title2 -text "by Gary P. Scavone\n Center for Computer Research in Music & Acoustics (CCRMA) \n Stanford University" \ - -font {Times 12 bold} -background white \ - -foreground darkred -relief raised - -pack .title -padx 5 -pady 10 -pack .title2 -padx 5 -pady 10 - -# Configure "note-on" buttons -frame .noteOn -bg black - -button .noteOn.on -text NoteOn -bg grey66 -command { noteOn $pitch 64.0 } -button .noteOn.off -text NoteOff -bg grey66 -command { noteOff $pitch 127.0 } -button .noteOn.exit -text "Exit Program" -bg grey66 -command myExit -pack .noteOn.on -side left -padx 5 -pack .noteOn.off -side left -padx 5 -pady 10 -pack .noteOn.exit -side left -padx 5 -pady 10 - -pack .noteOn - -# Configure sliders -frame .left -bg black - -scale .left.freq1 -from 0 -to 10000 -length 400 \ --command {changeParam 20 } \ --orient horizontal -label "Frequency 1" \ --tickinterval 2000 -showvalue true -bg grey66 \ --variable freq1 - -scale .left.amp1 -from 0 -to 127 -length 400 \ --command {changeParam 22 } \ --orient horizontal -label "Amp 1" \ --tickinterval 32 -showvalue true -bg grey66 \ --variable amp1 - -scale .left.freq2 -from 0 -to 10000 -length 400 \ --command {changeParam 21 } \ --orient horizontal -label "Frequency 2" \ --tickinterval 2000 -showvalue true -bg grey66 \ --variable freq2 - -scale .left.amp2 -from 0 -to 127 -length 400 \ --command {changeParam 23 } \ --orient horizontal -label "Amp 2" \ --tickinterval 32 -showvalue true -bg grey66 \ --variable amp2 - -pack .left.freq1 -padx 10 -pady 3 -pack .left.amp1 -padx 10 -pady 3 -pack .left.freq2 -padx 10 -pady 3 -pack .left.amp2 -padx 10 -pady 3 - -pack .left -side left - -# Configure more buttons -frame .onOff -bg black - -checkbutton .onOff.1 -text "Play Osc 1" -variable osc1on -relief flat \ - -command {setPlayStatus 22 $osc1on} -checkbutton .onOff.2 -text "Play Osc 2" -variable osc2on -relief flat \ - -command {setPlayStatus 23 $osc2on} - -pack .onOff.1 .onOff.2 -padx 5 -pack .onOff -side right -padx 5 -pady 10 - -# Bind an X windows "close" event with the Exit routine -bind . +myExit - -proc myExit {} { - global outID - puts $outID [format "NoteOff 0.0 1 64.0 127.0" ] - flush $outID - puts $outID [format "ExitProgram"] - flush $outID - close $outID - exit -} - -proc noteOn {pitchVal pressVal} { - global outID - puts $outID [format "NoteOn 0.0 1 %f %f" $pitchVal $pressVal] - flush $outID -} - -proc noteOff {pitchVal pressVal} { - global outID - puts $outID [format "NoteOff 0.0 1 %f %f" $pitchVal $pressVal] - flush $outID -} - -proc changeParam {controlNum value } { - global outID freq1 freq2 amp1 amp2 osc1on osc2on - if {$controlNum==20 || $controlNum==22} { - if {$osc1on==1} { - puts $outID [format "ControlChange 0.0 1 %d %f" $controlNum $value ] - } - } elseif {$controlNum==21 || $controlNum==23} { - if {$osc2on==1} { - puts $outID [format "ControlChange 0.0 1 %d %f" $controlNum $value ] - } - } - flush $outID -} - -proc setPlayStatus {controlNum value } { - global outID amp1 amp2 freq1 freq2 - if {$value==1} { - if {$controlNum==22} { - puts $outID [format "ControlChange 0.0 1 %d %f" 20 $freq1 ] - puts $outID [format "ControlChange 0.0 1 %d %f" $controlNum $amp1 ] - } elseif {$controlNum==23} { - puts $outID [format "ControlChange 0.0 1 %d %f" 21 $freq2 ] - puts $outID [format "ControlChange 0.0 1 %d %f" $controlNum $amp2 ] - } - } elseif {$value==0} { - puts $outID [format "ControlChange 0.0 1 %d %f" $controlNum 0.0 ] - } - flush $outID -} - -# Socket connection procedure -set d .socketdialog - -proc setComm {} { - global outID - global commtype - global d - if {$commtype == "stdout"} { - if { [string compare "stdout" $outID] } { - set i [tk_dialog .dialog "Break Socket Connection?" {You are about to break an existing socket connection ... is this what you want to do?} "" 0 Cancel OK] - switch $i { - 0 {set commtype "socket"} - 1 {close $outID - set outID "stdout"} - } - } - } elseif { ![string compare "stdout" $outID] } { - set sockport 2001 - set sockhost localhost - toplevel $d - wm title $d "STK Client Socket Connection" - wm resizable $d 0 0 - grab $d - label $d.message -text "Specify a socket host and port number below (if different than the STK defaults shown) and then click the \"Connect\" button to invoke a socket-client connection attempt to the STK socket server." \ - -background white -font {Helvetica 10 bold} \ - -wraplength 3i -justify left - frame $d.sockhost - entry $d.sockhost.entry -width 15 - label $d.sockhost.text -text "Socket Host:" \ - -font {Helvetica 10 bold} - frame $d.sockport - entry $d.sockport.entry -width 15 - label $d.sockport.text -text "Socket Port:" \ - -font {Helvetica 10 bold} - pack $d.message -side top -padx 5 -pady 10 - pack $d.sockhost.text -side left -padx 1 -pady 2 - pack $d.sockhost.entry -side right -padx 5 -pady 2 - pack $d.sockhost -side top -padx 5 -pady 2 - pack $d.sockport.text -side left -padx 1 -pady 2 - pack $d.sockport.entry -side right -padx 5 -pady 2 - pack $d.sockport -side top -padx 5 -pady 2 - $d.sockhost.entry insert 0 $sockhost - $d.sockport.entry insert 0 $sockport - frame $d.buttons - button $d.buttons.cancel -text "Cancel" -bg grey66 \ - -command { set commtype "stdout" - set outID "stdout" - destroy $d } - button $d.buttons.connect -text "Connect" -bg grey66 \ - -command { - set sockhost [$d.sockhost.entry get] - set sockport [$d.sockport.entry get] - set err [catch {socket $sockhost $sockport} outID] - - if {$err == 0} { - destroy $d - } else { - tk_dialog $d.error "Socket Error" {Error: Unable to make socket connection. Make sure the STK socket server is first running and that the port number is correct.} "" 0 OK - } } - pack $d.buttons.cancel -side left -padx 5 -pady 10 - pack $d.buttons.connect -side right -padx 5 -pady 10 - pack $d.buttons -side bottom -padx 5 -pady 10 - } -} - - - diff --git a/mus151/threads.cpp b/mus151/threads.cpp deleted file mode 100644 index 4313af0..0000000 --- a/mus151/threads.cpp +++ /dev/null @@ -1,279 +0,0 @@ -// Thread functions for use with syntmono. -// -// No mutexes are currently being used when accessing -// the global variables shared between these threads -// and the main() routine. In a single processor -// environment, no problems have resulted from such data -// sharing. However, if STK is to be run on a true parallel -// processing platform, it is likely that mutexes will be -// necessary. While the mutex calls are simple to code, I -// am trying to keep the code as generic as possible. A -// quick investigation of threads under Windoze indicates -// that mutex functionality is not available, at least with -// the standard libraries. -// -// Gary P. Scavone, 2000. - -#include "threads.h" - -#if defined(__STK_REALTIME_) - -// Default STK socket port ID number -#define SERVICE_PORT 2001 - -// Do OS dependent declarations and includes -#if (defined(__OS_IRIX_) || defined(__OS_Linux_)) -#include -#include -#include -#include -#include -#include - -pthread_t string_thread; - -#elif defined(__OS_Win_) -#include -#include - -unsigned long string_thread; - -#endif - - -// The thread function protocols are slightly different -// under Windoze ... but of course! - -#if (defined(__OS_IRIX_) || defined(__OS_Linux_)) - -void *newStringByPipe(void *) - -#elif defined(__OS_Win_) - -void newStringByPipe(void *) - -#endif - -{ - extern int numStrings, notDone; - extern char **inputString; - int i; - - // Malloc inputString. - inputString = (char **) malloc(MAX_IN_STRINGS * sizeof(char *)); - for ( i=0;i MAX_IN_STRINGS) { - fprintf(stderr,"Losing MIDI data ... try increasing MAX_IN_STRINGS.\n"); - numStrings--; - } - inOne++; - if (inOne == MAX_IN_STRINGS) inOne = 0; - } - } - - // Free inputString. - for ( i=0;i maxfd) maxfd = accept_id; - FD_CLR(soc_id, &rmask); - } - for (fd=0;fd<=maxfd;fd++) { // look for other sockets with data - if (FD_ISSET(fd, &rmask)) { // process the data - parsing = 1; - while (parsing) { - i = recv(fd, socBuf, STRING_LEN,0); - if (i==0) { - printf("Closing a socket connection.\n"); - FD_CLR(fd, &mask); -#if defined(__OS_Win_) - closesocket(fd); -#else - close(fd); -#endif - parsing = 0; - } - n = 0; - while (n < i) { - inputString[inOne][m++] = socBuf[n]; - if (socBuf[n++] == '\n') { - if (inputString[inOne][2] == 'i' && inputString[inOne][3] == 't' - && inputString[inOne][1] == 'x' && inputString[inOne][0] == 'E') { - notDone = 0; - n = i; - parsing = 0; - } - else { - m = 0; - if (n >= i) parsing = 0; - numStrings++; - if (numStrings > MAX_IN_STRINGS) { - fprintf(stderr,"Losing MIDI data ... try increasing MAX_IN_STRINGS.\n"); - numStrings--; - } - inOne++; - if (inOne == MAX_IN_STRINGS) inOne = 0; - memset(inputString[inOne], 0, STRING_LEN); - } - } - } - } - } - } - } -#if defined(__OS_Win_) // Stupid Windoze only stuff - closesocket(soc_id); - WSACleanup(); -#else - shutdown(soc_id,0); -#endif - - // Free inputString. - for ( i=0;inormalize(); - mods[1]->normalize(); mods[0]->setFreq(0.2); mods[1]->setFreq(0.222222); modDepth = 0.05; diff --git a/effects/Chorus.h b/projects/effects/Chorus.h similarity index 89% rename from effects/Chorus.h rename to projects/effects/Chorus.h index cf69163..11be90f 100644 --- a/effects/Chorus.h +++ b/projects/effects/Chorus.h @@ -6,9 +6,9 @@ #if !defined(__Chorus_h) #define __Chorus_h -#include "../STK/Object.h" -#include "../STK/DLineL.h" -#include "../STK/RawWvIn.h" +#include "Object.h" +#include "DLineL.h" +#include "RawWvIn.h" class Chorus : public Object { diff --git a/effects/Echo.cpp b/projects/effects/Echo.cpp similarity index 100% rename from effects/Echo.cpp rename to projects/effects/Echo.cpp diff --git a/effects/Echo.h b/projects/effects/Echo.h similarity index 90% rename from effects/Echo.h rename to projects/effects/Echo.h index 8a211d6..1c6462a 100644 --- a/effects/Echo.h +++ b/projects/effects/Echo.h @@ -6,8 +6,8 @@ #if !defined(__Echo_h) #define __Echo_h -#include "../STK/Object.h" -#include "../STK/DLineN.h" +#include "Object.h" +#include "DLineN.h" class Echo : public Object { diff --git a/effects/GUIeffects b/projects/effects/GUIeffects similarity index 100% rename from effects/GUIeffects rename to projects/effects/GUIeffects diff --git a/effects/Makefile b/projects/effects/Makefile similarity index 62% rename from effects/Makefile rename to projects/effects/Makefile index f8c2fb0..1e0c10a 100644 --- a/effects/Makefile +++ b/projects/effects/Makefile @@ -4,13 +4,14 @@ OS = $(shell uname) # The following definition indicates the relative location of # the core STK classes. -STK_PATH = ../STK/ +STK_PATH = ../../src/ O_FILES = Object.o Reverb.o PRCRev.o JCRev.o \ - NRev.o RTSoundIO.o DLineN.o Filter.o \ - RTDuplex.o SKINI11.o Envelope.o Echo.o \ + NRev.o RtAudio.o DLineN.o Filter.o \ + RtDuplex.o SKINI11.o Envelope.o Echo.o \ PitShift.o DLineL.o Chorus.o RawWvIn.o \ - WvIn.o swapstuf.o threads.o + WvIn.o ByteSwap.o StkError.o Controller.o \ + RtMidi.o RM = /bin/rm @@ -19,16 +20,18 @@ ifeq ($(OS),IRIX) # These are for SGI INSTR = effects CC = CC -O2 -D__OS_IRIX_ # -g -fullwarn -D__SGI_CC__ LIBRARY = -L/usr/sgitcl/lib -laudio -lmd -lm -lpthread + INCLUDE = -I../../include endif ifeq ($(OS),Linux) # These are for Linux INSTR = effects CC = g++ -O3 -Wall -D__OS_Linux_ # -g - LIBRARY = -lpthread -lm + LIBRARY = -lpthread -lm #-lasound + INCLUDE = -I../../include endif %.o : $(STK_PATH)%.cpp - $(CC) -c $(<) -o $@ + $(CC) $(INCLUDE) -c $(<) -o $@ all: $(INSTR) @@ -43,18 +46,15 @@ strip : strip $(INSTR) effects: effects.cpp $(O_FILES) - $(CC) -O3 -o effects effects.cpp $(O_FILES) $(LIBRARY) + $(CC) $(INCLUDE) -o effects effects.cpp $(O_FILES) $(LIBRARY) # $(O_FILES) : -threads.o: threads.cpp - $(CC) -c threads.cpp - Echo.o: Echo.cpp - $(CC) -c Echo.cpp + $(CC) $(INCLUDE) -c Echo.cpp PitShift.o: PitShift.cpp - $(CC) -c PitShift.cpp + $(CC) $(INCLUDE) -c PitShift.cpp Chorus.o: Chorus.cpp - $(CC) -c Chorus.cpp \ No newline at end of file + $(CC) $(INCLUDE) -c Chorus.cpp \ No newline at end of file diff --git a/projects/effects/Makefile.sgi b/projects/effects/Makefile.sgi new file mode 100644 index 0000000..88bd52f --- /dev/null +++ b/projects/effects/Makefile.sgi @@ -0,0 +1,53 @@ +# STK Makefile for Effects project- SGI solo version (non-GNU Makefile utilities version) + +# The following definition indicates the relative location of +# the core STK classes. +STK_PATH = ../../src/ + +O_FILES = $(STK_PATH)Object.o $(STK_PATH)Envelope.o $(STK_PATH)Filter.o \ + $(STK_PATH)DLineL.o $(STK_PATH)DLineN.o $(STK_PATH)ByteSwap.o \ + $(STK_PATH)SKINI11.o $(STK_PATH)WvIn.o $(STK_PATH)RawWvIn.o \ + $(STK_PATH)Reverb.o $(STK_PATH)PRCRev.o $(STK_PATH)JCRev.o \ + $(STK_PATH)NRev.o $(STK_PATH)RtAudio.o $(STK_PATH)RtMidi.o \ + $(STK_PATH)RtDuplex.o $(STK_PATH)StkError.o $(STK_PATH)Controller.o + +O_LOCAL_FILES = Echo.o PitShift.o Chorus.o + +RM = /bin/rm + +INSTR = effects +CC = CC -O2 -D__OS_IRIX_ # -g -fullwarn -D__SGI_CC__ +LIBRARY = -L/usr/sgitcl/lib -laudio -lmd -lm -lpthread +INCLUDE = -I../../include/ + +.SUFFIXES: .cpp +.cpp.o: $(O_FILES) + $(CC) $(INCLUDE) -c -o $@ $< + +all: $(INSTR) + +effects: effects.cpp $(O_FILES) $(O_LOCAL_FILES) + $(CC) -o effects effects.cpp $(O_FILES) $(O_LOCAL_FILES) $(LIBRARY) $(INCLUDE) + +clean : + rm *.o + rm $(STK_PATH)*.o + rm $(INSTR) + +cleanIns : + rm $(INSTR) + +strip : + strip $(INSTR) + +# $(O_FILES) : + +Echo.o: Echo.cpp + $(CC) $(INCLUDE) -c Echo.cpp + +PitShift.o: PitShift.cpp + $(CC) $(INCLUDE) -c PitShift.cpp + +Chorus.o: Chorus.cpp + $(CC) $(INCLUDE) -c Chorus.cpp + diff --git a/effects/PitShift.cpp b/projects/effects/PitShift.cpp similarity index 100% rename from effects/PitShift.cpp rename to projects/effects/PitShift.cpp diff --git a/effects/PitShift.h b/projects/effects/PitShift.h similarity index 91% rename from effects/PitShift.h rename to projects/effects/PitShift.h index 080246c..7ddc824 100644 --- a/effects/PitShift.h +++ b/projects/effects/PitShift.h @@ -6,8 +6,8 @@ #if !defined(__PitShift_h) #define __PitShift_h -#include "../STK/Object.h" -#include "../STK/DLineL.h" +#include "Object.h" +#include "DLineL.h" class PitShift : public Object { diff --git a/effects/README-effects.txt b/projects/effects/README-effects.txt similarity index 71% rename from effects/README-effects.txt rename to projects/effects/README-effects.txt index 1e6141b..2dcc698 100644 --- a/effects/README-effects.txt +++ b/projects/effects/README-effects.txt @@ -1,16 +1,16 @@ STK: A ToolKit of Audio Synthesis Classes and Instruments in C++ -Version 3.0 +Version 3.2 -By Perry R. Cook, 1995-99 -and Gary P. Scavone, 1997-99. +By Perry R. Cook, 1995-2000 +and Gary P. Scavone, 1997-2000. EFFECTS PROJECT: -This directory contains a program that demonstrates realtime duplex mode (simultaneous audio input and output) operation, as well as several simple delay-line based effects algorithms. Proper duplex mode operation is very hardware dependent. If you have trouble with this application, make sure your soundcard supports the desired sample rates and sample sizes. Under Linux, also make sure that your soundcard is supported by OSS (http://www.opensound.com/). +This directory contains a program that demonstrates realtime duplex mode (simultaneous audio input and output) operation, as well as several simple delay-line based effects algorithms. Proper duplex mode operation is very hardware dependent. If you have trouble with this application, make sure your soundcard supports the desired sample rate and sample size (16-bit). NOTES: -1. This project will not run under WindowsNT or NeXTStep, due to lack of realtime audio input support. +1. This project will not run under WindowsNT or NeXTStep, due to lack of realtime audio input support. However, it should run under Windows2000. 2. Audio input from either a microphone or line-input device MUST be available to the audio input port when the program is started. \ No newline at end of file diff --git a/effects/Debug/.placeholder b/projects/effects/Release/.placeholder similarity index 100% rename from effects/Debug/.placeholder rename to projects/effects/Release/.placeholder diff --git a/projects/effects/effects.cpp b/projects/effects/effects.cpp new file mode 100644 index 0000000..65c713f --- /dev/null +++ b/projects/effects/effects.cpp @@ -0,0 +1,171 @@ +/************** Effects Program *********************/ + +#include "RtDuplex.h" +#include "SKINI11.h" +#include "SKINI11.msg" +#include "Envelope.h" +#include "PRCRev.h" +#include "JCRev.h" +#include "NRev.h" +#include "Echo.h" +#include "PitShift.h" +#include "Chorus.h" + +// The input control handler. +#include "Controller.h" + +void usage(void) { + /* Error function in case of incorrect command-line argument specifications */ + printf("\nuseage: effects flag \n"); + printf(" where flag = -ip for realtime SKINI input by pipe\n"); + printf(" (won't work under Win95/98),\n"); + printf(" and flag = -is for realtime SKINI input by socket.\n"); + exit(0); +} + +int main(int argc,char *argv[]) +{ + MY_FLOAT inSample = 0.0; + MY_FLOAT lastSample = 0.0; + MY_FLOAT byte2, byte3; + long i, nTicks; + int type, effect = 0; + int controlMask = 0; + bool done; + Controller *controller; + + if (argc != 2) usage(); + + if (!strcmp(argv[1],"-is") ) + controlMask |= STK_SOCKET; + else if (!strcmp(argv[1],"-ip") ) + controlMask |= STK_PIPE; + else + usage(); + + Envelope *envelope = new Envelope; + PRCRev *prcrev = new PRCRev(2.0); + JCRev *jcrev = new JCRev(2.0); + NRev *nrev = new NRev(2.0); + Echo *echo = new Echo(SRATE); // one second delay + PitShift *shifter = new PitShift(); + Chorus *chorus = new Chorus(5000.0); + SKINI11 *score = new SKINI11(); + RtDuplex *inout; + + try { + inout = new RtDuplex(1, SRATE); + + // Instantiate the input message controller. + controller = new Controller( controlMask ); + } + catch (StkError& m) { + m.printMessage(); + exit(0); + } + + // The runtime loop begins here: + done = FALSE; + while (!done) { + + nTicks = controller->getNextMessage(); + + if (nTicks == -1) + done = TRUE; + + for (i=0; itick(envelope->tick() * echo->tick(lastSample)); + else if (effect == 1) + inSample = inout->tick(envelope->tick() * shifter->tick(lastSample)); + else if (effect == 2) + inSample = inout->tick(envelope->tick() * chorus->tick(lastSample)); + else if (effect == 3) + inSample = inout->tick(envelope->tick() * prcrev->tick(lastSample)); + else if (effect == 4) + inSample = inout->tick(envelope->tick() * jcrev->tick(lastSample)); + else if (effect == 5) + inSample = inout->tick(envelope->tick() * nrev->tick(lastSample)); + lastSample = inSample; + } + + type = controller->getType(); + if (type > 0) { + // parse the input control message + + byte2 = controller->getByte2(); + byte3 = controller->getByte3(); + + switch(type) { + + case __SK_NoteOn_: + if (byte3 == 0) { // velocity is zero ... really a NoteOff + envelope->setRate(0.001); + envelope->setTarget(0.0); + } + else { // really a NoteOn + envelope->setRate(0.001); + envelope->setTarget(1.0); + } + break; + + case __SK_NoteOff_: + envelope->setRate(0.001); + envelope->setTarget(0.0); + break; + + case __SK_ControlChange_: + if (byte2 == 20) effect = (int) byte3; // effect change + else if (byte2 == 44) { // effects mix + echo->setEffectMix(byte3*NORM_7); + shifter->setEffectMix(byte3*NORM_7); + chorus->setEffectMix(byte3*NORM_7); + prcrev->setEffectMix(byte3*NORM_7); + jcrev->setEffectMix(byte3*NORM_7); + nrev->setEffectMix(byte3*NORM_7); + } + else if (byte2 == 22) { // effect1 parameter change + echo->setDelay(byte3*NORM_7*SRATE*0.95 + 2); + shifter->setShift(byte3*NORM_7*3 + 0.25); + chorus->setModFreq(byte3*NORM_7); + } + else if (byte2 == 23) { // effect1 parameter change + chorus->setModDepth(byte3*NORM_7*0.2); + } + break; + } + } + } + + envelope->setRate(0.001); + envelope->setTarget(0.0); + for (i=0;itick(envelope->tick() * echo->tick(lastSample)); + else if (effect == 1) + inSample = inout->tick(envelope->tick() * shifter->tick(lastSample)); + else if (effect == 2) + inSample = inout->tick(envelope->tick() * chorus->tick(lastSample)); + else if (effect == 3) + inSample = inout->tick(envelope->tick() * prcrev->tick(lastSample)); + else if (effect == 4) + inSample = inout->tick(envelope->tick() * jcrev->tick(lastSample)); + else if (effect == 5) + inSample = inout->tick(envelope->tick() * nrev->tick(lastSample)); + lastSample = inSample; + } + + delete inout; + delete echo; + delete shifter; + delete chorus; + delete prcrev; + delete jcrev; + delete nrev; + delete score; + delete envelope; + delete controller; + + printf("effects finished ... goodbye.\n"); + return 0; +} diff --git a/effects/effects.dsp b/projects/effects/effects.dsp similarity index 69% rename from effects/effects.dsp rename to projects/effects/effects.dsp index e5d530d..0c91871 100644 --- a/effects/effects.dsp +++ b/projects/effects/effects.dsp @@ -1,5 +1,5 @@ # Microsoft Developer Studio Project File - Name="effects" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 @@ -22,6 +22,7 @@ CFG=effects - Win32 Debug !MESSAGE # Begin Project +# PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe @@ -41,7 +42,7 @@ RSC=rc.exe # 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 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__OS_Win_" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__OS_Win_" /YX /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe @@ -49,7 +50,7 @@ BSC32=bscmake.exe # 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 /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 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 winmm.lib /nologo /subsystem:console /machine:I386 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "effects - Win32 Debug" @@ -66,7 +67,7 @@ LINK32=link.exe # 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 /c -# ADD CPP /nologo /MT /W3 /Gm /GX /Zi /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__OS_Win_" /YX /FD /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__OS_Win_" /YX /FD /c # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe @@ -74,7 +75,7 @@ BSC32=bscmake.exe # 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 /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 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 winmm.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # SUBTRACT LINK32 /pdb:none !ENDIF @@ -85,6 +86,14 @@ LINK32=link.exe # Name "effects - Win32 Debug" # Begin Source File +SOURCE=..\..\src\ByteSwap.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\include\ByteSwap.h +# End Source File +# Begin Source File + SOURCE=.\Chorus.cpp # End Source File # Begin Source File @@ -93,19 +102,27 @@ SOURCE=.\Chorus.h # End Source File # Begin Source File -SOURCE=..\Stk\DLineL.cpp +SOURCE=..\..\src\Controller.cpp # End Source File # Begin Source File -SOURCE=..\Stk\DLineL.h +SOURCE=..\..\include\Controller.h # End Source File # Begin Source File -SOURCE=..\Stk\DLineN.cpp +SOURCE=..\..\src\DLineL.cpp # End Source File # Begin Source File -SOURCE=..\Stk\DLineN.h +SOURCE=..\..\include\DLineL.h +# End Source File +# Begin Source File + +SOURCE=..\..\src\DLineN.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\include\DLineN.h # End Source File # Begin Source File @@ -121,43 +138,43 @@ SOURCE=.\effects.cpp # End Source File # Begin Source File -SOURCE=..\Stk\Envelope.cpp +SOURCE=..\..\src\Envelope.cpp # End Source File # Begin Source File -SOURCE=..\Stk\Envelope.h +SOURCE=..\..\include\Envelope.h # End Source File # Begin Source File -SOURCE=..\Stk\Filter.cpp +SOURCE=..\..\src\Filter.cpp # End Source File # Begin Source File -SOURCE=..\Stk\Filter.h +SOURCE=..\..\include\Filter.h # End Source File # Begin Source File -SOURCE=..\Stk\JCRev.cpp +SOURCE=..\..\src\JCRev.cpp # End Source File # Begin Source File -SOURCE=..\Stk\JCRev.h +SOURCE=..\..\include\JCRev.h # End Source File # Begin Source File -SOURCE=..\Stk\NRev.cpp +SOURCE=..\..\src\NRev.cpp # End Source File # Begin Source File -SOURCE=..\Stk\NRev.h +SOURCE=..\..\include\NRev.h # End Source File # Begin Source File -SOURCE=..\Stk\Object.cpp +SOURCE=..\..\src\Object.cpp # End Source File # Begin Source File -SOURCE=..\Stk\Object.h +SOURCE=..\..\include\Object.h # End Source File # Begin Source File @@ -169,75 +186,75 @@ SOURCE=.\PitShift.h # End Source File # Begin Source File -SOURCE=..\Stk\PRCRev.cpp +SOURCE=..\..\src\PRCRev.cpp # End Source File # Begin Source File -SOURCE=..\Stk\PRCRev.h +SOURCE=..\..\include\PRCRev.h # End Source File # Begin Source File -SOURCE=..\Stk\RawWvIn.cpp +SOURCE=..\..\src\RawWvIn.cpp # End Source File # Begin Source File -SOURCE=..\Stk\RawWvIn.h +SOURCE=..\..\include\RawWvIn.h # End Source File # Begin Source File -SOURCE=..\Stk\Reverb.cpp +SOURCE=..\..\src\Reverb.cpp # End Source File # Begin Source File -SOURCE=..\Stk\Reverb.h +SOURCE=..\..\include\Reverb.h # End Source File # Begin Source File -SOURCE=..\Stk\RTDuplex.cpp +SOURCE=..\..\src\RtAudio.cpp # End Source File # Begin Source File -SOURCE=..\Stk\RTDuplex.h +SOURCE=..\..\include\RtAudio.h # End Source File # Begin Source File -SOURCE=..\Stk\RTSoundIO.cpp +SOURCE=..\..\src\RtDuplex.cpp # End Source File # Begin Source File -SOURCE=..\Stk\RTSoundIO.h +SOURCE=..\..\include\RtDuplex.h # End Source File # Begin Source File -SOURCE=..\Stk\SKINI11.cpp +SOURCE=..\..\src\RtMidi.cpp # End Source File # Begin Source File -SOURCE=..\Stk\SKINI11.h +SOURCE=..\..\include\RtMidi.h # End Source File # Begin Source File -SOURCE=..\Stk\swapstuf.cpp +SOURCE=..\..\src\SKINI11.cpp # End Source File # Begin Source File -SOURCE=..\Stk\swapstuf.h +SOURCE=..\..\include\SKINI11.h # End Source File # Begin Source File -SOURCE=.\threads.cpp +SOURCE=..\..\src\StkError.cpp # End Source File # Begin Source File -SOURCE=.\threads.h +SOURCE=..\..\include\StkError.h # End Source File # Begin Source File -SOURCE=..\Stk\WvIn.cpp +SOURCE=..\..\src\WvIn.cpp # End Source File # Begin Source File -SOURCE=..\Stk\WvIn.h +SOURCE=..\..\include\WvIn.h # End Source File # End Target # End Project diff --git a/effects/effects.dsw b/projects/effects/effects.dsw similarity index 82% rename from effects/effects.dsw rename to projects/effects/effects.dsw index 135e27f..2ebac4a 100644 --- a/effects/effects.dsw +++ b/projects/effects/effects.dsw @@ -1,4 +1,4 @@ -Microsoft Developer Studio Workspace File, Format Version 5.00 +Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### diff --git a/effects/tcl/Effects.tcl b/projects/effects/tcl/Effects.tcl similarity index 99% rename from effects/tcl/Effects.tcl rename to projects/effects/tcl/Effects.tcl index 9c37240..363924a 100644 --- a/effects/tcl/Effects.tcl +++ b/projects/effects/tcl/Effects.tcl @@ -49,7 +49,7 @@ pack .noteOn frame .left -bg black scale .left.effectsmix -from 0 -to 127 -length 400 \ --command {printWhatz "ControlChange 0.0 1 " 21} \ +-command {printWhatz "ControlChange 0.0 1 " 44} \ -orient horizontal -label "Effects Mix" \ -tickinterval 32 -showvalue true -bg grey66 \ -variable mixlevel diff --git a/projects/examples/Makefile b/projects/examples/Makefile new file mode 100644 index 0000000..7cd25af --- /dev/null +++ b/projects/examples/Makefile @@ -0,0 +1,60 @@ +# Misc Makefile - Global version for Unix systems which have GNU +# Makefile utilities installed. If this Makefile does not work on +# your system, try using the platform specific Makefiles (.sgi, +# .next, and .linux). + +OS = $(shell uname) + +# You will have to modify this path to correspond to the correct +# location in your system. The following definition corresponds +# to an STK project directory that is a subdirectory of the core +# STK distribution. +STK_PATH = ../../src/ + +O_FILES = Object.o WvOut.o WvIn.o RtAudio.o \ + RtWvIn.o RtWvOut.o ByteSwap.o \ + StkError.o WavWvOut.o StrmWvIn.o \ + RtDuplex.o StrmWvOut.o WavWvIn.o \ + RawWvIn.o + +RM = /bin/rm + +ifeq ($(OS),Linux) # These are for Linux + INSTR = sineN playN recordN ioN streamInN streamOutN + CC = g++ -O3 -Wall -D__OS_Linux_ # -g -pg -O3 + LIBRARY = -lpthread -lm #-lasound + INCLUDE = -I../../include +endif + +%.o : $(STK_PATH)%.cpp + $(CC) $(INCLUDE) -c $(<) -o $@ + +all: $(INSTR) + +clean : + rm *.o + rm $(INSTR) + +cleanIns : + rm $(INSTR) + +strip : + strip $(INSTR) + +playN: playN.cpp $(O_FILES) + $(CC) -o playN playN.cpp $(O_FILES) $(LIBRARY) $(INCLUDE) + +streamOutN: streamOutN.cpp $(O_FILES) + $(CC) -o streamOutN streamOutN.cpp $(O_FILES) $(LIBRARY) $(INCLUDE) + +streamInN: streamInN.cpp $(O_FILES) + $(CC) -o streamInN streamInN.cpp $(O_FILES) $(LIBRARY) $(INCLUDE) + +recordN: recordN.cpp $(O_FILES) + $(CC) -o recordN recordN.cpp $(O_FILES) $(LIBRARY) $(INCLUDE) + +ioN: ioN.cpp $(O_FILES) + $(CC) -o ioN ioN.cpp $(O_FILES) $(LIBRARY) $(INCLUDE) + +sineN: sineN.cpp $(O_FILES) + $(CC) -o sineN sineN.cpp $(O_FILES) $(LIBRARY) $(INCLUDE) diff --git a/projects/examples/examples.dsw b/projects/examples/examples.dsw new file mode 100755 index 0000000..ade5b1d --- /dev/null +++ b/projects/examples/examples.dsw @@ -0,0 +1,89 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "ioN"=.\ioN.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "playN"=.\playN.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "recordN"=.\recordN.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "sineN"=.\sineN.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "streamInN"=.\streamInN.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "streamOutN"=.\streamOutN.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/projects/examples/ioN.cpp b/projects/examples/ioN.cpp new file mode 100644 index 0000000..abe3398 --- /dev/null +++ b/projects/examples/ioN.cpp @@ -0,0 +1,99 @@ +/******************************************/ +/* + Example program for realtime input/output + by Gary P. Scavone, 2000 + + This program reads N channels of realtime + audio input for a specified amount of time + and immediately play them back in realtime + (duplex mode). This program also demonstrates + the use of FIFO scheduling priority. To be + run with such priority, the program must be + set suid (chmod +s) and owned by root. +*/ +/******************************************/ + +#include "RtDuplex.h" + +#if !defined(__OS_Win_) + #include +#endif + +void usage(void) { + /* Error function in case of incorrect command-line + argument specifications + */ + printf("\nuseage: ioN N time \n"); + printf(" where N = number of channels,\n"); + printf(" and time = the amount of time to record (in seconds).\n\n"); + exit(0); +} + +int +main(int argc, char *argv[]) +{ + int i=0; + + // minimal command-line checking + if (argc != 3) usage(); + + int chans = (int) atoi(argv[1]); + float time = atof(argv[2]); + float sample_rate = SRATE; + MY_FLOAT *inSamples; + MY_FLOAT *lastSamples; + + // allocate the lastSamples array + lastSamples = (MY_FLOAT *) new MY_FLOAT[chans]; + for (i=0; imtick(lastSamples); + for (int k=0; k=256) { + sched_yield(); + j = 0; + } +#endif + } + + // Clean up + delete inout; + delete [] lastSamples; +} diff --git a/projects/examples/ioN.dsp b/projects/examples/ioN.dsp new file mode 100755 index 0000000..bba37c6 --- /dev/null +++ b/projects/examples/ioN.dsp @@ -0,0 +1,142 @@ +# Microsoft Developer Studio Project File - Name="ioN" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=ioN - 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 "ioN.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 "ioN.mak" CFG="ioN - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ioN - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "ioN - 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)" == "ioN - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "ioN___Win32_Release" +# PROP BASE Intermediate_Dir "ioN___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 "__OS_Win_" /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 dsound.lib winmm.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "ioN - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "ioN___Win32_Debug" +# PROP BASE Intermediate_Dir "ioN___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 "__OS_Win_" /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 dsound.lib winmm.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "ioN - Win32 Release" +# Name "ioN - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\src\ByteSwap.cpp +# End Source File +# Begin Source File + +SOURCE=.\ioN.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\Object.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\RtAudio.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\RtDuplex.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\StkError.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\include\ByteSwap.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\Object.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\RtAudio.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\RtDuplex.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\StkError.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/playN.cpp b/projects/examples/playN.cpp new file mode 100644 index 0000000..f2e02bb --- /dev/null +++ b/projects/examples/playN.cpp @@ -0,0 +1,66 @@ +/******************************************/ +/* + Example program to play an N channel soundfile + by Gary P. Scavone, 2000 + + This program is currently written to load + a WAV file and play it in realtime. However, + it is simple to replace the instance of + WavWvIn with any other WvIn subclass. + Likewise, RtWvOut can be replaced with any + other WvOut subclass. +*/ +/******************************************/ + +#include "RtWvOut.h" +#include "WavWvIn.h" + +void usage(void) { + /* Error function in case of incorrect command-line + argument specifications + */ + printf("\nuseage: playN N file fs \n"); + printf(" where N = number of channels,\n"); + printf(" file = the .wav file to play,\n"); + printf(" and fs = the sample rate.\n\n"); + exit(0); +} + +int main(int argc, char *argv[]) +{ + // minimal command-line checking + if (argc != 4) usage(); + + int chans = (int) atoi(argv[1]); + + // Define and load the SND soundfile + WvIn *input; + try { + input = new WavWvIn((char *)argv[2], "oneshot"); + } + catch (StkError& m) { + m.printMessage(); + exit(0); + } + // Set playback rate here + input->setRate(atof(argv[3])/SRATE); + + // Define and open the realtime output device + WvOut *output; + try { + output = new RtWvOut(chans); + } + catch (StkError& m) { + m.printMessage(); + exit(0); + } + + // Here's the runtime loop + while (!input->isFinished()) { + output->mtick(input->mtick()); + } + + // Clean up + delete input; + delete output; +} diff --git a/projects/examples/playN.dsp b/projects/examples/playN.dsp new file mode 100755 index 0000000..586790e --- /dev/null +++ b/projects/examples/playN.dsp @@ -0,0 +1,167 @@ +# Microsoft Developer Studio Project File - Name="playN" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=playN - 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 "playN.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 "playN.mak" CFG="playN - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "playN - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "playN - 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)" == "playN - 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 "__OS_Win_" /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 winmm.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 dsound.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "playN - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "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 "__OS_Win_" /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 dsound.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# SUBTRACT LINK32 /pdb:none + +!ENDIF + +# Begin Target + +# Name "playN - Win32 Release" +# Name "playN - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\src\ByteSwap.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\Object.cpp +# End Source File +# Begin Source File + +SOURCE=.\playN.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\RtAudio.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\RtWvOut.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\StkError.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\WavWvIn.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\ByteSwap.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\Object.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\RtAudio.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\RtWvOut.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\StkError.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\WavWvIn.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" + +# 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/recordN.cpp b/projects/examples/recordN.cpp new file mode 100644 index 0000000..82ad701 --- /dev/null +++ b/projects/examples/recordN.cpp @@ -0,0 +1,71 @@ +/******************************************/ +/* + Example program to record N channels of data + by Gary P. Scavone, 2000 + + This program is currently written to read + from a realtime audio input device and to + write to a WAV output file. However, it + is simple to replace the instance of + RtWvIn with any other WvIn subclass. + Likewise, WavWvOut can be replaced with any + other WvOut subclass. +*/ +/******************************************/ + +#include "RtWvIn.h" +#include "WavWvOut.h" + +void usage(void) { + /* Error function in case of incorrect command-line + argument specifications + */ + printf("\nuseage: recordN N file time fs \n"); + printf(" where N = number of channels,\n"); + printf(" file = the .wav file to create,\n"); + printf(" time = the amount of time to record (in seconds),\n"); + printf(" and fs = the sample rate.\n\n"); + exit(0); +} + +int main(int argc, char *argv[]) +{ + // minimal command-line checking + if (argc != 5) usage(); + + int chans = (int) atoi(argv[1]); + float sample_rate = atof(argv[4]); + float time = atof(argv[3]); + + // Define and open the realtime input device + WvIn *input; + try { + input = new RtWvIn(chans, sample_rate); + } + catch (StkError& m) { + m.printMessage(); + exit(0); + } + + // Define and open the soundfile for output + WvOut *output; + try { + output = new WavWvOut(argv[2],chans); + } + catch (StkError& m) { + m.printMessage(); + exit(0); + } + + // Here's the runtime loop + int i=0; + int samples = (int) (time*SRATE); + while (imtick(input->mtick()); + i++; + } + + // Clean up + delete input; + delete output; +} diff --git a/projects/examples/recordN.dsp b/projects/examples/recordN.dsp new file mode 100755 index 0000000..0685e4e --- /dev/null +++ b/projects/examples/recordN.dsp @@ -0,0 +1,166 @@ +# Microsoft Developer Studio Project File - Name="recordN" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=recordN - 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 "recordN.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 "recordN.mak" CFG="recordN - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "recordN - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "recordN - 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)" == "recordN - 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 "__OS_Win_" /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 dsound.lib winmm.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "recordN - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "recordN___Win32_Debug" +# PROP BASE Intermediate_Dir "recordN___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 "__OS_Win_" /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 dsound.lib winmm.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "recordN - Win32 Release" +# Name "recordN - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\src\ByteSwap.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\Object.cpp +# End Source File +# Begin Source File + +SOURCE=.\recordN.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\RtAudio.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\RtWvIn.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\StkError.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\WavWvOut.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\ByteSwap.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\Object.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\RtAudio.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\RtWvIn.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\StkError.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\WavWvOut.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" + +# 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/simple.tcl b/projects/examples/simple.tcl new file mode 100644 index 0000000..ea7b2bd --- /dev/null +++ b/projects/examples/simple.tcl @@ -0,0 +1,54 @@ +# A simple Tcl/Tk example script + +# Set initial control values +set pitch 64.0 +set press 64.0 +set outID "stdout" + +# Configure main window +wm title . "A Simple GUI" +wm iconname . "simple" +. config -bg black + +# Configure a "note-on" button +frame .noteOn -bg black + +button .noteOn.on -text NoteOn -bg grey66 -command { noteOn $pitch $press } +pack .noteOn.on -side left -padx 5 +pack .noteOn + +# Configure sliders +frame .slider -bg black + +scale .slider.pitch -from 0 -to 128 -length 200 \ +-command {changePitch } -variable pitch \ +-orient horizontal -label "MIDI Note Number" \ +-tickinterval 32 -showvalue true -bg grey66 + +pack .slider.pitch -padx 10 -pady 10 +pack .slider -side left + +# Bind an X windows "close" event with the Exit routine +bind . +myExit + +proc myExit {} { + global pitch outID + puts $outID [format "NoteOff 0.0 1 %f 127" $pitch ] + flush $outID + puts $outID [format "ExitProgram"] + flush $outID + close $outID + exit +} + +proc noteOn {pitchVal pressVal} { + global outID + puts $outID [format "NoteOn 0.0 1 %f %f" $pitchVal $pressVal] + flush $outID +} + +proc changePitch {value} { + global outID + puts $outID [format "PitchBend 0.0 1 %.3f" $value] + flush $outID +} diff --git a/projects/examples/sineN.cpp b/projects/examples/sineN.cpp new file mode 100644 index 0000000..2f244a2 --- /dev/null +++ b/projects/examples/sineN.cpp @@ -0,0 +1,79 @@ +/******************************************/ +/* + Example program to write N sine tones to + an N channel soundfile + by Gary P. Scavone, 2000 + + This program is currently written to write + an N channel WAV file. However, it is + simple to replace the instance of WavWvOut + with any other WvOut subclass. +*/ +/******************************************/ + +#include "WavWvOut.h" +#include "RawWvIn.h" + +void usage(void) { + /* Error function in case of incorrect command-line + argument specifications + */ + printf("\nuseage: sineN N file time \n"); + printf(" where N = number of channels (sines),\n"); + printf(" file = the .wav file to create,\n"); + printf(" and time = the amount of time to record (in seconds).\n\n"); + exit(0); +} + +int +main(int argc, char *argv[]) +{ + // minimal command-line checking + if (argc != 4) usage(); + + int chans = (int) atoi(argv[1]); + float time = atof(argv[3]); + int i; + + // Define and load the rawwave file(s) ... the path is critical + RawWvIn *oscs[chans]; + try { + for (i=0; isetFreq(base_freq + i*(45.0)); + + // Define and open the soundfile for output + WvOut *output; + try { + output = new WavWvOut(argv[2],chans); + } + catch (StkError& m) { + m.printMessage(); + exit(0); + } + + // Here's the runtime loop + i=0; + int samples = (int) (time*SRATE); + MY_FLOAT *outvec = (MY_FLOAT *) new MY_FLOAT[chans]; + while (itick(); + output->mtick(outvec); + i++; + } + + // Clean up + for (i=0; i +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=sineN - 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 "sineN.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 "sineN.mak" CFG="sineN - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "sineN - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "sineN - 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)" == "sineN - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "sineN___Win32_Release" +# PROP BASE Intermediate_Dir "sineN___Win32_Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "" +# PROP Intermediate_Dir "Release" +# 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 "__OS_Win_" /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 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 + +!ELSEIF "$(CFG)" == "sineN - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "sineN___Win32_Debug" +# PROP BASE Intermediate_Dir "sineN___Win32_Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "" +# PROP Intermediate_Dir "Debug" +# 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 "__OS_Win_" /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 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 + +!ENDIF + +# Begin Target + +# Name "sineN - Win32 Release" +# Name "sineN - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\src\ByteSwap.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\Object.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\RawWvIn.cpp +# End Source File +# Begin Source File + +SOURCE=.\sineN.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\StkError.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\WavWvOut.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\ByteSwap.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\Object.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\RawWvIn.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\StkError.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\WavWvOut.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" + +# 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/streamInN.cpp b/projects/examples/streamInN.cpp new file mode 100644 index 0000000..f3d49ac --- /dev/null +++ b/projects/examples/streamInN.cpp @@ -0,0 +1,73 @@ +/******************************************/ +/* + Example program to read N channels of audio + data that are streamed over an ethernet + connection. + + by Gary P. Scavone, 2000 + + This program is currently written to play + the input data in realtime. However, it + is simple to replace the instance of + RtWvOut with any other WvOut subclass. + + The class StrmWvIn sets up a socket server + and waits for a connection. Thus, this + program needs to be started before the + streaming client. This program will + terminate when the socket connection is + closed. +*/ +/******************************************/ + +#include "Object.h" +#include "StrmWvIn.h" +#include "RtWvOut.h" + +void usage(void) { + /* Error function in case of incorrect command-line + argument specifications + */ + printf("\nuseage: streamInN N fs \n"); + printf(" where N = number of channels,\n"); + printf(" and fs = the sample rate.\n\n"); + exit(0); +} + +int main(int argc, char *argv[]) +{ + // minimal command-line checking + if (argc != 3) usage(); + + int chans = (int) atoi(argv[1]); + + WvIn *input; + try { + input = new StrmWvIn(chans); + } + catch (StkError& m) { + m.printMessage(); + exit(0); + } + // Set playback rate here + input->setRate(atof(argv[2])/SRATE); + + // Define and open the realtime output device + WvOut *output; + try { + output = new RtWvOut(chans); + } + catch (StkError& m) { + m.printMessage(); + exit(0); + } + + // Here's the runtime loop + while (!input->isFinished()) { + output->mtick(input->mtick()); + } + + // Clean up + delete input; + delete output; +} diff --git a/mus151/MUS151.dsp b/projects/examples/streamInN.dsp old mode 100644 new mode 100755 similarity index 52% rename from mus151/MUS151.dsp rename to projects/examples/streamInN.dsp index 3c7b0ea..ab55c57 --- a/mus151/MUS151.dsp +++ b/projects/examples/streamInN.dsp @@ -1,38 +1,39 @@ -# Microsoft Developer Studio Project File - Name="MUS151" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# Microsoft Developer Studio Project File - Name="streamInN" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 -CFG=MUS151 - Win32 Debug +CFG=streamInN - 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 "MUS151.MAK". +!MESSAGE NMAKE /f "streamInN.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 "MUS151.MAK" CFG="MUS151 - Win32 Debug" +!MESSAGE NMAKE /f "streamInN.mak" CFG="streamInN - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE -!MESSAGE "MUS151 - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "MUS151 - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE "streamInN - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "streamInN - 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)" == "MUS151 - Win32 Release" +!IF "$(CFG)" == "streamInN - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "MUS151__" -# PROP BASE Intermediate_Dir "MUS151__" +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 @@ -41,17 +42,17 @@ RSC=rc.exe # 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 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__OS_Win_" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__OS_Win_" /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 /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 dsound.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 winmm.lib Wsock32.lib /nologo /subsystem:console /machine:I386 -!ELSEIF "$(CFG)" == "MUS151 - Win32 Debug" +!ELSEIF "$(CFG)" == "streamInN - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 @@ -64,122 +65,102 @@ 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 /c -# ADD CPP /nologo /MT /W3 /Gm /GX /Zi /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__OS_Win_" /YX /FD /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 "__OS_Win_" /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 /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 dsound.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 winmm.lib Wsock32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept !ENDIF # Begin Target -# Name "MUS151 - Win32 Release" -# Name "MUS151 - Win32 Debug" +# Name "streamInN - Win32 Release" +# Name "streamInN - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File -SOURCE=..\Stk\Envelope.cpp +SOURCE=..\..\src\ByteSwap.cpp # End Source File # Begin Source File -SOURCE=..\Stk\Envelope.h +SOURCE=..\..\src\Object.cpp # End Source File # Begin Source File -SOURCE=.\MUS151.cpp +SOURCE=..\..\src\RtAudio.cpp # End Source File # Begin Source File -SOURCE=..\Stk\Object.cpp +SOURCE=..\..\src\RtWvOut.cpp # End Source File # Begin Source File -SOURCE=..\Stk\Object.h +SOURCE=..\..\src\StkError.cpp # End Source File # Begin Source File -SOURCE=..\Stk\RawWvIn.cpp +SOURCE=.\streamInN.cpp # End Source File # Begin Source File -SOURCE=..\Stk\RawWvIn.h +SOURCE=..\..\src\StrmWvIn.cpp # End Source File # Begin Source File -SOURCE=..\Stk\RTSoundIO.cpp +SOURCE=..\..\src\WvIn.cpp # End Source File # Begin Source File -SOURCE=..\Stk\RTSoundIO.h +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\ByteSwap.h # End Source File # Begin Source File -SOURCE=..\Stk\RTWvOut.cpp +SOURCE=..\..\include\Object.h # End Source File # Begin Source File -SOURCE=..\Stk\RTWvOut.h +SOURCE=..\..\include\RtAudio.h # End Source File # Begin Source File -SOURCE=..\Stk\SKINI11.cpp +SOURCE=..\..\include\RtWvOut.h # End Source File # Begin Source File -SOURCE=..\Stk\SKINI11.h +SOURCE=..\..\include\StkError.h # End Source File # Begin Source File -SOURCE=..\SKINI11.msg +SOURCE=..\..\include\StrmWvIn.h # End Source File # Begin Source File -SOURCE=..\SKINI11.tbl +SOURCE=..\..\include\WvIn.h # End Source File # Begin Source File -SOURCE=..\Stk\swapstuf.cpp +SOURCE=..\..\include\WvOut.h # End Source File -# Begin Source File +# End Group +# Begin Group "Resource Files" -SOURCE=..\Stk\swapstuf.h -# End Source File -# Begin Source File - -SOURCE=.\threads.cpp -# End Source File -# Begin Source File - -SOURCE=.\threads.h -# End Source File -# Begin Source File - -SOURCE=.\TwoOsc.cpp -# End Source File -# Begin Source File - -SOURCE=.\TwoOsc.h -# End Source File -# Begin Source File - -SOURCE=..\Stk\WvIn.cpp -# End Source File -# Begin Source File - -SOURCE=..\Stk\WvIn.h -# End Source File -# Begin Source File - -SOURCE=..\Stk\WvOut.cpp -# End Source File -# Begin Source File - -SOURCE=..\Stk\WvOut.h -# End Source File +# 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/streamOutN.cpp b/projects/examples/streamOutN.cpp new file mode 100644 index 0000000..9240610 --- /dev/null +++ b/projects/examples/streamOutN.cpp @@ -0,0 +1,73 @@ +/******************************************/ +/* + Example program to output N channels of audio + data over an ethernet socket connection. + + by Gary P. Scavone, 2000 + + This program is currently written to load + a WAV file for streaming. However, it is + simple to replace the instance of WavWvIn + with any other WvIn subclass. + + The class StrmWvOut first attempts to + establish a socket connection to a socket + server running on port 2005. Thus, this + program needs to be started after the + streaming server. +*/ +/******************************************/ + +#include "WavWvIn.h" +#include "StrmWvOut.h" + +void usage(void) { + /* Error function in case of incorrect command-line + argument specifications + */ + printf("\nuseage: streamOutN N file host fs \n"); + printf(" where N = number of channels,\n"); + printf(" file = the .wav file to load,\n"); + printf(" host = the hostname of the receiving app,\n"); + printf(" and fs = the sample rate.\n\n"); + exit(0); +} + +int main(int argc, char *argv[]) +{ + // minimal command-line checking + if (argc != 5) usage(); + + int chans = (int) atoi(argv[1]); + + // Define and load the SND soundfile + WvIn *input; + try { + input = new WavWvIn((char *)argv[2], "oneshot"); + } + catch (StkError& m) { + m.printMessage(); + exit(0); + } + // Set playback rate here + input->setRate(atof(argv[4])/SRATE); + + // Define and open the realtime output device + WvOut *output; + try { + output = new StrmWvOut(2005, (char *)argv[3], chans); + } + catch (StkError& m) { + m.printMessage(); + exit(0); + } + + // Here's the runtime loop + while (!input->isFinished()) { + output->mtick(input->mtick()); + } + + // Clean up + delete input; + delete output; +} diff --git a/projects/examples/streamOutN.dsp b/projects/examples/streamOutN.dsp new file mode 100755 index 0000000..985b1b8 --- /dev/null +++ b/projects/examples/streamOutN.dsp @@ -0,0 +1,158 @@ +# Microsoft Developer Studio Project File - Name="streamOutN" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=streamOutN - 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 "streamOutN.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 "streamOutN.mak" CFG="streamOutN - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "streamOutN - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "streamOutN - 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)" == "streamOutN - 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 "__OS_Win_" /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)" == "streamOutN - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "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 "__OS_Win_" /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 "streamOutN - Win32 Release" +# Name "streamOutN - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\src\ByteSwap.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\Object.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\StkError.cpp +# End Source File +# Begin Source File + +SOURCE=.\streamOutN.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\StrmWvOut.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\WavWvIn.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\ByteSwap.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\Object.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\StkError.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\StrmWvOut.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\WavWvIn.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" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/ragamatic/GUIRaga b/projects/ragamatic/GUIRaga similarity index 100% rename from ragamatic/GUIRaga rename to projects/ragamatic/GUIRaga diff --git a/ragamatic/Makefile b/projects/ragamatic/Makefile similarity index 59% rename from ragamatic/Makefile rename to projects/ragamatic/Makefile index 251fbf9..a2a3c1e 100644 --- a/ragamatic/Makefile +++ b/projects/ragamatic/Makefile @@ -7,41 +7,40 @@ OS = $(shell uname) # The following definition indicates the relative location of # the core STK classes. -STK_PATH = ../STK/ +STK_PATH = ../../src/ O_FILES = Object.o Envelope.o ADSR.o Noise.o \ - Filter.o DLineA.o DLineL.o DLineN.o \ - OnePole.o OneZero.o DCBlock.o SKINI11.o \ - swapstuf.o Tabla.o Instrmnt.o Sitar1.o \ - StrDrone.o VoicDrum.o WvOut.o WvIn.o RawWvIn.o \ - RTSoundIO.o RTWvOut.o MIDIIO.o Reverb.o \ - NRev.o JCRev.o PRCRev.o threads.o + Filter.o DLineA.o DLineL.o DLineN.o \ + OnePole.o OneZero.o DCBlock.o SKINI11.o \ + ByteSwap.o Tabla.o Instrmnt.o Sitar1.o \ + StrDrone.o VoicDrum.o WvOut.o WvIn.o RawWvIn.o \ + RtAudio.o RtWvOut.o RtMidi.o Reverb.o \ + JCRev.o Controller.o StkError.o RM = /bin/rm ifeq ($(OS),IRIX) # These are for SGI - INSTR = ragamat MD2SKINI + INSTR = ragamat CC = CC -O2 -D__OS_IRIX_ # -g -fullwarn -D__SGI_CC__ LIBRARY = -L/usr/sgitcl/lib -laudio -lmd -lm -lpthread + INCLUDE = -I../../include endif ifeq ($(OS),Linux) # These are for Linux - INSTR = ragamat MD2SKINI + INSTR = ragamat CC = g++ -O3 -Wall -D__OS_Linux_ # -g - LIBRARY = -lpthread -lm + LIBRARY = -lpthread -lm #-lasound + INCLUDE = -I../../include endif %.o : $(STK_PATH)%.cpp - $(CC) -c $(<) -o $@ + $(CC) $(INCLUDE) -c $(<) -o $@ all: $(INSTR) ragamat: ragamat.cpp $(O_FILES) $(CC) $(INCLUDE) -o ragamat ragamat.cpp $(O_FILES) $(LIBRARY) -MD2SKINI: $(STK_PATH)MD2SKINI.cpp Object.o MIDIIO.o - $(CC) -o MD2SKINI $(STK_PATH)MD2SKINI.cpp Object.o MIDIIO.o $(LIBRARY) - clean : rm *.o rm $(INSTR) @@ -54,17 +53,14 @@ strip : # $(O_FILES) : -threads.o: threads.cpp - $(CC) -c threads.cpp - Tabla.o: Tabla.cpp - $(CC) -c Tabla.cpp + $(CC) $(INCLUDE) -c Tabla.cpp Sitar1.o: Sitar1.cpp - $(CC) -c Sitar1.cpp + $(CC) $(INCLUDE) -c Sitar1.cpp StrDrone.o: StrDrone.cpp - $(CC) -c StrDrone.cpp + $(CC) $(INCLUDE) -c StrDrone.cpp VoicDrum.o: VoicDrum.cpp - $(CC) -c VoicDrum.cpp \ No newline at end of file + $(CC) $(INCLUDE) -c VoicDrum.cpp \ No newline at end of file diff --git a/projects/ragamatic/Makefile.sgi b/projects/ragamatic/Makefile.sgi new file mode 100644 index 0000000..d0eb4be --- /dev/null +++ b/projects/ragamatic/Makefile.sgi @@ -0,0 +1,58 @@ +# STK Makefile for RagaMatic project- SGI solo version (non-GNU Makefile utilities version) + +# The following definition indicates the relative location of +# the core STK classes. +STK_PATH = ../../src/ + +O_FILES = $(STK_PATH)Object.o $(STK_PATH)Envelope.o $(STK_PATH)ADSR.o \ + $(STK_PATH)Filter.o $(STK_PATH)DLineL.o $(STK_PATH)DLineN.o \ + $(STK_PATH)ByteSwap.o $(STK_PATH)Noise.o $(STK_PATH)OnePole.o \ + $(STK_PATH)OneZero.o $(STK_PATH)DCBlock.o $(STK_PATH)SKINI11.o \ + $(STK_PATH)Instrmnt.o $(STK_PATH)WvIn.o $(STK_PATH)RawWvIn.o \ + $(STK_PATH)DLineA.o $(STK_PATH)Reverb.o $(STK_PATH)JCRev.o \ + $(STK_PATH)WvOut.o $(STK_PATH)RtAudio.o $(STK_PATH)RtMidi.o \ + $(STK_PATH)RtWvOut.o $(STK_PATH)StkError.o $(STK_PATH)Controller.o + +O_LOCAL_FILES = Tabla.o Sitar1.o StrDrone.o VoicDrum.o + +RM = /bin/rm + +INSTR = ragamat +CC = CC -O2 -D__OS_IRIX_ # -g -fullwarn -D__SGI_CC__ +LIBRARY = -L/usr/sgitcl/lib -laudio -lmd -lm -lpthread +INCLUDE = -I../../include/ + +.SUFFIXES: .cpp +.cpp.o: $(O_FILES) + $(CC) $(INCLUDE) -c -o $@ $< + +all: $(INSTR) + +ragamat: ragamat.cpp $(O_FILES) $(O_LOCAL_FILES) + $(CC) -o ragamat ragamat.cpp $(O_FILES) $(O_LOCAL_FILES) $(LIBRARY) $(INCLUDE) + +clean : + rm *.o + rm $(STK_PATH)*.o + rm $(INSTR) + +cleanIns : + rm $(INSTR) + +strip : + strip $(INSTR) + +# $(O_FILES) : + +Tabla.o: Tabla.cpp + $(CC) $(INCLUDE) -c Tabla.cpp + +Sitar1.o: Sitar1.cpp + $(CC) $(INCLUDE) -c Sitar1.cpp + +StrDrone.o: StrDrone.cpp + $(CC) $(INCLUDE) -c StrDrone.cpp + +VoicDrum.o: VoicDrum.cpp + $(CC) $(INCLUDE) -c VoicDrum.cpp + diff --git a/ragamatic/README-raga.txt b/projects/ragamatic/README-raga.txt similarity index 100% rename from ragamatic/README-raga.txt rename to projects/ragamatic/README-raga.txt diff --git a/ragamatic/Sitar1.cpp b/projects/ragamatic/Sitar1.cpp similarity index 100% rename from ragamatic/Sitar1.cpp rename to projects/ragamatic/Sitar1.cpp diff --git a/ragamatic/Sitar1.h b/projects/ragamatic/Sitar1.h similarity index 86% rename from ragamatic/Sitar1.h rename to projects/ragamatic/Sitar1.h index 10cca20..65ce232 100644 --- a/ragamatic/Sitar1.h +++ b/projects/ragamatic/Sitar1.h @@ -10,11 +10,11 @@ #if !defined(__Sitar1_h) #define __Sitar1_h -#include "../STK/Instrmnt.h" -#include "../STK/DLineA.h" -#include "../STK/OneZero.h" -#include "../STK/ADSR.h" -#include "../STK/Noise.h" +#include "Instrmnt.h" +#include "DLineA.h" +#include "OneZero.h" +#include "ADSR.h" +#include "Noise.h" class Sitar1 : public Instrmnt { diff --git a/ragamatic/StrDrone.cpp b/projects/ragamatic/StrDrone.cpp similarity index 100% rename from ragamatic/StrDrone.cpp rename to projects/ragamatic/StrDrone.cpp diff --git a/ragamatic/StrDrone.h b/projects/ragamatic/StrDrone.h similarity index 86% rename from ragamatic/StrDrone.h rename to projects/ragamatic/StrDrone.h index 4e7c062..78a2ae7 100644 --- a/ragamatic/StrDrone.h +++ b/projects/ragamatic/StrDrone.h @@ -10,11 +10,11 @@ #if !defined(__StrDrone_h) #define __StrDrone_h -#include "../STK/Instrmnt.h" -#include "../STK/DLineA.h" -#include "../STK/OneZero.h" -#include "../STK/ADSR.h" -#include "../STK/Noise.h" +#include "Instrmnt.h" +#include "DLineA.h" +#include "OneZero.h" +#include "ADSR.h" +#include "Noise.h" class StrDrone : public Instrmnt { diff --git a/ragamatic/Tabla.cpp b/projects/ragamatic/Tabla.cpp similarity index 100% rename from ragamatic/Tabla.cpp rename to projects/ragamatic/Tabla.cpp diff --git a/ragamatic/Tabla.h b/projects/ragamatic/Tabla.h similarity index 93% rename from ragamatic/Tabla.h rename to projects/ragamatic/Tabla.h index 5a7102d..ade6d3f 100644 --- a/ragamatic/Tabla.h +++ b/projects/ragamatic/Tabla.h @@ -22,9 +22,9 @@ #if !defined(__Tabla_h) #define __Tabla_h -#include "../STK/Instrmnt.h" -#include "../STK/RawWvIn.h" -#include "../STK/OnePole.h" +#include "Instrmnt.h" +#include "RawWvIn.h" +#include "OnePole.h" #define TABLA_NUMWAVES 15 #define TABLA_POLYPHONY 4 diff --git a/ragamatic/VoicDrum.cpp b/projects/ragamatic/VoicDrum.cpp similarity index 100% rename from ragamatic/VoicDrum.cpp rename to projects/ragamatic/VoicDrum.cpp diff --git a/ragamatic/VoicDrum.h b/projects/ragamatic/VoicDrum.h similarity index 93% rename from ragamatic/VoicDrum.h rename to projects/ragamatic/VoicDrum.h index 103d477..783e829 100644 --- a/ragamatic/VoicDrum.h +++ b/projects/ragamatic/VoicDrum.h @@ -22,9 +22,9 @@ #if !defined(__VoicDrum_h) #define __VoicDrum_h -#include "../STK/Instrmnt.h" -#include "../STK/RawWvIn.h" -#include "../STK/OnePole.h" +#include "Instrmnt.h" +#include "RawWvIn.h" +#include "OnePole.h" #define DRUM_NUMWAVES 11 #define DRUM_POLYPHONY 4 diff --git a/ragamatic/ragamat.cpp b/projects/ragamatic/ragamat.cpp similarity index 51% rename from ragamatic/ragamat.cpp rename to projects/ragamatic/ragamat.cpp index 7b18d6a..aa74e7f 100644 --- a/ragamatic/ragamat.cpp +++ b/projects/ragamatic/ragamat.cpp @@ -1,14 +1,10 @@ /************** Test Main Program Individual Voice *********************/ -#include "../STK/WvOut.h" -#include "../STK/RTWvOut.h" -#include "../STK/SKINI11.h" -#include "../STK/SKINI11.msg" -#include "../STK/Instrmnt.h" -#include "../STK/Reverb.h" -#include "../STK/NRev.h" -#include "../STK/PRCRev.h" -#include "../STK/JCRev.h" +#include "RtWvOut.h" +#include "SKINI11.msg" +#include "Instrmnt.h" +#include "Reverb.h" +#include "JCRev.h" #include "StrDrone.h" #include "Sitar1.h" #include "Tabla.h" @@ -17,12 +13,8 @@ #define RATE_NORM (MY_FLOAT) (22050.0/SRATE) -int numStrings = 0; -int notDone = 1; -char **inputString; - -// The input command pipe and socket threads are defined in threads.cpp. -#include "threads.h" +// The input control handler. +#include "Controller.h" // Return random float between 0.0 and max MY_FLOAT float_random(MY_FLOAT max) { @@ -48,10 +40,13 @@ void usage(void) { int main(int argc,char *argv[]) { - long i, j, synlength; - int type, outOne = 0, useSocket = 0; - MY_FLOAT reverbTime = 5.0; /* in seconds */ - MY_FLOAT byte3, outSample, temp; + long i, nTicks; + int type; + MY_FLOAT byte2, byte3, temp; + MY_FLOAT outSamples[2]; + int controlMask = 0; + bool done; + MY_FLOAT reverbTime = 4.0; /* in seconds */ MY_FLOAT drone_prob = 0.01, note_prob = 0.0; MY_FLOAT drum_prob = 0.0, voic_prob = 0.0; MY_FLOAT droneFreqs[3] = {55.0,82.5,220.0}; @@ -63,23 +58,34 @@ int main(int argc,char *argv[]) {52, 54, 55, 57, 59, 60, 63, 64, 66, 67, 71, 72}}; int ragaDown[2][13] = {{57, 60, 62, 64, 65, 67, 69, 71, 72, 76, 79, 81}, {48, 52, 53, 55, 57, 59, 60, 64, 66, 68, 70, 72}}; - WvOut *output; + RtWvOut *output; Instrmnt *drones[3]; Instrmnt *sitar; Instrmnt *voicDrums; Instrmnt *drums; Reverb *reverbs[2]; SKINI11 *score; + Controller *controller; if (argc != 2) usage(); if (!strcmp(argv[1],"-is") ) - useSocket = 1; - else if (strcmp(argv[1],"-ip")) { + controlMask |= STK_SOCKET; + else if (!strcmp(argv[1],"-ip") ) + controlMask |= STK_PIPE; + else usage(); - } + + try { + output = new RtWvOut(2); - output = new RTWvOut(SRATE,1); + // Instantiate the input message controller. + controller = new Controller( controlMask ); + } + catch (StkError& m) { + m.printMessage(); + exit(0); + } drones[0] = new StrDrone(50.0); drones[1] = new StrDrone(50.0); @@ -94,36 +100,36 @@ int main(int argc,char *argv[]) reverbs[1] = new JCRev(2.0); reverbs[1]->setEffectMix(0.2); - // Start the input thread - if (useSocket) - startSocketThread(); - else - startPipeThread(); - drones[0]->noteOn(droneFreqs[0],0.1); drones[1]->noteOn(droneFreqs[1],0.1); drones[2]->noteOn(droneFreqs[2],0.1); for (i=0;itick(); - output->tick(reverbs[0]->tick(outSample)); + outSamples[0] = reverbs[0]->tick(drones[0]->tick() + drones[2]->tick()); + outSamples[1] = reverbs[1]->tick(1.5 * drones[1]->tick()); + output->mtick(outSamples); } - /* Finally ... the runtime loop begins! */ - notDone = 1; - synlength = RT_BUFFER_SIZE; - while(notDone || numStrings) { - if (numStrings > 1) synlength = (long) RT_BUFFER_SIZE / numStrings; - else synlength = RT_BUFFER_SIZE; - for ( i=0; itick(); - outSample -= sitar->tick(); - output->tick(reverbs[0]->tick(outSample) - + reverbs[1]->tick(voicDrums->tick() + drums->tick())); + // The runtime loop begins here: + done = FALSE; + while (!done) { + + nTicks = controller->getNextMessage(); + + if (nTicks == -1) + done = TRUE; + + for (i=0; itick(drones[0]->tick() + drones[2]->tick() + + sitar->tick()); + outSamples[1] = reverbs[1]->tick(1.5 * drones[1]->tick() + 0.5 * voicDrums->tick() + + 0.5 * drums->tick()); + // mix a little left to right and back + temp = outSamples[0]; + outSamples[0] += 0.3 * outSamples[1]; + outSamples[1] += 0.3 * temp; + output->mtick(outSamples); + counter -= 1; if (counter == 0) { counter = (int) (tempo / RATE_NORM); @@ -146,105 +152,100 @@ int main(int argc,char *argv[]) if (ragaPoint > 11) ragaPoint = 11; if (ragaStep > 0) - sitar->noteOn(__MIDI_To_Pitch[ragaUp[key][ragaPoint]] - ,0.05 + float_random(0.3)); + sitar->noteOn(__MIDI_To_Pitch[ragaUp[key][ragaPoint]], + 0.05 + float_random(0.3)); else - sitar->noteOn(__MIDI_To_Pitch[ragaDown[key][ragaPoint]] - ,0.05 + float_random(0.3)); + sitar->noteOn(__MIDI_To_Pitch[ragaDown[key][ragaPoint]], + 0.05 + float_random(0.3)); } if (float_random(1.0) < voic_prob) { voicNote = (int) float_random(11); - voicDrums->noteOn(voicNote,0.3 + (0.4 * drum_prob) + + voicDrums->noteOn(voicNote, 0.3 + (0.4 * drum_prob) + float_random(0.9 * voic_prob)); } if (float_random(1.0) < drum_prob) { voicNote = (int) float_random(TABLA_NUMWAVES); - drums->noteOn(voicNote,0.2 + (0.2 * drum_prob) + + drums->noteOn(voicNote, 0.2 + (0.2 * drum_prob) + float_random(0.7 * drum_prob)); } } } - if (numStrings) { - score->parseThis(inputString[outOne]); - type = score->getType(); - if (type > 0) { - if (type == __SK_ControlChange_) { - j = (int) score->getByteTwo(); - byte3 = score->getByteThree(); - if (j == 1) { - drone_prob = byte3 * NORM_7; + + type = controller->getType(); + if (type > 0) { + // parse the input control message + + byte2 = controller->getByte2(); + byte3 = controller->getByte3(); + + switch(type) { + + case __SK_ControlChange_: + if (byte2 == 1) { + drone_prob = byte3 * NORM_7; + } + else if (byte2 == 2) { + note_prob = byte3 * NORM_7; + } + else if (byte2 == 4) { + voic_prob = byte3 * NORM_7; + } + else if (byte2 == 11) { + drum_prob = byte3 * NORM_7; + } + else if (byte2 == 7) { + tempo = (int) (11025 - (byte3 * 70)); + } + else if (byte2 == 64) { + if (byte3 == 0) { + key = 1; + droneFreqs[0] = 55.0; + droneFreqs[1] = 82.5; + droneFreqs[2] = 220.0; } - else if (j == 2) { - note_prob = byte3 * NORM_7; - } - else if (j == 4) { - voic_prob = byte3 * NORM_7; - } - else if (j == 11) { - drum_prob = byte3 * NORM_7; - } - else if (j == 7) { - tempo = (int) (11025 - (byte3 * 70)); - } - else if (j == 64) { - if (byte3 == 0) { - key = 1; - droneFreqs[0] = 55.0; - droneFreqs[1] = 82.5; - droneFreqs[2] = 220.0; - } - else { - key = 0; - droneFreqs[0] = 82.5; - droneFreqs[1] = 123.5; - droneFreqs[2] = 330.0; - } + else { + key = 0; + droneFreqs[0] = 82.5; + droneFreqs[1] = 123.5; + droneFreqs[2] = 330.0; } } } - outOne += 1; - if (outOne == MAX_IN_STRINGS) outOne = 0; - numStrings--; } } printf("What Need Have I for This?\n"); drones[1]->noteOn(droneFreqs[1],0.1); - for (i=0;itick(); - output->tick(reverbs[0]->tick(outSample)); + for (i=0; itick(drones[0]->tick() + drones[2]->tick()); + outSamples[1] = reverbs[1]->tick(1.5 * drones[1]->tick()); + output->mtick(outSamples); } printf("What Need Have I for This?\n"); drones[2]->noteOn(droneFreqs[2],0.1); - for (i=0;itick(); - output->tick(reverbs[0]->tick(outSample)); + for (i=0; itick(drones[0]->tick() + drones[2]->tick()); + outSamples[1] = reverbs[1]->tick(1.5 * drones[1]->tick()); + output->mtick(outSamples); } printf("RagaMatic finished ... \n"); drones[0]->noteOn(droneFreqs[0],0.1); - for (i=0;itick(); - output->tick(reverbs[0]->tick(outSample)); + for (i=0; itick(drones[0]->tick() + drones[2]->tick()); + outSamples[1] = reverbs[1]->tick(1.5 * drones[1]->tick()); + output->mtick(outSamples); } printf("All is Bliss ...\n"); - for (i=0;itick(); - output->tick(reverbs[0]->tick(outSample)); + for (i=0; itick(drones[0]->tick() + drones[2]->tick()); + outSamples[1] = reverbs[1]->tick(1.5 * drones[1]->tick()); + output->mtick(outSamples); } printf("All is Bliss ...\n"); - for (i=0;itick(); - output->tick(reverbs[0]->tick(outSample)); + for (i=0; itick(drones[0]->tick() + drones[2]->tick()); + outSamples[1] = reverbs[1]->tick(1.5 * drones[1]->tick()); + output->mtick(outSamples); } delete output; @@ -257,6 +258,7 @@ int main(int argc,char *argv[]) delete voicDrums; delete reverbs[0]; delete reverbs[1]; + delete controller; return 0; } diff --git a/ragamatic/ragamat.dsp b/projects/ragamatic/ragamat.dsp similarity index 69% rename from ragamatic/ragamat.dsp rename to projects/ragamatic/ragamat.dsp index b31e8a0..c389f61 100755 --- a/ragamatic/ragamat.dsp +++ b/projects/ragamatic/ragamat.dsp @@ -1,5 +1,5 @@ # Microsoft Developer Studio Project File - Name="ragamatic" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 @@ -17,12 +17,12 @@ CFG=ragamatic - Win32 Debug !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE -!MESSAGE "ragamatic - Win32 Release" (based on\ - "Win32 (x86) Console Application") +!MESSAGE "ragamatic - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "ragamatic - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project +# PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe @@ -42,7 +42,7 @@ RSC=rc.exe # 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 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__OS_Win_" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__OS_Win_" /YX /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe @@ -66,7 +66,7 @@ LINK32=link.exe # 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 /c -# ADD CPP /nologo /MT /W3 /Gm /GX /Zi /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__OS_Win_" /YX /FD /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__OS_Win_" /YX /FD /c # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe @@ -84,115 +84,131 @@ LINK32=link.exe # Name "ragamatic - Win32 Debug" # Begin Source File -SOURCE=..\Stk\ADSR.cpp +SOURCE=..\..\src\ADSR.cpp # End Source File # Begin Source File -SOURCE=..\Stk\ADSR.h +SOURCE=..\..\include\ADSR.h # End Source File # Begin Source File -SOURCE=..\Stk\DLineA.cpp +SOURCE=..\..\src\ByteSwap.cpp # End Source File # Begin Source File -SOURCE=..\Stk\DLineA.h +SOURCE=..\..\include\ByteSwap.h # End Source File # Begin Source File -SOURCE=..\Stk\DLineL.cpp +SOURCE=..\..\src\Controller.cpp # End Source File # Begin Source File -SOURCE=..\Stk\DLineL.h +SOURCE=..\..\include\Controller.h # End Source File # Begin Source File -SOURCE=..\Stk\DLineN.cpp +SOURCE=..\..\src\DLineA.cpp # End Source File # Begin Source File -SOURCE=..\Stk\DLineN.h +SOURCE=..\..\include\DLineA.h # End Source File # Begin Source File -SOURCE=..\Stk\Envelope.cpp +SOURCE=..\..\src\DLineL.cpp # End Source File # Begin Source File -SOURCE=..\Stk\Envelope.h +SOURCE=..\..\include\DLineL.h # End Source File # Begin Source File -SOURCE=..\Stk\Filter.cpp +SOURCE=..\..\src\DLineN.cpp # End Source File # Begin Source File -SOURCE=..\Stk\Filter.h +SOURCE=..\..\include\DLineN.h # End Source File # Begin Source File -SOURCE=..\Stk\Instrmnt.cpp +SOURCE=..\..\src\Envelope.cpp # End Source File # Begin Source File -SOURCE=..\Stk\Instrmnt.h +SOURCE=..\..\include\Envelope.h # End Source File # Begin Source File -SOURCE=..\Stk\JCRev.cpp +SOURCE=..\..\src\Filter.cpp # End Source File # Begin Source File -SOURCE=..\Stk\JCRev.h +SOURCE=..\..\include\Filter.h # End Source File # Begin Source File -SOURCE=..\Stk\Noise.cpp +SOURCE=..\..\src\Instrmnt.cpp # End Source File # Begin Source File -SOURCE=..\Stk\Noise.h +SOURCE=..\..\include\Instrmnt.h # End Source File # Begin Source File -SOURCE=..\Stk\NRev.cpp +SOURCE=..\..\src\JCRev.cpp # End Source File # Begin Source File -SOURCE=..\Stk\NRev.h +SOURCE=..\..\include\JCRev.h # End Source File # Begin Source File -SOURCE=..\Stk\Object.cpp +SOURCE=..\..\src\Noise.cpp # End Source File # Begin Source File -SOURCE=..\Stk\Object.h +SOURCE=..\..\include\Noise.h # End Source File # Begin Source File -SOURCE=..\Stk\OnePole.cpp +SOURCE=..\..\src\NRev.cpp # End Source File # Begin Source File -SOURCE=..\Stk\OnePole.h +SOURCE=..\..\include\NRev.h # End Source File # Begin Source File -SOURCE=..\Stk\OneZero.cpp +SOURCE=..\..\src\Object.cpp # End Source File # Begin Source File -SOURCE=..\Stk\OneZero.h +SOURCE=..\..\include\Object.h # End Source File # Begin Source File -SOURCE=..\Stk\PRCRev.cpp +SOURCE=..\..\src\OnePole.cpp # End Source File # Begin Source File -SOURCE=..\Stk\PRCRev.h +SOURCE=..\..\include\OnePole.h +# End Source File +# Begin Source File + +SOURCE=..\..\src\OneZero.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\include\OneZero.h +# End Source File +# Begin Source File + +SOURCE=..\..\src\PRCRev.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\include\PRCRev.h # End Source File # Begin Source File @@ -200,35 +216,43 @@ SOURCE=.\ragamat.cpp # End Source File # Begin Source File -SOURCE=..\Stk\RawWvIn.cpp +SOURCE=..\..\src\RawWvIn.cpp # End Source File # Begin Source File -SOURCE=..\Stk\RawWvIn.h +SOURCE=..\..\include\RawWvIn.h # End Source File # Begin Source File -SOURCE=..\Stk\Reverb.cpp +SOURCE=..\..\src\Reverb.cpp # End Source File # Begin Source File -SOURCE=..\Stk\Reverb.h +SOURCE=..\..\include\Reverb.h # End Source File # Begin Source File -SOURCE=..\Stk\RTSoundIO.cpp +SOURCE=..\..\src\RtAudio.cpp # End Source File # Begin Source File -SOURCE=..\Stk\RTSoundIO.h +SOURCE=..\..\include\RtAudio.h # End Source File # Begin Source File -SOURCE=..\Stk\RTWvOut.cpp +SOURCE=..\..\src\RtMidi.cpp # End Source File # Begin Source File -SOURCE=..\Stk\RTWvOut.h +SOURCE=..\..\include\RtMidi.h +# End Source File +# Begin Source File + +SOURCE=..\..\src\RtWvOut.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\include\RtWvOut.h # End Source File # Begin Source File @@ -240,11 +264,19 @@ SOURCE=.\Sitar1.h # End Source File # Begin Source File -SOURCE=..\Stk\SKINI11.cpp +SOURCE=..\..\src\SKINI11.cpp # End Source File # Begin Source File -SOURCE=..\Stk\SKINI11.h +SOURCE=..\..\include\SKINI11.h +# End Source File +# Begin Source File + +SOURCE=..\..\src\StkError.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\include\StkError.h # End Source File # Begin Source File @@ -256,14 +288,6 @@ SOURCE=.\StrDrone.h # End Source File # Begin Source File -SOURCE=..\Stk\swapstuf.cpp -# End Source File -# Begin Source File - -SOURCE=..\Stk\swapstuf.h -# End Source File -# Begin Source File - SOURCE=.\Tabla.cpp # End Source File # Begin Source File @@ -272,14 +296,6 @@ SOURCE=.\Tabla.h # End Source File # Begin Source File -SOURCE=.\threads.cpp -# End Source File -# Begin Source File - -SOURCE=.\threads.h -# End Source File -# Begin Source File - SOURCE=.\VoicDrum.cpp # End Source File # Begin Source File @@ -288,19 +304,19 @@ SOURCE=.\VoicDrum.h # End Source File # Begin Source File -SOURCE=..\Stk\WvIn.cpp +SOURCE=..\..\src\WvIn.cpp # End Source File # Begin Source File -SOURCE=..\Stk\WvIn.h +SOURCE=..\..\include\WvIn.h # End Source File # Begin Source File -SOURCE=..\Stk\WvOut.cpp +SOURCE=..\..\src\WvOut.cpp # End Source File # Begin Source File -SOURCE=..\Stk\WvOut.h +SOURCE=..\..\include\WvOut.h # End Source File # End Target # End Project diff --git a/mus151/MUS151.dsw b/projects/ragamatic/ragamatic.dsw old mode 100644 new mode 100755 similarity index 72% rename from mus151/MUS151.dsw rename to projects/ragamatic/ragamatic.dsw index 5020f16..9708f17 --- a/mus151/MUS151.dsw +++ b/projects/ragamatic/ragamatic.dsw @@ -1,9 +1,9 @@ -Microsoft Developer Studio Workspace File, Format Version 5.00 +Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### -Project: "MUS151"=.\MUS151.DSP - Package Owner=<4> +Project: "ragamatic"=.\ragamat.dsp - Package Owner=<4> Package=<5> {{{ diff --git a/ragamatic/rawwaves/DrDoi1.raw b/projects/ragamatic/rawwaves/DrDoi1.raw similarity index 100% rename from ragamatic/rawwaves/DrDoi1.raw rename to projects/ragamatic/rawwaves/DrDoi1.raw diff --git a/ragamatic/rawwaves/DrDoi2.raw b/projects/ragamatic/rawwaves/DrDoi2.raw similarity index 100% rename from ragamatic/rawwaves/DrDoi2.raw rename to projects/ragamatic/rawwaves/DrDoi2.raw diff --git a/ragamatic/rawwaves/DrTak1.raw b/projects/ragamatic/rawwaves/DrTak1.raw similarity index 100% rename from ragamatic/rawwaves/DrTak1.raw rename to projects/ragamatic/rawwaves/DrTak1.raw diff --git a/ragamatic/rawwaves/DrTak2.raw b/projects/ragamatic/rawwaves/DrTak2.raw similarity index 100% rename from ragamatic/rawwaves/DrTak2.raw rename to projects/ragamatic/rawwaves/DrTak2.raw diff --git a/ragamatic/rawwaves/Drdak2.raw b/projects/ragamatic/rawwaves/Drdak2.raw similarity index 100% rename from ragamatic/rawwaves/Drdak2.raw rename to projects/ragamatic/rawwaves/Drdak2.raw diff --git a/ragamatic/rawwaves/Drdak3.raw b/projects/ragamatic/rawwaves/Drdak3.raw similarity index 100% rename from ragamatic/rawwaves/Drdak3.raw rename to projects/ragamatic/rawwaves/Drdak3.raw diff --git a/ragamatic/rawwaves/Drdak4.raw b/projects/ragamatic/rawwaves/Drdak4.raw similarity index 100% rename from ragamatic/rawwaves/Drdak4.raw rename to projects/ragamatic/rawwaves/Drdak4.raw diff --git a/ragamatic/rawwaves/Drddak1.raw b/projects/ragamatic/rawwaves/Drddak1.raw similarity index 100% rename from ragamatic/rawwaves/Drddak1.raw rename to projects/ragamatic/rawwaves/Drddak1.raw diff --git a/ragamatic/rawwaves/Drdee1.raw b/projects/ragamatic/rawwaves/Drdee1.raw similarity index 100% rename from ragamatic/rawwaves/Drdee1.raw rename to projects/ragamatic/rawwaves/Drdee1.raw diff --git a/ragamatic/rawwaves/Drdee2.raw b/projects/ragamatic/rawwaves/Drdee2.raw similarity index 100% rename from ragamatic/rawwaves/Drdee2.raw rename to projects/ragamatic/rawwaves/Drdee2.raw diff --git a/ragamatic/rawwaves/Drdoo1.raw b/projects/ragamatic/rawwaves/Drdoo1.raw similarity index 100% rename from ragamatic/rawwaves/Drdoo1.raw rename to projects/ragamatic/rawwaves/Drdoo1.raw diff --git a/ragamatic/rawwaves/Drdoo2.raw b/projects/ragamatic/rawwaves/Drdoo2.raw similarity index 100% rename from ragamatic/rawwaves/Drdoo2.raw rename to projects/ragamatic/rawwaves/Drdoo2.raw diff --git a/ragamatic/rawwaves/Drdoo3.raw b/projects/ragamatic/rawwaves/Drdoo3.raw similarity index 100% rename from ragamatic/rawwaves/Drdoo3.raw rename to projects/ragamatic/rawwaves/Drdoo3.raw diff --git a/ragamatic/rawwaves/Drjun1.raw b/projects/ragamatic/rawwaves/Drjun1.raw similarity index 100% rename from ragamatic/rawwaves/Drjun1.raw rename to projects/ragamatic/rawwaves/Drjun1.raw diff --git a/ragamatic/rawwaves/Drjun2.raw b/projects/ragamatic/rawwaves/Drjun2.raw similarity index 100% rename from ragamatic/rawwaves/Drjun2.raw rename to projects/ragamatic/rawwaves/Drjun2.raw diff --git a/ragamatic/rawwaves/ahh.raw b/projects/ragamatic/rawwaves/ahh.raw similarity index 100% rename from ragamatic/rawwaves/ahh.raw rename to projects/ragamatic/rawwaves/ahh.raw diff --git a/ragamatic/rawwaves/bassdrum.raw b/projects/ragamatic/rawwaves/bassdrum.raw similarity index 100% rename from ragamatic/rawwaves/bassdrum.raw rename to projects/ragamatic/rawwaves/bassdrum.raw diff --git a/ragamatic/rawwaves/bee1.raw b/projects/ragamatic/rawwaves/bee1.raw similarity index 100% rename from ragamatic/rawwaves/bee1.raw rename to projects/ragamatic/rawwaves/bee1.raw diff --git a/ragamatic/rawwaves/britestk.raw b/projects/ragamatic/rawwaves/britestk.raw similarity index 100% rename from ragamatic/rawwaves/britestk.raw rename to projects/ragamatic/rawwaves/britestk.raw diff --git a/ragamatic/rawwaves/cowbell1.raw b/projects/ragamatic/rawwaves/cowbell1.raw similarity index 100% rename from ragamatic/rawwaves/cowbell1.raw rename to projects/ragamatic/rawwaves/cowbell1.raw diff --git a/ragamatic/rawwaves/dee1.raw b/projects/ragamatic/rawwaves/dee1.raw similarity index 100% rename from ragamatic/rawwaves/dee1.raw rename to projects/ragamatic/rawwaves/dee1.raw diff --git a/ragamatic/rawwaves/dee2.raw b/projects/ragamatic/rawwaves/dee2.raw similarity index 100% rename from ragamatic/rawwaves/dee2.raw rename to projects/ragamatic/rawwaves/dee2.raw diff --git a/ragamatic/rawwaves/din1.raw b/projects/ragamatic/rawwaves/din1.raw similarity index 100% rename from ragamatic/rawwaves/din1.raw rename to projects/ragamatic/rawwaves/din1.raw diff --git a/ragamatic/rawwaves/fwavblnk.raw b/projects/ragamatic/rawwaves/fwavblnk.raw similarity index 100% rename from ragamatic/rawwaves/fwavblnk.raw rename to projects/ragamatic/rawwaves/fwavblnk.raw diff --git a/ragamatic/rawwaves/gun1.raw b/projects/ragamatic/rawwaves/gun1.raw similarity index 100% rename from ragamatic/rawwaves/gun1.raw rename to projects/ragamatic/rawwaves/gun1.raw diff --git a/ragamatic/rawwaves/halfwave.raw b/projects/ragamatic/rawwaves/halfwave.raw similarity index 100% rename from ragamatic/rawwaves/halfwave.raw rename to projects/ragamatic/rawwaves/halfwave.raw diff --git a/ragamatic/rawwaves/hihatcym.raw b/projects/ragamatic/rawwaves/hihatcym.raw similarity index 100% rename from ragamatic/rawwaves/hihatcym.raw rename to projects/ragamatic/rawwaves/hihatcym.raw diff --git a/ragamatic/rawwaves/impuls10.raw b/projects/ragamatic/rawwaves/impuls10.raw similarity index 100% rename from ragamatic/rawwaves/impuls10.raw rename to projects/ragamatic/rawwaves/impuls10.raw diff --git a/ragamatic/rawwaves/impuls20.raw b/projects/ragamatic/rawwaves/impuls20.raw similarity index 100% rename from ragamatic/rawwaves/impuls20.raw rename to projects/ragamatic/rawwaves/impuls20.raw diff --git a/ragamatic/rawwaves/impuls40.raw b/projects/ragamatic/rawwaves/impuls40.raw similarity index 100% rename from ragamatic/rawwaves/impuls40.raw rename to projects/ragamatic/rawwaves/impuls40.raw diff --git a/ragamatic/rawwaves/jun1.raw b/projects/ragamatic/rawwaves/jun1.raw similarity index 100% rename from ragamatic/rawwaves/jun1.raw rename to projects/ragamatic/rawwaves/jun1.raw diff --git a/ragamatic/rawwaves/jun2.raw b/projects/ragamatic/rawwaves/jun2.raw similarity index 100% rename from ragamatic/rawwaves/jun2.raw rename to projects/ragamatic/rawwaves/jun2.raw diff --git a/ragamatic/rawwaves/makefunc.c b/projects/ragamatic/rawwaves/makefunc.c similarity index 100% rename from ragamatic/rawwaves/makefunc.c rename to projects/ragamatic/rawwaves/makefunc.c diff --git a/ragamatic/rawwaves/makemidi.c b/projects/ragamatic/rawwaves/makemidi.c similarity index 100% rename from ragamatic/rawwaves/makemidi.c rename to projects/ragamatic/rawwaves/makemidi.c diff --git a/ragamatic/rawwaves/makewavs.c b/projects/ragamatic/rawwaves/makewavs.c similarity index 100% rename from ragamatic/rawwaves/makewavs.c rename to projects/ragamatic/rawwaves/makewavs.c diff --git a/ragamatic/rawwaves/mand1.raw b/projects/ragamatic/rawwaves/mand1.raw similarity index 100% rename from ragamatic/rawwaves/mand1.raw rename to projects/ragamatic/rawwaves/mand1.raw diff --git a/ragamatic/rawwaves/mand10.raw b/projects/ragamatic/rawwaves/mand10.raw similarity index 100% rename from ragamatic/rawwaves/mand10.raw rename to projects/ragamatic/rawwaves/mand10.raw diff --git a/ragamatic/rawwaves/mand11.raw b/projects/ragamatic/rawwaves/mand11.raw similarity index 100% rename from ragamatic/rawwaves/mand11.raw rename to projects/ragamatic/rawwaves/mand11.raw diff --git a/ragamatic/rawwaves/mand12.raw b/projects/ragamatic/rawwaves/mand12.raw similarity index 100% rename from ragamatic/rawwaves/mand12.raw rename to projects/ragamatic/rawwaves/mand12.raw diff --git a/ragamatic/rawwaves/mand2.raw b/projects/ragamatic/rawwaves/mand2.raw similarity index 100% rename from ragamatic/rawwaves/mand2.raw rename to projects/ragamatic/rawwaves/mand2.raw diff --git a/ragamatic/rawwaves/mand3.raw b/projects/ragamatic/rawwaves/mand3.raw similarity index 100% rename from ragamatic/rawwaves/mand3.raw rename to projects/ragamatic/rawwaves/mand3.raw diff --git a/ragamatic/rawwaves/mand4.raw b/projects/ragamatic/rawwaves/mand4.raw similarity index 100% rename from ragamatic/rawwaves/mand4.raw rename to projects/ragamatic/rawwaves/mand4.raw diff --git a/ragamatic/rawwaves/mand5.raw b/projects/ragamatic/rawwaves/mand5.raw similarity index 100% rename from ragamatic/rawwaves/mand5.raw rename to projects/ragamatic/rawwaves/mand5.raw diff --git a/ragamatic/rawwaves/mand6.raw b/projects/ragamatic/rawwaves/mand6.raw similarity index 100% rename from ragamatic/rawwaves/mand6.raw rename to projects/ragamatic/rawwaves/mand6.raw diff --git a/ragamatic/rawwaves/mand7.raw b/projects/ragamatic/rawwaves/mand7.raw similarity index 100% rename from ragamatic/rawwaves/mand7.raw rename to projects/ragamatic/rawwaves/mand7.raw diff --git a/ragamatic/rawwaves/mand8.raw b/projects/ragamatic/rawwaves/mand8.raw similarity index 100% rename from ragamatic/rawwaves/mand8.raw rename to projects/ragamatic/rawwaves/mand8.raw diff --git a/ragamatic/rawwaves/mand9.raw b/projects/ragamatic/rawwaves/mand9.raw similarity index 100% rename from ragamatic/rawwaves/mand9.raw rename to projects/ragamatic/rawwaves/mand9.raw diff --git a/ragamatic/rawwaves/silence.raw b/projects/ragamatic/rawwaves/silence.raw similarity index 100% rename from ragamatic/rawwaves/silence.raw rename to projects/ragamatic/rawwaves/silence.raw diff --git a/ragamatic/rawwaves/tak1.raw b/projects/ragamatic/rawwaves/tak1.raw similarity index 100% rename from ragamatic/rawwaves/tak1.raw rename to projects/ragamatic/rawwaves/tak1.raw diff --git a/ragamatic/rawwaves/tak2.raw b/projects/ragamatic/rawwaves/tak2.raw similarity index 100% rename from ragamatic/rawwaves/tak2.raw rename to projects/ragamatic/rawwaves/tak2.raw diff --git a/ragamatic/rawwaves/tak3.raw b/projects/ragamatic/rawwaves/tak3.raw similarity index 100% rename from ragamatic/rawwaves/tak3.raw rename to projects/ragamatic/rawwaves/tak3.raw diff --git a/ragamatic/rawwaves/tak4.raw b/projects/ragamatic/rawwaves/tak4.raw similarity index 100% rename from ragamatic/rawwaves/tak4.raw rename to projects/ragamatic/rawwaves/tak4.raw diff --git a/ragamatic/tcl/TCLRaga.tcl b/projects/ragamatic/tcl/TCLRaga.tcl similarity index 80% rename from ragamatic/tcl/TCLRaga.tcl rename to projects/ragamatic/tcl/TCLRaga.tcl index 6b3b200..13a1f06 100644 --- a/ragamatic/tcl/TCLRaga.tcl +++ b/projects/ragamatic/tcl/TCLRaga.tcl @@ -51,7 +51,7 @@ bind . +myExit proc myExit {} { global outID - puts $outID [format "NoteOff 0.0 1 60 127"] + puts $outID [format "NoteOff -1.0 1 60 127"] flush $outID puts $outID [format "ExitProgram"] flush $outID @@ -66,11 +66,11 @@ proc mellow {} { set cont4 0.0 set cont11 10.0 set cont7 3.0 - printWhatz "ControlChange 0.0 1 " 1 $cont1 - printWhatz "ControlChange 0.0 1 " 2 $cont2 - printWhatz "ControlChange 0.0 1 " 4 $cont4 - printWhatz "ControlChange 0.0 1 " 7 $cont7 - printWhatz "ControlChange 0.0 1 " 11 $cont11 + printWhatz "ControlChange -1.0 1 " 1 $cont1 + printWhatz "ControlChange -1.0 1 " 2 $cont2 + printWhatz "ControlChange -1.0 1 " 4 $cont4 + printWhatz "ControlChange -1.0 1 " 7 $cont7 + printWhatz "ControlChange -1.0 1 " 11 $cont11 } proc nicevibe {} { @@ -80,11 +80,11 @@ proc nicevibe {} { set cont4 21.0 set cont11 50.0 set cont7 60.0 - printWhatz "ControlChange 0.0 1 " 1 $cont1 - printWhatz "ControlChange 0.0 1 " 2 $cont2 - printWhatz "ControlChange 0.0 1 " 4 $cont4 - printWhatz "ControlChange 0.0 1 " 7 $cont7 - printWhatz "ControlChange 0.0 1 " 11 $cont11 + printWhatz "ControlChange -1.0 1 " 1 $cont1 + printWhatz "ControlChange -1.0 1 " 2 $cont2 + printWhatz "ControlChange -1.0 1 " 4 $cont4 + printWhatz "ControlChange -1.0 1 " 7 $cont7 + printWhatz "ControlChange -1.0 1 " 11 $cont11 } proc voicSolo {} { @@ -94,11 +94,11 @@ proc voicSolo {} { set cont4 90.0 set cont11 10.0 set cont7 120.0 - printWhatz "ControlChange 0.0 1 " 1 $cont1 - printWhatz "ControlChange 0.0 1 " 2 $cont2 - printWhatz "ControlChange 0.0 1 " 4 $cont4 - printWhatz "ControlChange 0.0 1 " 7 $cont7 - printWhatz "ControlChange 0.0 1 " 11 $cont11 + printWhatz "ControlChange -1.0 1 " 1 $cont1 + printWhatz "ControlChange -1.0 1 " 2 $cont2 + printWhatz "ControlChange -1.0 1 " 4 $cont4 + printWhatz "ControlChange -1.0 1 " 7 $cont7 + printWhatz "ControlChange -1.0 1 " 11 $cont11 } proc drumSolo {} { @@ -108,11 +108,11 @@ proc drumSolo {} { set cont4 0.0 set cont11 100.0 set cont7 120.0 - printWhatz "ControlChange 0.0 1 " 1 $cont1 - printWhatz "ControlChange 0.0 1 " 2 $cont2 - printWhatz "ControlChange 0.0 1 " 4 $cont4 - printWhatz "ControlChange 0.0 1 " 7 $cont7 - printWhatz "ControlChange 0.0 1 " 11 $cont11 + printWhatz "ControlChange -1.0 1 " 1 $cont1 + printWhatz "ControlChange -1.0 1 " 2 $cont2 + printWhatz "ControlChange -1.0 1 " 4 $cont4 + printWhatz "ControlChange -1.0 1 " 7 $cont7 + printWhatz "ControlChange -1.0 1 " 11 $cont11 } proc rockOut {} { @@ -122,28 +122,28 @@ proc rockOut {} { set cont4 52.0 set cont11 120.0 set cont7 123.0 - printWhatz "ControlChange 0.0 1 " 1 $cont1 - printWhatz "ControlChange 0.0 1 " 2 $cont2 - printWhatz "ControlChange 0.0 1 " 4 $cont4 - printWhatz "ControlChange 0.0 1 " 7 $cont7 - printWhatz "ControlChange 0.0 1 " 11 $cont11 + printWhatz "ControlChange -1.0 1 " 1 $cont1 + printWhatz "ControlChange -1.0 1 " 2 $cont2 + printWhatz "ControlChange -1.0 1 " 4 $cont4 + printWhatz "ControlChange -1.0 1 " 7 $cont7 + printWhatz "ControlChange -1.0 1 " 11 $cont11 } proc raga {scale} { global outID - puts $outID [format "ControlChange 0.0 1 64 %f" $scale] + puts $outID [format "ControlChange -1.0 1 64 %f" $scale] flush $outID } proc noteOn {pitchVal pressVal} { global outID - puts $outID [format "NoteOn 0.0 1 %f %f" $pitchVal $pressVal] + puts $outID [format "NoteOn -1.0 1 %f %f" $pitchVal $pressVal] flush $outID } proc noteOff {pitchVal pressVal} { global outID - puts $outID [format "NoteOff 0.0 1 %f %f" $pitchVal $pressVal] + puts $outID [format "NoteOff -1.0 1 %f %f" $pitchVal $pressVal] flush $outID } @@ -182,31 +182,31 @@ button .banner.butts.noteOn -text "Cease Meditations and Exit" \ frame .controls -bg black scale .controls.cont1 -from 0 -to 128 -length 300 \ --command {printWhatz "ControlChange 0.0 1 " 1} \ +-command {printWhatz "ControlChange -1.0 1 " 1} \ -orient horizontal -label "Drone Probability" \ -tickinterval 32 -showvalue true -bg grey66 \ -variable cont1 scale .controls.cont2 -from 0 -to 128 -length 300 \ --command {printWhatz "ControlChange 0.0 1 " 2} \ +-command {printWhatz "ControlChange -1.0 1 " 2} \ -orient horizontal -label "Sitar Probability" \ -tickinterval 32 -showvalue true -bg grey66 \ -variable cont2 scale .controls.cont4 -from 0 -to 128 -length 300 \ --command {printWhatz "ControlChange 0.0 1 " 4} \ +-command {printWhatz "ControlChange -1.0 1 " 4} \ -orient horizontal -label "Voice Drum Probability" \ -tickinterval 32 -showvalue true -bg grey66 \ -variable cont4 scale .controls.cont11 -from 0 -to 128 -length 300 \ --command {printWhatz "ControlChange 0.0 1 " 11} \ +-command {printWhatz "ControlChange -1.0 1 " 11} \ -orient horizontal -label "Tabla Probability" \ -tickinterval 32 -showvalue true -bg grey66 \ -variable cont11 scale .controls.cont7 -from 0 -to 128 -length 300 \ --command {printWhatz "ControlChange 0.0 1 " 7} \ +-command {printWhatz "ControlChange -1.0 1 " 7} \ -orient horizontal -label "Tempo" \ -tickinterval 32 -showvalue true -bg grey66 \ -variable cont7 diff --git a/ragamatic/tcl/bitmaps/prc.xbm b/projects/ragamatic/tcl/bitmaps/prc.xbm similarity index 100% rename from ragamatic/tcl/bitmaps/prc.xbm rename to projects/ragamatic/tcl/bitmaps/prc.xbm diff --git a/ragamatic/tcl/bitmaps/prcFunny.xbm b/projects/ragamatic/tcl/bitmaps/prcFunny.xbm similarity index 100% rename from ragamatic/tcl/bitmaps/prcFunny.xbm rename to projects/ragamatic/tcl/bitmaps/prcFunny.xbm diff --git a/ragamatic/tcl/bitmaps/ragamat.bmp b/projects/ragamatic/tcl/bitmaps/ragamat.bmp similarity index 100% rename from ragamatic/tcl/bitmaps/ragamat.bmp rename to projects/ragamatic/tcl/bitmaps/ragamat.bmp diff --git a/ragamatic/tcl/bitmaps/ragamat.xbm b/projects/ragamatic/tcl/bitmaps/ragamat.xbm similarity index 100% rename from ragamatic/tcl/bitmaps/ragamat.xbm rename to projects/ragamatic/tcl/bitmaps/ragamat.xbm diff --git a/ragamatic/tcl/bitmaps/ragamat2.bmp b/projects/ragamatic/tcl/bitmaps/ragamat2.bmp similarity index 100% rename from ragamatic/tcl/bitmaps/ragamat2.bmp rename to projects/ragamatic/tcl/bitmaps/ragamat2.bmp diff --git a/ragamatic/tcl/bitmaps/ragamat2.xbm b/projects/ragamatic/tcl/bitmaps/ragamat2.xbm similarity index 100% rename from ragamatic/tcl/bitmaps/ragamat2.xbm rename to projects/ragamatic/tcl/bitmaps/ragamat2.xbm diff --git a/projects/syntmono/GUIBowedBar b/projects/syntmono/GUIBowedBar new file mode 100755 index 0000000..c8f02a9 --- /dev/null +++ b/projects/syntmono/GUIBowedBar @@ -0,0 +1 @@ +wish < tcl/TCLBowedBar.tcl | syntmono BowedBar -or -ip diff --git a/projects/syntmono/GUIDrums b/projects/syntmono/GUIDrums new file mode 100755 index 0000000..4cfffff --- /dev/null +++ b/projects/syntmono/GUIDrums @@ -0,0 +1 @@ +wish < tcl/TCLDrums.tcl | syntmono DrumSynt -or -ip diff --git a/projects/syntmono/GUIModal b/projects/syntmono/GUIModal new file mode 100755 index 0000000..38228aa --- /dev/null +++ b/projects/syntmono/GUIModal @@ -0,0 +1 @@ +wish < tcl/TCLModal.tcl | syntmono ModalBar -or -ip diff --git a/projects/syntmono/GUIPhysical b/projects/syntmono/GUIPhysical new file mode 100755 index 0000000..f21dc9d --- /dev/null +++ b/projects/syntmono/GUIPhysical @@ -0,0 +1 @@ +wish < tcl/TCLPhys.tcl | syntmono Clarinet -or -ip diff --git a/projects/syntmono/GUIShakers b/projects/syntmono/GUIShakers new file mode 100755 index 0000000..2509ab5 --- /dev/null +++ b/projects/syntmono/GUIShakers @@ -0,0 +1 @@ +wish < tcl/TCLShakers.tcl | syntmono Shakers -or -ip diff --git a/projects/syntmono/GUIVoice b/projects/syntmono/GUIVoice new file mode 100755 index 0000000..b6da5fe --- /dev/null +++ b/projects/syntmono/GUIVoice @@ -0,0 +1 @@ +wish < tcl/TCLVoice.tcl | syntmono FMVoices -or -ip diff --git a/syntmono/Makefile b/projects/syntmono/Makefile similarity index 56% rename from syntmono/Makefile rename to projects/syntmono/Makefile index 5cba594..1cf91f3 100644 --- a/syntmono/Makefile +++ b/projects/syntmono/Makefile @@ -7,7 +7,7 @@ OS = $(shell uname) # The following definition indicates the relative location of # the core STK classes. -STK_PATH = ../STK/ +STK_PATH = ../../src/ O_FILES = Object.o Envelope.o ADSR.o Noise.o SubNoise.o \ Modulatr.o Filter.o OneZero.o TablLook.o \ @@ -17,49 +17,54 @@ O_FILES = Object.o Envelope.o ADSR.o Noise.o SubNoise.o \ LipFilt.o Modal4.o FM4Op.o FM4Alg3.o FM4Alg4.o \ FM4Alg5.o FM4Alg6.o FM4Alg8.o Plucked2.o \ SamplFlt.o Sampler.o SKINI11.o Simple.o \ - SingWave.o VoicForm.o FMVoices.o swapstuf.o \ - utilities.o threads.o \ + SingWave.o VoicForm.o FMVoices.o ByteSwap.o \ + utilities.o StkError.o PoleZero.o \ \ - Instrmnt.o Marimba.o Vibraphn.o AgogoBel.o Shakers.o \ - Plucked.o Mandolin.o Clarinet.o Flute.o Moog1.o \ - Brass.o Bowed.o Rhodey.o Wurley.o TubeBell.o \ - HeavyMtl.o PercFlut.o BeeThree.o DrumSynt.o \ + Instrmnt.o Shakers.o Plucked.o Mandolin.o \ + Clarinet.o Flute.o Moog1.o Brass.o Bowed.o \ + Rhodey.o Wurley.o TubeBell.o HeavyMtl.o \ + PercFlut.o BeeThree.o DrumSynt.o \ \ WvOut.o SndWvOut.o WavWvOut.o MatWvOut.o RawWvOut.o \ WvIn.o SndWvIn.o WavWvIn.o MatWvIn.o RawWvIn.o \ - Reverb.o PRCRev.o JCRev.o NRev.o BowedBar.o + Reverb.o PRCRev.o JCRev.o NRev.o BowedBar.o \ + Controller.o ModalBar.o AifWvOut.o BlowHole.o RM = /bin/rm ifeq ($(OS),NEXTSTEP) # These are for NeXT - CC = cc -arch m68k -arch i386 -Wall -D__OS_NeXT_ +# CC = cc -arch m68k -arch i386 -Wall -D__OS_NeXT_ + CC = g++ -bm68k-next-nextstep3 -bi386-next-nextstep3 -Wall -D__OS_NeXT_ -fhandle-exceptions INSTR = syntmono + INCLUDE = -I../../include endif ifeq ($(OS),IRIX) # These are for SGI - INSTR = MD2SKINI syntmono - CC = CC -O2 -D__OS_IRIX_ # -g -fullwarn -D__SGI_CC__ - O_FILES += RTWvOut.o RTSoundIO.o RTWvIn.o MIDIIO.o RTDuplex.o + INSTR = syntmono + CC = CC -D__OS_IRIX_ # -g -fullwarn -D__SGI_CC__ -O2 + O_FILES += RtWvOut.o RtAudio.o RtWvIn.o RtMidi.o RtDuplex.o LIBRARY = -L/usr/sgitcl/lib -laudio -lmd -lm -lpthread + INCLUDE = -I../../include endif ifeq ($(OS),Linux) # These are for Linux - INSTR = syntmono MD2SKINI + INSTR = syntmono CC = g++ -O3 -Wall -D__OS_Linux_ # -g -O3 -Wall - O_FILES += RTWvOut.o RTSoundIO.o RTWvIn.o MIDIIO.o RTDuplex.o - LIBRARY = -lpthread -lm + O_FILES += RtWvOut.o RtAudio.o RtWvIn.o RtMidi.o RtDuplex.o + LIBRARY = -lpthread -lm #-lasound + INCLUDE = -I../../include endif %.o : $(STK_PATH)%.cpp - $(CC) -c $(<) -o $@ + $(CC) $(INCLUDE) -c $(<) -o $@ all: $(INSTR) syntmono: syntmono.cpp $(O_FILES) $(CC) $(INCLUDE) -o syntmono syntmono.cpp $(O_FILES) $(LIBRARY) -MD2SKINI: $(STK_PATH)MD2SKINI.cpp Object.o MIDIIO.o - $(CC) -o MD2SKINI $(STK_PATH)MD2SKINI.cpp Object.o MIDIIO.o $(LIBRARY) +MD2SKINI: $(STK_PATH)MD2SKINI.cpp Object.o RtMidi.o StkError.o + $(CC) -o MD2SKINI $(STK_PATH)MD2SKINI.cpp Object.o RtMidi.o StkError.o $(LIBRARY) $(INCLUDE) clean : rm *.o @@ -74,7 +79,4 @@ strip : # $(O_FILES) : utilities.o: utilities.cpp - $(CC) -c utilities.cpp - -threads.o: threads.cpp - $(CC) -c threads.cpp \ No newline at end of file + $(CC) $(INCLUDE) -c utilities.cpp diff --git a/syntmono/Makefile.sgi b/projects/syntmono/Makefile.sgi similarity index 67% rename from syntmono/Makefile.sgi rename to projects/syntmono/Makefile.sgi index cd598e2..9ae49bd 100644 --- a/syntmono/Makefile.sgi +++ b/projects/syntmono/Makefile.sgi @@ -2,7 +2,7 @@ # The following definition indicates the relative location of # the core STK classes. -STK_PATH = ../STK/ +STK_PATH = ../../src/ O_FILES = $(STK_PATH)Object.o $(STK_PATH)Envelope.o $(STK_PATH)ADSR.o \ $(STK_PATH)Noise.o $(STK_PATH)SubNoise.o $(STK_PATH)Modulatr.o \ @@ -16,10 +16,9 @@ O_FILES = $(STK_PATH)Object.o $(STK_PATH)Envelope.o $(STK_PATH)ADSR.o \ $(STK_PATH)FM4Alg6.o $(STK_PATH)FM4Alg8.o $(STK_PATH)Plucked2.o \ $(STK_PATH)SamplFlt.o $(STK_PATH)Sampler.o $(STK_PATH)SKINI11.o \ $(STK_PATH)Simple.o $(STK_PATH)SingWave.o $(STK_PATH)VoicForm.o \ - $(STK_PATH)FMVoices.o $(STK_PATH)swapstuf.o \ + $(STK_PATH)FMVoices.o $(STK_PATH)ByteSwap.o $(STK_PATH)PoleZero.o \ \ - $(STK_PATH)Instrmnt.o $(STK_PATH)Marimba.o $(STK_PATH)Vibraphn.o \ - $(STK_PATH)AgogoBel.o $(STK_PATH)Shakers.o $(STK_PATH)Plucked.o \ + $(STK_PATH)Instrmnt.o $(STK_PATH)Shakers.o $(STK_PATH)Plucked.o \ $(STK_PATH)Mandolin.o $(STK_PATH)Clarinet.o $(STK_PATH)Flute.o \ $(STK_PATH)Moog1.o $(STK_PATH)Brass.o $(STK_PATH)Bowed.o \ $(STK_PATH)Rhodey.o $(STK_PATH)Wurley.o $(STK_PATH)TubeBell.o \ @@ -30,29 +29,31 @@ O_FILES = $(STK_PATH)Object.o $(STK_PATH)Envelope.o $(STK_PATH)ADSR.o \ $(STK_PATH)MatWvOut.o $(STK_PATH)WvIn.o $(STK_PATH)SndWvIn.o \ $(STK_PATH)WavWvIn.o $(STK_PATH)MatWvIn.o $(STK_PATH)RawWvIn.o \ $(STK_PATH)Reverb.o $(STK_PATH)PRCRev.o $(STK_PATH)JCRev.o \ - $(STK_PATH)NRev.o $(STK_PATH)RTWvOut.o $(STK_PATH)RTWvIn.o \ - $(STK_PATH)RTSoundIO.o $(STK_PATH)MIDIIO.o $(STK_PATH)RTDuplex.o \ - $(STK_PATH)BowedBar.o + $(STK_PATH)NRev.o $(STK_PATH)RtWvOut.o $(STK_PATH)RtWvIn.o \ + $(STK_PATH)RtAudio.o $(STK_PATH)RtMidi.o $(STK_PATH)RtDuplex.o \ + $(STK_PATH)BowedBar.o $(STK_PATH)StkError.o $(STK_PATH)Controller.o \ + $(STK_PATH)BlowHole.o $(STK_PATH)AifWvOut.o $(STK_PATH)ModalBar.o -O_UTIL_FILES = utilities.o threads.o +O_LOCAL_FILES = utilities.o RM = /bin/rm -INSTR = MD2SKINI syntmono +INSTR = syntmono CC = CC -O2 -D__OS_IRIX_ # -g -fullwarn -D__SGI_CC__ -LIBRARY = -L/usr/sgitcl/lib -laudio -lmd -lm +LIBRARY = -L/usr/sgitcl/lib -laudio -lmd -lm -lpthread +INCLUDE = -I../../include/ .SUFFIXES: .cpp -.cpp.o: $(STK_PATH)Object.h $(O_FILES) - $(CC) -c -o $@ $< +.cpp.o: $(O_FILES) + $(CC) $(INCLUDE) -c -o $@ $< all: $(INSTR) -syntmono: syntmono.cpp $(O_FILES) $(O_UTIL_FILES) - $(CC) $(INCLUDE) -o syntmono syntmono.cpp $(O_FILES) $(O_UTIL_FILES) $(LIBRARY) +syntmono: syntmono.cpp $(O_FILES) $(O_LOCAL_FILES) + $(CC) -o syntmono syntmono.cpp $(O_FILES) $(O_LOCAL_FILES) $(LIBRARY) $(INCLUDE) -MD2SKINI: $(STK_PATH)MD2SKINI.cpp $(STK_PATH)Object.o $(STK_PATH)MIDIIO.o - $(CC) -o MD2SKINI $(STK_PATH)MD2SKINI.cpp $(STK_PATH)Object.o $(STK_PATH)MIDIIO.o $(LIBRARY) +MD2SKINI: $(STK_PATH)MD2SKINI.cpp $(STK_PATH)Object.o $(STK_PATH)RtMidi.o + $(CC) $(INCLUDE) -o MD2SKINI $(STK_PATH)MD2SKINI.cpp $(STK_PATH)Object.o $(STK_PATH)RtMidi.o $(STK_PATH)StkError.o $(LIBRARY) clean : rm *.o @@ -68,7 +69,5 @@ strip : # $(O_FILES) : utilities.o: utilities.cpp - $(CC) -c utilities.cpp + $(CC) $(INCLUDE) -c utilities.cpp -threads.o: threads.cpp - $(CC) -c threads.cpp diff --git a/effects/Release/.placeholder b/projects/syntmono/Release/.placeholder similarity index 100% rename from effects/Release/.placeholder rename to projects/syntmono/Release/.placeholder diff --git a/syntmono/STK.dsw b/projects/syntmono/STK.dsw similarity index 85% rename from syntmono/STK.dsw rename to projects/syntmono/STK.dsw index 48ebf3b..bf6721d 100644 --- a/syntmono/STK.dsw +++ b/projects/syntmono/STK.dsw @@ -1,4 +1,4 @@ -Microsoft Developer Studio Workspace File, Format Version 5.00 +Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### diff --git a/projects/syntmono/StkDemo b/projects/syntmono/StkDemo new file mode 100755 index 0000000..71b3b60 --- /dev/null +++ b/projects/syntmono/StkDemo @@ -0,0 +1 @@ +wish < tcl/TCLDemo.tcl | syntmono Clarinet -or -ip diff --git a/syntmono/md2skini.dsp b/projects/syntmono/md2skini.dsp similarity index 80% rename from syntmono/md2skini.dsp rename to projects/syntmono/md2skini.dsp index 0a4e480..2b97847 100644 --- a/syntmono/md2skini.dsp +++ b/projects/syntmono/md2skini.dsp @@ -1,5 +1,5 @@ # Microsoft Developer Studio Project File - Name="MD2SKINI" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 @@ -17,12 +17,12 @@ CFG=MD2SKINI - Win32 Debug !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE -!MESSAGE "MD2SKINI - Win32 Release" (based on\ - "Win32 (x86) Console Application") +!MESSAGE "MD2SKINI - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "MD2SKINI - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project +# PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe @@ -42,7 +42,7 @@ RSC=rc.exe # 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 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__OS_Win_" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /I "../../include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__OS_Win_" /YX /FD /D /i /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe @@ -66,7 +66,7 @@ LINK32=link.exe # 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 /c -# ADD CPP /nologo /MT /W3 /Gm /GX /Zi /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__OS_Win_" /YX /FD /c +# ADD CPP /nologo /MT /W3 /Gm /GX /ZI /Od /I "../../include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__OS_Win_" /YX /FD /D /c # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe @@ -84,23 +84,31 @@ LINK32=link.exe # Name "MD2SKINI - Win32 Debug" # Begin Source File -SOURCE=..\Stk\MD2SKINI.cpp +SOURCE=..\..\src\MD2SKINI.cpp # End Source File # Begin Source File -SOURCE=..\Stk\MIDIIO.cpp +SOURCE=..\..\src\Object.cpp # End Source File # Begin Source File -SOURCE=..\Stk\MIDIIO.h +SOURCE=..\..\include\Object.h # End Source File # Begin Source File -SOURCE=..\Stk\Object.cpp +SOURCE=..\..\src\RtMidi.cpp # End Source File # Begin Source File -SOURCE=..\Stk\Object.h +SOURCE=..\..\include\RtMidi.h +# End Source File +# Begin Source File + +SOURCE=..\..\src\StkError.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\include\StkError.h # End Source File # End Target # End Project diff --git a/syntmono/scores/bookert.ski b/projects/syntmono/scores/bookert.ski similarity index 100% rename from syntmono/scores/bookert.ski rename to projects/syntmono/scores/bookert.ski diff --git a/syntmono/scores/capture.ski b/projects/syntmono/scores/capture.ski similarity index 100% rename from syntmono/scores/capture.ski rename to projects/syntmono/scores/capture.ski diff --git a/syntmono/scores/chords.ski b/projects/syntmono/scores/chords.ski similarity index 100% rename from syntmono/scores/chords.ski rename to projects/syntmono/scores/chords.ski diff --git a/syntmono/scores/doogie.ski b/projects/syntmono/scores/doogie.ski similarity index 100% rename from syntmono/scores/doogie.ski rename to projects/syntmono/scores/doogie.ski diff --git a/syntmono/scores/drumfunk.ski b/projects/syntmono/scores/drumfunk.ski similarity index 100% rename from syntmono/scores/drumfunk.ski rename to projects/syntmono/scores/drumfunk.ski diff --git a/syntmono/scores/drumtest.ski b/projects/syntmono/scores/drumtest.ski similarity index 100% rename from syntmono/scores/drumtest.ski rename to projects/syntmono/scores/drumtest.ski diff --git a/syntmono/scores/duelingb.ski b/projects/syntmono/scores/duelingb.ski similarity index 100% rename from syntmono/scores/duelingb.ski rename to projects/syntmono/scores/duelingb.ski diff --git a/syntmono/scores/fiddle.ski b/projects/syntmono/scores/fiddle.ski similarity index 100% rename from syntmono/scores/fiddle.ski rename to projects/syntmono/scores/fiddle.ski diff --git a/syntmono/scores/flutbach.ski b/projects/syntmono/scores/flutbach.ski similarity index 100% rename from syntmono/scores/flutbach.ski rename to projects/syntmono/scores/flutbach.ski diff --git a/syntmono/scores/funicula.ski b/projects/syntmono/scores/funicula.ski similarity index 100% rename from syntmono/scores/funicula.ski rename to projects/syntmono/scores/funicula.ski diff --git a/syntmono/scores/funskini.ski b/projects/syntmono/scores/funskini.ski similarity index 100% rename from syntmono/scores/funskini.ski rename to projects/syntmono/scores/funskini.ski diff --git a/syntmono/scores/instructions b/projects/syntmono/scores/instructions similarity index 100% rename from syntmono/scores/instructions rename to projects/syntmono/scores/instructions diff --git a/syntmono/scores/lacrymos.ski b/projects/syntmono/scores/lacrymos.ski similarity index 100% rename from syntmono/scores/lacrymos.ski rename to projects/syntmono/scores/lacrymos.ski diff --git a/syntmono/scores/mandtune.ski b/projects/syntmono/scores/mandtune.ski similarity index 100% rename from syntmono/scores/mandtune.ski rename to projects/syntmono/scores/mandtune.ski diff --git a/syntmono/scores/marimba2.ski b/projects/syntmono/scores/marimba2.ski similarity index 100% rename from syntmono/scores/marimba2.ski rename to projects/syntmono/scores/marimba2.ski diff --git a/syntmono/scores/marimtst.ski b/projects/syntmono/scores/marimtst.ski similarity index 100% rename from syntmono/scores/marimtst.ski rename to projects/syntmono/scores/marimtst.ski diff --git a/syntmono/scores/misacrio.ski b/projects/syntmono/scores/misacrio.ski similarity index 100% rename from syntmono/scores/misacrio.ski rename to projects/syntmono/scores/misacrio.ski diff --git a/syntmono/scores/morazbel.ski b/projects/syntmono/scores/morazbel.ski similarity index 100% rename from syntmono/scores/morazbel.ski rename to projects/syntmono/scores/morazbel.ski diff --git a/syntmono/scores/organs.ski b/projects/syntmono/scores/organs.ski similarity index 100% rename from syntmono/scores/organs.ski rename to projects/syntmono/scores/organs.ski diff --git a/syntmono/scores/pickdamp.ski b/projects/syntmono/scores/pickdamp.ski similarity index 100% rename from syntmono/scores/pickdamp.ski rename to projects/syntmono/scores/pickdamp.ski diff --git a/syntmono/scores/pictures.ski b/projects/syntmono/scores/pictures.ski similarity index 100% rename from syntmono/scores/pictures.ski rename to projects/syntmono/scores/pictures.ski diff --git a/syntmono/scores/riderson.ski b/projects/syntmono/scores/riderson.ski similarity index 100% rename from syntmono/scores/riderson.ski rename to projects/syntmono/scores/riderson.ski diff --git a/syntmono/scores/scales.ski b/projects/syntmono/scores/scales.ski similarity index 100% rename from syntmono/scores/scales.ski rename to projects/syntmono/scores/scales.ski diff --git a/syntmono/scores/shaktest.ski b/projects/syntmono/scores/shaktest.ski similarity index 100% rename from syntmono/scores/shaktest.ski rename to projects/syntmono/scores/shaktest.ski diff --git a/syntmono/scores/simplgft.ski b/projects/syntmono/scores/simplgft.ski similarity index 100% rename from syntmono/scores/simplgft.ski rename to projects/syntmono/scores/simplgft.ski diff --git a/syntmono/scores/spain.ski b/projects/syntmono/scores/spain.ski similarity index 100% rename from syntmono/scores/spain.ski rename to projects/syntmono/scores/spain.ski diff --git a/syntmono/scores/spain0.ski b/projects/syntmono/scores/spain0.ski similarity index 100% rename from syntmono/scores/spain0.ski rename to projects/syntmono/scores/spain0.ski diff --git a/syntmono/scores/streetsf.ski b/projects/syntmono/scores/streetsf.ski similarity index 100% rename from syntmono/scores/streetsf.ski rename to projects/syntmono/scores/streetsf.ski diff --git a/syntmono/scores/test.ski b/projects/syntmono/scores/test.ski similarity index 100% rename from syntmono/scores/test.ski rename to projects/syntmono/scores/test.ski diff --git a/syntmono/scores/thecars.ski b/projects/syntmono/scores/thecars.ski similarity index 100% rename from syntmono/scores/thecars.ski rename to projects/syntmono/scores/thecars.ski diff --git a/syntmono/scores/tubebell.ski b/projects/syntmono/scores/tubebell.ski similarity index 100% rename from syntmono/scores/tubebell.ski rename to projects/syntmono/scores/tubebell.ski diff --git a/syntmono/scores/vocaliz.ski b/projects/syntmono/scores/vocaliz.ski similarity index 100% rename from syntmono/scores/vocaliz.ski rename to projects/syntmono/scores/vocaliz.ski diff --git a/projects/syntmono/syntmono.cpp b/projects/syntmono/syntmono.cpp new file mode 100644 index 0000000..5fa007b --- /dev/null +++ b/projects/syntmono/syntmono.cpp @@ -0,0 +1,148 @@ +// syntmono.cpp +// +// An example STK program for monophonic voice playback and control. + +#include "WvOut.h" +#include "Instrmnt.h" +#include "Reverb.h" +#include "PRCRev.h" +#include "SKINI11.msg" +#include "miditabl.h" + +// The input control handler. +#include "Controller.h" + +// Miscellaneous command-line parsing and instrument allocation +// functions are defined in utilites.cpp. +#include "utilities.h" + +Instrmnt *instrument; +WvOut **output; + +int main(int argc, char *argv[]) +{ + long i, j, nTicks; + int type; + int nOutputs = 0; + int instrumentNo; + int controlMask; + bool done; + MY_FLOAT reverbTime = 0.5; // in seconds + MY_FLOAT temp, byte2, byte3; + MY_FLOAT sample, lastPitch = 200.0; + Reverb *reverb; + Controller *controller; + + // Check the command-line arguments for errors and to determine + // the number of WvOut objects to be instantiated. + nOutputs = checkArgs(argc, argv); + output = (WvOut **) malloc(nOutputs * sizeof(WvOut *)); + + // Instantiate the instrument from the command-line argument. + if ( (instrumentNo=newInstByName(argv[1])) < 0 ) usage(argv[0]); + + // Parse the command-line flags, instantiate WvOut objects, and instantiate + // the input message controller. + try { + controlMask = parseArgs(argc, argv); + controller = new Controller( controlMask ); + } + catch (StkError& m) { + m.printMessage(); + exit(0); + } + + if (controlMask) + instrument->noteOn(lastPitch, 0.7); + + reverb = new PRCRev(reverbTime); + reverb->setEffectMix(0.2); + + // The runtime loop begins here: + done = FALSE; + while (!done) { + + nTicks = controller->getNextMessage(); + + if (nTicks == -1) + done = TRUE; + + for (i=0; itick(instrument->tick()); + for ( j=0; jtick(sample); + } + + type = controller->getType(); + if (type > 0) { + // parse the input control message + + byte2 = controller->getByte2(); + byte3 = controller->getByte3(); + + switch(type) { + + case __SK_NoteOn_: + if (byte3 == 0) // velocity is zero ... really a NoteOff + instrument->noteOff(64.0); + else { // a NoteOn + lastPitch = __MIDI_To_Pitch[(int)byte2]; + instrument->noteOn(lastPitch, byte3*NORM_7); + } + break; + + case __SK_NoteOff_: + instrument->noteOff(byte3*NORM_7); + break; + + case __SK_ControlChange_: + if (byte2 == 44) + reverb->setEffectMix(byte3*NORM_7); + else + instrument->controlChange((int)byte2, byte3); + break; + + case __SK_AfterTouch_: + instrument->controlChange(128, byte2); + break; + + case __SK_PitchBend_: + temp = byte2 - (int)byte2; // floating-point remainder + lastPitch = __MIDI_To_Pitch[(int)byte2] * pow(2.0, temp/12.0) ; + instrument->setFreq(lastPitch); + break; + + case __SK_ProgramChange_: + if (instrumentNo != (int)byte2) { + instrument->noteOff(1.0); + // let the old instrument settle a little + for (i=0; i<4096; i++) { + sample = reverb->tick(instrument->tick()); + for ( j=0; jtick(sample); + } + delete instrument; + if ( (instrumentNo=newInstByNum((int)byte2)) < 0 ) { + // Default instrument = 0 + instrumentNo = newInstByNum(0); + } + instrument->noteOn(lastPitch, 0.2); + } + break; + } + } + } + + for (i=0;itick(instrument->tick()); + for ( j=0; jtick(sample); + } + + for ( i=0; i -# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 @@ -17,12 +17,12 @@ CFG=syntmono - Win32 Debug !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE -!MESSAGE "syntmono - Win32 Release" (based on\ - "Win32 (x86) Console Application") +!MESSAGE "syntmono - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "syntmono - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project +# PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe @@ -42,7 +42,7 @@ RSC=rc.exe # 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 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__OS_Win_" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /I "..\..\include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__OS_Win_" /YX /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe @@ -66,7 +66,7 @@ LINK32=link.exe # 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 /c -# ADD CPP /nologo /MT /W3 /Gm /GX /Zi /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__OS_Win_" /YX /FD /c +# ADD CPP /nologo /MTd /W3 /GX /Zd /Od /I "..\..\include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__OS_Win_" /YX /FD /c # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe @@ -75,6 +75,7 @@ BSC32=bscmake.exe 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 /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 dsound.lib Wsock32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# SUBTRACT LINK32 /pdb:none !ENDIF @@ -84,539 +85,547 @@ LINK32=link.exe # Name "syntmono - Win32 Debug" # Begin Source File -SOURCE=..\Stk\ADSR.cpp +SOURCE=..\..\src\ADSR.cpp # End Source File # Begin Source File -SOURCE=..\Stk\ADSR.h +SOURCE=..\..\include\ADSR.h # End Source File # Begin Source File -SOURCE=..\Stk\AgogoBel.cpp +SOURCE=..\..\src\AifWvOut.cpp # End Source File # Begin Source File -SOURCE=..\Stk\AgogoBel.h +SOURCE=..\..\include\AifWvOut.h # End Source File # Begin Source File -SOURCE=..\Stk\BeeThree.cpp +SOURCE=..\..\src\BeeThree.cpp # End Source File # Begin Source File -SOURCE=..\Stk\BeeThree.h +SOURCE=..\..\include\BeeThree.h # End Source File # Begin Source File -SOURCE=..\Stk\BiQuad.cpp +SOURCE=..\..\src\BiQuad.cpp # End Source File # Begin Source File -SOURCE=..\Stk\BiQuad.h +SOURCE=..\..\include\BiQuad.h # End Source File # Begin Source File -SOURCE=..\Stk\Bowed.cpp +SOURCE=..\..\src\BlowHole.cpp # End Source File # Begin Source File -SOURCE=..\Stk\Bowed.h +SOURCE=..\..\include\BlowHole.h # End Source File # Begin Source File -SOURCE=..\Stk\BowedBar.cpp +SOURCE=..\..\src\Bowed.cpp # End Source File # Begin Source File -SOURCE=..\Stk\BowedBar.h +SOURCE=..\..\include\Bowed.h # End Source File # Begin Source File -SOURCE=..\Stk\BowTabl.cpp +SOURCE=..\..\src\BowedBar.cpp # End Source File # Begin Source File -SOURCE=..\Stk\BowTabl.h +SOURCE=..\..\include\BowedBar.h # End Source File # Begin Source File -SOURCE=..\Stk\Brass.cpp +SOURCE=..\..\src\BowTabl.cpp # End Source File # Begin Source File -SOURCE=..\Stk\Brass.h +SOURCE=..\..\include\BowTabl.h # End Source File # Begin Source File -SOURCE=..\Stk\Clarinet.cpp +SOURCE=..\..\src\Brass.cpp # End Source File # Begin Source File -SOURCE=..\Stk\Clarinet.h +SOURCE=..\..\include\Brass.h # End Source File # Begin Source File -SOURCE=..\Stk\DCBlock.cpp +SOURCE=..\..\src\ByteSwap.cpp # End Source File # Begin Source File -SOURCE=..\Stk\DCBlock.h +SOURCE=..\..\include\ByteSwap.h # End Source File # Begin Source File -SOURCE=..\Stk\DLineA.cpp +SOURCE=..\..\src\Clarinet.cpp # End Source File # Begin Source File -SOURCE=..\Stk\DLineA.h +SOURCE=..\..\include\Clarinet.h # End Source File # Begin Source File -SOURCE=..\Stk\DLineL.cpp +SOURCE=..\..\src\Controller.cpp # End Source File # Begin Source File -SOURCE=..\Stk\DLineL.h +SOURCE=..\..\include\Controller.h # End Source File # Begin Source File -SOURCE=..\Stk\DLineN.cpp +SOURCE=..\..\src\DCBlock.cpp # End Source File # Begin Source File -SOURCE=..\Stk\DLineN.h +SOURCE=..\..\include\DCBlock.h # End Source File # Begin Source File -SOURCE=..\Stk\DrumSynt.cpp +SOURCE=..\..\src\DLineA.cpp # End Source File # Begin Source File -SOURCE=..\Stk\DrumSynt.h +SOURCE=..\..\include\DLineA.h # End Source File # Begin Source File -SOURCE=..\Stk\Envelope.cpp +SOURCE=..\..\src\DLineL.cpp # End Source File # Begin Source File -SOURCE=..\Stk\Envelope.h +SOURCE=..\..\include\DLineL.h # End Source File # Begin Source File -SOURCE=..\Stk\Filter.cpp +SOURCE=..\..\src\DLineN.cpp # End Source File # Begin Source File -SOURCE=..\Stk\Filter.h +SOURCE=..\..\include\DLineN.h # End Source File # Begin Source File -SOURCE=..\Stk\Flute.cpp +SOURCE=..\..\src\DrumSynt.cpp # End Source File # Begin Source File -SOURCE=..\Stk\Flute.h +SOURCE=..\..\include\DrumSynt.h # End Source File # Begin Source File -SOURCE=..\Stk\FM4Alg3.cpp +SOURCE=..\..\src\Envelope.cpp # End Source File # Begin Source File -SOURCE=..\Stk\FM4Alg3.h +SOURCE=..\..\include\Envelope.h # End Source File # Begin Source File -SOURCE=..\Stk\FM4Alg4.cpp +SOURCE=..\..\src\Filter.cpp # End Source File # Begin Source File -SOURCE=..\Stk\FM4Alg4.h +SOURCE=..\..\include\Filter.h # End Source File # Begin Source File -SOURCE=..\Stk\FM4Alg5.cpp +SOURCE=..\..\src\Flute.cpp # End Source File # Begin Source File -SOURCE=..\Stk\FM4Alg5.h +SOURCE=..\..\include\Flute.h # End Source File # Begin Source File -SOURCE=..\Stk\FM4Alg6.cpp +SOURCE=..\..\src\FM4Alg3.cpp # End Source File # Begin Source File -SOURCE=..\Stk\FM4Alg6.h +SOURCE=..\..\include\FM4Alg3.h # End Source File # Begin Source File -SOURCE=..\Stk\FM4Alg8.cpp +SOURCE=..\..\src\FM4Alg4.cpp # End Source File # Begin Source File -SOURCE=..\Stk\FM4Alg8.h +SOURCE=..\..\include\FM4Alg4.h # End Source File # Begin Source File -SOURCE=..\Stk\FM4Op.cpp +SOURCE=..\..\src\FM4Alg5.cpp # End Source File # Begin Source File -SOURCE=..\Stk\FM4Op.h +SOURCE=..\..\include\FM4Alg5.h # End Source File # Begin Source File -SOURCE=..\Stk\FMVoices.cpp +SOURCE=..\..\src\FM4Alg6.cpp # End Source File # Begin Source File -SOURCE=..\Stk\FMVoices.h +SOURCE=..\..\include\FM4Alg6.h # End Source File # Begin Source File -SOURCE=..\Stk\FormSwep.cpp +SOURCE=..\..\src\FM4Alg8.cpp # End Source File # Begin Source File -SOURCE=..\Stk\FormSwep.h +SOURCE=..\..\include\FM4Alg8.h # End Source File # Begin Source File -SOURCE=..\Stk\HeavyMtl.cpp +SOURCE=..\..\src\FM4Op.cpp # End Source File # Begin Source File -SOURCE=..\Stk\HeavyMtl.h +SOURCE=..\..\include\FM4Op.h # End Source File # Begin Source File -SOURCE=..\Stk\Instrmnt.cpp +SOURCE=..\..\src\FMVoices.cpp # End Source File # Begin Source File -SOURCE=..\Stk\Instrmnt.h +SOURCE=..\..\include\FMVoices.h # End Source File # Begin Source File -SOURCE=..\Stk\JCRev.cpp +SOURCE=..\..\src\FormSwep.cpp # End Source File # Begin Source File -SOURCE=..\Stk\JCRev.h +SOURCE=..\..\include\FormSwep.h # End Source File # Begin Source File -SOURCE=..\Stk\JetTabl.cpp +SOURCE=..\..\src\HeavyMtl.cpp # End Source File # Begin Source File -SOURCE=..\Stk\JetTabl.h +SOURCE=..\..\include\HeavyMtl.h # End Source File # Begin Source File -SOURCE=..\Stk\LipFilt.cpp +SOURCE=..\..\src\Instrmnt.cpp # End Source File # Begin Source File -SOURCE=..\Stk\LipFilt.h +SOURCE=..\..\include\Instrmnt.h # End Source File # Begin Source File -SOURCE=..\Stk\Mandolin.cpp +SOURCE=..\..\src\JetTabl.cpp # End Source File # Begin Source File -SOURCE=..\Stk\Mandolin.h +SOURCE=..\..\include\JetTabl.h # End Source File # Begin Source File -SOURCE=..\Stk\Marimba.cpp +SOURCE=..\..\src\LipFilt.cpp # End Source File # Begin Source File -SOURCE=..\Stk\Marimba.h +SOURCE=..\..\include\LipFilt.h # End Source File # Begin Source File -SOURCE=..\Stk\MatWvIn.cpp +SOURCE=..\..\src\Mandolin.cpp # End Source File # Begin Source File -SOURCE=..\Stk\MatWvIn.h +SOURCE=..\..\include\Mandolin.h # End Source File # Begin Source File -SOURCE=..\Stk\MatWvOut.cpp +SOURCE=..\..\src\MatWvIn.cpp # End Source File # Begin Source File -SOURCE=..\Stk\MatWvOut.h +SOURCE=..\..\include\MatWvIn.h # End Source File # Begin Source File -SOURCE=.\Miditabl.h +SOURCE=..\..\src\MatWvOut.cpp # End Source File # Begin Source File -SOURCE=..\Stk\Modal4.cpp +SOURCE=..\..\include\MatWvOut.h # End Source File # Begin Source File -SOURCE=..\Stk\Modal4.h +SOURCE=.\miditabl.h # End Source File # Begin Source File -SOURCE=..\Stk\Modulatr.cpp +SOURCE=..\..\src\Modal4.cpp # End Source File # Begin Source File -SOURCE=..\Stk\Modulatr.h +SOURCE=..\..\include\Modal4.h # End Source File # Begin Source File -SOURCE=..\Stk\Moog1.cpp +SOURCE=..\..\src\ModalBar.cpp # End Source File # Begin Source File -SOURCE=..\Stk\Moog1.h +SOURCE=..\..\include\ModalBar.h # End Source File # Begin Source File -SOURCE=..\Stk\Noise.cpp +SOURCE=..\..\src\Modulatr.cpp # End Source File # Begin Source File -SOURCE=..\Stk\Noise.h +SOURCE=..\..\include\Modulatr.h # End Source File # Begin Source File -SOURCE=..\Stk\NRev.cpp +SOURCE=..\..\src\Moog1.cpp # End Source File # Begin Source File -SOURCE=..\Stk\NRev.h +SOURCE=..\..\include\Moog1.h # End Source File # Begin Source File -SOURCE=..\Stk\Object.cpp +SOURCE=..\..\src\Noise.cpp # End Source File # Begin Source File -SOURCE=..\Stk\Object.h +SOURCE=..\..\include\Noise.h # End Source File # Begin Source File -SOURCE=..\Stk\OnePole.cpp +SOURCE=..\..\src\Object.cpp # End Source File # Begin Source File -SOURCE=..\Stk\OnePole.h +SOURCE=..\..\include\Object.h # End Source File # Begin Source File -SOURCE=..\Stk\OneZero.cpp +SOURCE=..\..\src\OnePole.cpp # End Source File # Begin Source File -SOURCE=..\Stk\OneZero.h +SOURCE=..\..\include\OnePole.h # End Source File # Begin Source File -SOURCE=..\Stk\PercFlut.cpp +SOURCE=..\..\src\OneZero.cpp # End Source File # Begin Source File -SOURCE=..\Stk\PercFlut.h +SOURCE=..\..\include\OneZero.h # End Source File # Begin Source File -SOURCE=..\Stk\phontabl.h +SOURCE=..\..\src\PercFlut.cpp # End Source File # Begin Source File -SOURCE=..\Stk\Plucked.cpp +SOURCE=..\..\include\PercFlut.h # End Source File # Begin Source File -SOURCE=..\Stk\Plucked.h +SOURCE=..\..\include\phontabl.h # End Source File # Begin Source File -SOURCE=..\Stk\Plucked2.cpp +SOURCE=..\..\src\Plucked.cpp # End Source File # Begin Source File -SOURCE=..\Stk\Plucked2.h +SOURCE=..\..\include\Plucked.h # End Source File # Begin Source File -SOURCE=..\Stk\PoleZero.cpp +SOURCE=..\..\src\Plucked2.cpp # End Source File # Begin Source File -SOURCE=..\Stk\PoleZero.h +SOURCE=..\..\include\Plucked2.h # End Source File # Begin Source File -SOURCE=..\Stk\PRCRev.cpp +SOURCE=..\..\src\PoleZero.cpp # End Source File # Begin Source File -SOURCE=..\Stk\PRCRev.h +SOURCE=..\..\include\PoleZero.h # End Source File # Begin Source File -SOURCE=..\Stk\RawWvIn.cpp +SOURCE=..\..\src\PRCRev.cpp # End Source File # Begin Source File -SOURCE=..\Stk\RawWvIn.h +SOURCE=..\..\include\PRCRev.h # End Source File # Begin Source File -SOURCE=..\Stk\RawWvOut.cpp +SOURCE=..\..\src\RawWvIn.cpp # End Source File # Begin Source File -SOURCE=..\Stk\RawWvOut.h +SOURCE=..\..\include\RawWvIn.h # End Source File # Begin Source File -SOURCE=..\Stk\ReedTabl.cpp +SOURCE=..\..\src\RawWvOut.cpp # End Source File # Begin Source File -SOURCE=..\Stk\ReedTabl.h +SOURCE=..\..\include\RawWvOut.h # End Source File # Begin Source File -SOURCE=..\Stk\Reverb.cpp +SOURCE=..\..\src\ReedTabl.cpp # End Source File # Begin Source File -SOURCE=..\Stk\Reverb.h +SOURCE=..\..\include\ReedTabl.h # End Source File # Begin Source File -SOURCE=..\Stk\Rhodey.cpp +SOURCE=..\..\src\Reverb.cpp # End Source File # Begin Source File -SOURCE=..\Stk\Rhodey.h +SOURCE=..\..\include\Reverb.h # End Source File # Begin Source File -SOURCE=..\Stk\RTDuplex.cpp +SOURCE=..\..\src\Rhodey.cpp # End Source File # Begin Source File -SOURCE=..\Stk\RTDuplex.h +SOURCE=..\..\include\Rhodey.h # End Source File # Begin Source File -SOURCE=..\Stk\RTSoundIO.cpp +SOURCE=..\..\src\RtAudio.cpp # End Source File # Begin Source File -SOURCE=..\Stk\RTSoundIO.h +SOURCE=..\..\include\RtAudio.h # End Source File # Begin Source File -SOURCE=..\Stk\RTWvIn.cpp +SOURCE=..\..\src\RtMidi.cpp # End Source File # Begin Source File -SOURCE=..\Stk\RTWvIn.h +SOURCE=..\..\include\RtMidi.h # End Source File # Begin Source File -SOURCE=..\Stk\RTWvOut.cpp +SOURCE=..\..\src\RtWvIn.cpp # End Source File # Begin Source File -SOURCE=..\Stk\RTWvOut.h +SOURCE=..\..\include\RtWvIn.h # End Source File # Begin Source File -SOURCE=..\Stk\Sampler.cpp +SOURCE=..\..\src\RtWvOut.cpp # End Source File # Begin Source File -SOURCE=..\Stk\Sampler.h +SOURCE=..\..\include\RtWvOut.h # End Source File # Begin Source File -SOURCE=..\Stk\SamplFlt.cpp +SOURCE=..\..\src\Sampler.cpp # End Source File # Begin Source File -SOURCE=..\Stk\SamplFlt.h +SOURCE=..\..\include\Sampler.h # End Source File # Begin Source File -SOURCE=..\Stk\Shakers.cpp +SOURCE=..\..\src\SamplFlt.cpp # End Source File # Begin Source File -SOURCE=..\Stk\Shakers.h +SOURCE=..\..\include\SamplFlt.h # End Source File # Begin Source File -SOURCE=..\Stk\Simple.cpp +SOURCE=..\..\src\Shakers.cpp # End Source File # Begin Source File -SOURCE=..\Stk\Simple.h +SOURCE=..\..\include\Shakers.h # End Source File # Begin Source File -SOURCE=..\Stk\SingWave.cpp +SOURCE=..\..\src\Simple.cpp # End Source File # Begin Source File -SOURCE=..\Stk\SingWave.h +SOURCE=..\..\include\Simple.h # End Source File # Begin Source File -SOURCE=..\Stk\SKINI11.cpp +SOURCE=..\..\src\SingWave.cpp # End Source File # Begin Source File -SOURCE=..\Stk\SKINI11.h +SOURCE=..\..\include\SingWave.h # End Source File # Begin Source File -SOURCE=..\Stk\SndWvIn.cpp +SOURCE=..\..\src\SKINI11.cpp # End Source File # Begin Source File -SOURCE=..\Stk\SndWvIn.h +SOURCE=..\..\include\SKINI11.h # End Source File # Begin Source File -SOURCE=..\Stk\SndWvOut.cpp +SOURCE=..\..\src\SndWvIn.cpp # End Source File # Begin Source File -SOURCE=..\Stk\SndWvOut.h +SOURCE=..\..\include\SndWvIn.h # End Source File # Begin Source File -SOURCE=..\Stk\SubNoise.cpp +SOURCE=..\..\src\SndWvOut.cpp # End Source File # Begin Source File -SOURCE=..\Stk\SubNoise.h +SOURCE=..\..\include\SndWvOut.h # End Source File # Begin Source File -SOURCE=..\Stk\swapstuf.cpp +SOURCE=..\..\src\StkError.cpp # End Source File # Begin Source File -SOURCE=..\Stk\swapstuf.h +SOURCE=..\..\include\StkError.h +# End Source File +# Begin Source File + +SOURCE=..\..\src\SubNoise.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\include\SubNoise.h # End Source File # Begin Source File @@ -624,35 +633,27 @@ SOURCE=.\syntmono.cpp # End Source File # Begin Source File -SOURCE=.\threads.cpp +SOURCE=..\..\src\TubeBell.cpp # End Source File # Begin Source File -SOURCE=.\threads.h +SOURCE=..\..\include\TubeBell.h # End Source File # Begin Source File -SOURCE=..\Stk\TubeBell.cpp +SOURCE=..\..\src\TwoPole.cpp # End Source File # Begin Source File -SOURCE=..\Stk\TubeBell.h +SOURCE=..\..\include\TwoPole.h # End Source File # Begin Source File -SOURCE=..\Stk\TwoPole.cpp +SOURCE=..\..\src\TwoZero.cpp # End Source File # Begin Source File -SOURCE=..\Stk\TwoPole.h -# End Source File -# Begin Source File - -SOURCE=..\Stk\TwoZero.cpp -# End Source File -# Begin Source File - -SOURCE=..\Stk\TwoZero.h +SOURCE=..\..\include\TwoZero.h # End Source File # Begin Source File @@ -664,67 +665,51 @@ SOURCE=.\utilities.h # End Source File # Begin Source File -SOURCE=..\Stk\Vibraphn.cpp +SOURCE=..\..\src\VoicForm.cpp # End Source File # Begin Source File -SOURCE=..\Stk\Vibraphn.h +SOURCE=..\..\include\VoicForm.h # End Source File # Begin Source File -SOURCE=..\Stk\VoicForm.cpp +SOURCE=..\..\src\WavWvIn.cpp # End Source File # Begin Source File -SOURCE=..\Stk\VoicForm.h +SOURCE=..\..\include\WavWvIn.h # End Source File # Begin Source File -SOURCE=..\Stk\VoicMang.cpp +SOURCE=..\..\src\WavWvOut.cpp # End Source File # Begin Source File -SOURCE=..\Stk\VoicMang.h +SOURCE=..\..\include\WavWvOut.h # End Source File # Begin Source File -SOURCE=..\Stk\WavWvIn.cpp +SOURCE=..\..\src\Wurley.cpp # End Source File # Begin Source File -SOURCE=..\Stk\WavWvIn.h +SOURCE=..\..\include\Wurley.h # End Source File # Begin Source File -SOURCE=..\Stk\WavWvOut.cpp +SOURCE=..\..\src\WvIn.cpp # End Source File # Begin Source File -SOURCE=..\Stk\WavWvOut.h +SOURCE=..\..\include\WvIn.h # End Source File # Begin Source File -SOURCE=..\Stk\Wurley.cpp +SOURCE=..\..\src\WvOut.cpp # End Source File # Begin Source File -SOURCE=..\Stk\Wurley.h -# End Source File -# Begin Source File - -SOURCE=..\Stk\WvIn.cpp -# End Source File -# Begin Source File - -SOURCE=..\Stk\WvIn.h -# End Source File -# Begin Source File - -SOURCE=..\Stk\WvOut.cpp -# End Source File -# Begin Source File - -SOURCE=..\Stk\WvOut.h +SOURCE=..\..\include\WvOut.h # End Source File # End Target # End Project diff --git a/syntmono/tcl/TCLBowedBar.tcl b/projects/syntmono/tcl/TCLBowedBar.tcl similarity index 88% rename from syntmono/tcl/TCLBowedBar.tcl rename to projects/syntmono/tcl/TCLBowedBar.tcl index 9591b45..e5c5353 100644 --- a/syntmono/tcl/TCLBowedBar.tcl +++ b/projects/syntmono/tcl/TCLBowedBar.tcl @@ -30,7 +30,7 @@ frame .leftsid -bg black proc myExit {} { global pitch outID - puts $outID [format "NoteOff 0.0 1 %f 127" $pitch ] + puts $outID [format "NoteOff -1.0 1 %f 127" $pitch ] flush $outID puts $outID [format "ExitProgram"] flush $outID @@ -40,20 +40,20 @@ proc myExit {} { proc noteOn {pitchVal pressVal} { global outID - puts $outID [format "NoteOn 0.0 1 %f %f" $pitchVal $pressVal] + puts $outID [format "NoteOn -1.0 1 %f %f" $pitchVal $pressVal] flush $outID } proc noteOff {pitchVal pressVal} { global outID - puts $outID [format "NoteOff 0.0 1 %f %f" $pitchVal $pressVal] + puts $outID [format "NoteOff -1.0 1 %f %f" $pitchVal $pressVal] flush $outID } proc patchChange {value} { global outID press cont1 cont4 cont11 set patch $value - puts $outID [format "ProgramChange 0.0 1 %i" $value] + puts $outID [format "ProgramChange -1.0 1 %i" $value] flush $outID set cont1 64.0 set cont4 64.0 @@ -68,27 +68,27 @@ proc printWhatz {tag value1 value2 } { proc changePress {value} { global outID - puts $outID [format "AfterTouch 0.0 1 %f" $value] + puts $outID [format "AfterTouch -1.0 1 %f" $value] flush $outID } proc changePitch {value} { global outID - puts $outID [format "PitchBend 0.0 1 %.3f" $value] + puts $outID [format "PitchBend -1.0 1 %.3f" $value] flush $outID } proc activateVel {} { global pitch noteOn $pitch 127 - printWhatz "ControlChange 0.0 1 " 65 0 + printWhatz "ControlChange -1.0 1 " 65 0 } # Configure sliders frame .press -bg grey66 button .press.pos -text Pos. -bg grey66 \ --command {printWhatz "ControlChange 0.0 1 " 65 127} +-command {printWhatz "ControlChange -1.0 1 " 65 127} button .press.vel -text Vel. -bg grey66 \ -command activateVel @@ -103,25 +103,25 @@ scale .pitch -from 0 -to 128 -length 200 \ -tickinterval 32 -showvalue true -bg grey66 scale .cont2 -from 0 -to 128 -length 200 \ --command {printWhatz "ControlChange 0.0 1 " 2} \ +-command {printWhatz "ControlChange -1.0 1 " 2} \ -orient horizontal -label "Bowing Pressure" \ -tickinterval 32 -showvalue true -bg grey66 \ -variable cont2 scale .cont4 -from 0 -to 128 -length 200 \ --command {printWhatz "ControlChange 0.0 1 " 4} \ +-command {printWhatz "ControlChange -1.0 1 " 4} \ -orient horizontal -label "Strike/Bow Position" \ -tickinterval 32 -showvalue true -bg grey66 \ -variable cont4 scale .cont11 -from 0 -to 128 -length 200 \ --command {printWhatz "ControlChange 0.0 1 " 11} \ +-command {printWhatz "ControlChange -1.0 1 " 11} \ -orient horizontal -label "Integration" \ -tickinterval 32 -showvalue true -bg grey66 \ -variable cont11 scale .reson -from 0 -to 128 -length 200 \ --command {printWhatz "ControlChange 0.0 1 " 1} \ +-command {printWhatz "ControlChange -1.0 1 " 1} \ -orient horizontal -label "Mode Resonance" \ -tickinterval 32 -showvalue true -bg grey66 \ -variable cont1 @@ -130,10 +130,10 @@ scale .reson -from 0 -to 128 -length 200 \ frame .bowstruk -bg black radiobutton .bowstruk.bowed -text Bowed -bg grey66 \ --command {printWhatz "ControlChange 0.0 1 " 64 127} \ +-command {printWhatz "ControlChange -1.0 1 " 64 127} \ -value 1 -variable struckbow radiobutton .bowstruk.struck -text Struck -bg grey66 \ --command {printWhatz "ControlChange 0.0 1 " 64 0} \ +-command {printWhatz "ControlChange -1.0 1 " 64 0} \ -value 0 -variable struckbow pack .press.pos -side left diff --git a/syntmono/tcl/TCLDemo.tcl b/projects/syntmono/tcl/TCLDemo.tcl similarity index 77% rename from syntmono/tcl/TCLDemo.tcl rename to projects/syntmono/tcl/TCLDemo.tcl index 4d8ac1a..192808b 100644 --- a/syntmono/tcl/TCLDemo.tcl +++ b/projects/syntmono/tcl/TCLDemo.tcl @@ -9,10 +9,12 @@ set cont1 0.0 set cont2 10.0 set cont4 20.0 set cont11 64.0 +set cont44 24.0 set outID "stdout" set commtype "stdout" set patchnum 0 set oldpatch 0 +set temp 0 # Configure main window wm title . "STK Demo GUI" @@ -41,60 +43,71 @@ menu .menu.instrument -tearoff 0 -value 2 -command { patchChange $patchnum } .menu.instrument add radio -label "Bowed String" -variable patchnum \ -value 3 -command { patchChange $patchnum } -.menu.instrument add radio -label "Plucked String" -variable patchnum \ +.menu.instrument add radio -label "BlowHole" -variable patchnum \ -value 4 -command { patchChange $patchnum } -.menu.instrument add radio -label "Mandolin" -variable patchnum \ +.menu.instrument add radio -label "Plucked String" -variable patchnum \ -value 5 -command { patchChange $patchnum } -.menu.instrument add radio -label "Marimba" -variable patchnum \ +.menu.instrument add radio -label "Mandolin" -variable patchnum \ -value 6 -command { patchChange $patchnum } -.menu.instrument add radio -label "Vibraphone" -variable patchnum \ - -value 7 -command { patchChange $patchnum } -.menu.instrument add radio -label "Agogo Bell" -variable patchnum \ - -value 8 -command { patchChange $patchnum } .menu.instrument add radio -label "Rhodey" -variable patchnum \ - -value 9 -command { patchChange $patchnum } + -value 7 -command { patchChange $patchnum } .menu.instrument add radio -label "Wurley" -variable patchnum \ - -value 10 -command { patchChange $patchnum } + -value 8 -command { patchChange $patchnum } .menu.instrument add radio -label "Tubular Bell" -variable patchnum \ - -value 11 -command { patchChange $patchnum } + -value 9 -command { patchChange $patchnum } .menu.instrument add radio -label "Heavy Metal" -variable patchnum \ - -value 12 -command { patchChange $patchnum } + -value 10 -command { patchChange $patchnum } .menu.instrument add radio -label "Percussive Flute" -variable patchnum \ - -value 13 -command { patchChange $patchnum } + -value 11 -command { patchChange $patchnum } .menu.instrument add radio -label "B3 Organ" -variable patchnum \ - -value 14 -command { patchChange $patchnum } + -value 12 -command { patchChange $patchnum } .menu.instrument add radio -label "Moog" -variable patchnum \ - -value 15 -command { patchChange $patchnum } + -value 13 -command { patchChange $patchnum } .menu.instrument add radio -label "FM Voices" -variable patchnum \ - -value 16 -command { patchChange $patchnum } + -value 14 -command { patchChange $patchnum } .menu.instrument add radio -label "Drum Kit" -variable patchnum \ - -value 18 -command { patchChange $patchnum } + -value 16 -command { patchChange $patchnum } .menu.instrument add radio -label "Maraca" -variable patchnum \ - -value 19 -command { patchChange $patchnum } + -value 17 -command { patchChange $patchnum } .menu.instrument add radio -label "Sekere" -variable patchnum \ - -value 20 -command { patchChange $patchnum } + -value 18 -command { patchChange $patchnum } .menu.instrument add radio -label "Cabasa" -variable patchnum \ - -value 21 -command { patchChange $patchnum } + -value 19 -command { patchChange $patchnum } .menu.instrument add radio -label "Bamboo" -variable patchnum \ - -value 22 -command { patchChange $patchnum } + -value 20 -command { patchChange $patchnum } .menu.instrument add radio -label "Waterdrop" -variable patchnum \ - -value 23 -command { patchChange $patchnum } + -value 21 -command { patchChange $patchnum } .menu.instrument add radio -label "Tambourine" -variable patchnum \ - -value 24 -command { patchChange $patchnum } + -value 22 -command { patchChange $patchnum } .menu.instrument add radio -label "Sleigh Bell" -variable patchnum \ - -value 25 -command { patchChange $patchnum } + -value 23 -command { patchChange $patchnum } .menu.instrument add radio -label "Guiro" -variable patchnum \ - -value 26 -command { patchChange $patchnum } + -value 24 -command { patchChange $patchnum } .menu.instrument add radio -label "Sticks" -variable patchnum \ - -value 27 -command { patchChange $patchnum } + -value 25 -command { patchChange $patchnum } .menu.instrument add radio -label "Crunch" -variable patchnum \ - -value 28 -command { patchChange $patchnum } + -value 26 -command { patchChange $patchnum } .menu.instrument add radio -label "Wrench" -variable patchnum \ - -value 29 -command { patchChange $patchnum } + -value 27 -command { patchChange $patchnum } .menu.instrument add radio -label "SandPaper" -variable patchnum \ - -value 30 -command { patchChange $patchnum } + -value 28 -command { patchChange $patchnum } .menu.instrument add radio -label "CokeCan" -variable patchnum \ + -value 29 -command { patchChange $patchnum } +.menu.instrument add radio -label "Marimba" -variable patchnum \ + -value 30 -command { patchChange $patchnum } +.menu.instrument add radio -label "Vibraphone" -variable patchnum \ -value 31 -command { patchChange $patchnum } +.menu.instrument add radio -label "Agogo Bell" -variable patchnum \ + -value 32 -command { patchChange $patchnum } +.menu.instrument add radio -label "Wood 1" -variable patchnum \ + -value 33 -command { patchChange $patchnum } +.menu.instrument add radio -label "Reso" -variable patchnum \ + -value 34 -command { patchChange $patchnum } +.menu.instrument add radio -label "Wood 2" -variable patchnum \ + -value 35 -command { patchChange $patchnum } +.menu.instrument add radio -label "Beats" -variable patchnum \ + -value 36 -command { patchChange $patchnum } + . configure -menu .menu # Configure bitmap display @@ -104,9 +117,8 @@ if {[file isdirectory bitmaps]} { set bitmappath tcl/bitmaps } -button .pretty -bitmap @$bitmappath/prcFunny.xbm \ +button .pretty -bitmap @$bitmappath/Klar.xbm \ -background white -foreground black -.pretty config -bitmap @$bitmappath/prc.xbm pack .pretty -padx 5 -pady 10 # Configure "note-on" buttons @@ -121,6 +133,18 @@ pack .noteOn.exit -side left -padx 5 -pady 10 pack .noteOn +# Configure reverb slider +frame .reverb -bg black + +scale .reverb.mix -from 0 -to 128 -length 200 \ +-command {printWhatz "ControlChange -1.0 1 " 44} \ +-orient horizontal -label "Reverb Mix" \ +-tickinterval 32 -showvalue true -bg grey66 \ +-variable cont44 + +pack .reverb.mix -padx 10 -pady 10 +pack .reverb + # Configure sliders frame .left -bg black frame .right -bg black @@ -136,25 +160,25 @@ scale .left.pitch -from 0 -to 128 -length 200 \ -tickinterval 32 -showvalue true -bg grey66 scale .left.cont2 -from 0 -to 128 -length 200 \ --command {printWhatz "ControlChange 0.0 1 " 2} \ +-command {printWhatz "ControlChange -1.0 1 " 2} \ -orient horizontal -label "Reed Stiffness" \ -tickinterval 32 -showvalue true -bg grey66 \ -variable cont2 scale .right.cont4 -from 0 -to 128 -length 200 \ --command {printWhatz "ControlChange 0.0 1 " 4} \ +-command {printWhatz "ControlChange -1.0 1 " 4} \ -orient horizontal -label "Breath Noise" \ -tickinterval 32 -showvalue true -bg grey66 \ -variable cont4 scale .right.cont11 -from 0 -to 128 -length 200 \ --command {printWhatz "ControlChange 0.0 1 " 11} \ +-command {printWhatz "ControlChange -1.0 1 " 11} \ -orient horizontal -label "Vibrato Rate" \ -tickinterval 32 -showvalue true -bg grey66 \ -variable cont11 scale .right.cont1 -from 0 -to 128 -length 200 \ --command {printWhatz "ControlChange 0.0 1 " 1} \ +-command {printWhatz "ControlChange -1.0 1 " 1} \ -orient horizontal -label "Vibrato Amount" \ -tickinterval 32 -showvalue true -bg grey66 \ -variable cont1 @@ -174,8 +198,6 @@ set p .drumwindow proc myExit {} { global pitch outID - puts $outID [format "NoteOff 0.0 1 %3.2f 127" $pitch ] - flush $outID puts $outID [format "ExitProgram"] flush $outID close $outID @@ -184,28 +206,31 @@ proc myExit {} { proc noteOn {pitchVal pressVal} { global outID - puts $outID [format "NoteOn 0.0 1 %3.2f %3.2f" $pitchVal $pressVal] + puts $outID [format "NoteOn -1.0 1 %3.2f %3.2f" $pitchVal $pressVal] flush $outID } proc noteOff {pitchVal pressVal} { global outID - puts $outID [format "NoteOff 0.0 1 %3.2f %3.2f" $pitchVal $pressVal] + puts $outID [format "NoteOff -1.0 1 %3.2f %3.2f" $pitchVal $pressVal] flush $outID } proc patchChange {value} { - global outID bitmappath cont1 cont2 cont4 cont11 oldpatch press pitch + global outID bitmappath cont1 cont2 cont4 cont11 oldpatch press pitch temp if {$value!=$oldpatch} { - if {$value < 19} { - puts $outID [format "ProgramChange 0.0 1 %2i" $value] + if {$value < 17} { + puts $outID [format "ProgramChange -1.0 1 %2i" $value] flush $outID } - if {$value > 18 && $oldpatch < 19} { - puts $outID [format "ProgramChange 0.0 1 19"] + if {($value > 16 && $value < 30) && ($oldpatch < 17 || $oldpatch > 29)} { + puts $outID [format "ProgramChange -1.0 1 17"] + flush $outID + } + if {$value > 29 && $oldpatch < 30} { + puts $outID [format "ProgramChange -1.0 1 19"] flush $outID } - set oldpatch $value # This stuff below sets up the correct bitmaps, slider labels, and control # parameters. if {$value==0} { # Clarinet @@ -220,10 +245,10 @@ proc patchChange {value} { set cont2 64.0 set cont4 20.0 set cont11 64.0 - printWhatz "ControlChange 0.0 1 " 1 $cont1 - printWhatz "ControlChange 0.0 1 " 2 $cont2 - printWhatz "ControlChange 0.0 1 " 4 $cont4 - printWhatz "ControlChange 0.0 1 " 11 $cont11 + printWhatz "ControlChange -1.0 1 " 1 $cont1 + printWhatz "ControlChange -1.0 1 " 2 $cont2 + printWhatz "ControlChange -1.0 1 " 4 $cont4 + printWhatz "ControlChange -1.0 1 " 11 $cont11 } if {$value==1} { # Flute .pretty config -bitmap @$bitmappath/KFloot.xbm @@ -237,10 +262,10 @@ proc patchChange {value} { set cont2 64.0 set cont4 20.0 set cont11 64.0 - printWhatz "ControlChange 0.0 1 " 1 $cont1 - printWhatz "ControlChange 0.0 1 " 2 $cont2 - printWhatz "ControlChange 0.0 1 " 4 $cont4 - printWhatz "ControlChange 0.0 1 " 11 $cont11 + printWhatz "ControlChange -1.0 1 " 1 $cont1 + printWhatz "ControlChange -1.0 1 " 2 $cont2 + printWhatz "ControlChange -1.0 1 " 4 $cont4 + printWhatz "ControlChange -1.0 1 " 11 $cont11 } if {$value==2} { # Brass .pretty config -bitmap @$bitmappath/KHose.xbm @@ -254,11 +279,12 @@ proc patchChange {value} { set cont2 64.0 set cont4 20.0 set cont11 64.0 - printWhatz "ControlChange 0.0 1 " 1 $cont1 - printWhatz "ControlChange 0.0 1 " 2 $cont2 - printWhatz "ControlChange 0.0 1 " 4 $cont4 - printWhatz "ControlChange 0.0 1 " 11 $cont11 + printWhatz "ControlChange -1.0 1 " 1 $cont1 + printWhatz "ControlChange -1.0 1 " 2 $cont2 + printWhatz "ControlChange -1.0 1 " 4 $cont4 + printWhatz "ControlChange -1.0 1 " 11 $cont11 } + if {$value==3} { # Bowed String .pretty config -bitmap @$bitmappath/KFiddl.xbm .left.bPressure config -state normal -label "Volume" @@ -271,12 +297,29 @@ proc patchChange {value} { set cont2 64.0 set cont4 64.0 set cont11 64.0 - printWhatz "ControlChange 0.0 1 " 1 $cont1 - printWhatz "ControlChange 0.0 1 " 2 $cont2 - printWhatz "ControlChange 0.0 1 " 4 $cont4 - printWhatz "ControlChange 0.0 1 " 11 $cont11 + printWhatz "ControlChange -1.0 1 " 1 $cont1 + printWhatz "ControlChange -1.0 1 " 2 $cont2 + printWhatz "ControlChange -1.0 1 " 4 $cont4 + printWhatz "ControlChange -1.0 1 " 11 $cont11 } - if {$value==4} { # Yer Basic Pluck + if {$value==4} { # BlowHole + .pretty config -bitmap @$bitmappath/Klar.xbm + .left.bPressure config -state normal -label "Breath Pressure" + .left.pitch config -state normal -label "MIDI Note Number" + .left.cont2 config -state normal -label "Reed Stiffness" + .right.cont4 config -state normal -label "Breath Noise" + .right.cont11 config -state normal -label "Tonehole Openness" + .right.cont1 config -state normal -label "Register Vent Openness" + set cont1 0.0 + set cont2 64.0 + set cont4 20.0 + set cont11 0.0 + printWhatz "ControlChange -1.0 1 " 1 $cont1 + printWhatz "ControlChange -1.0 1 " 2 $cont2 + printWhatz "ControlChange -1.0 1 " 4 $cont4 + printWhatz "ControlChange -1.0 1 " 11 $cont11 + } + if {$value==5} { # Yer Basic Pluck .pretty config -bitmap @$bitmappath/KPluk.xbm .left.bPressure config -state disabled -label "Disabled" .left.pitch config -state normal -label "MIDI Note Number" @@ -285,7 +328,7 @@ proc patchChange {value} { .right.cont11 config -state disabled -label "Disabled" .right.cont1 config -state disabled -label "Disabled" } - if {$value==5} { # Mandolin + if {$value==6} { # Mandolin .pretty config -bitmap @$bitmappath/KPluk.xbm .left.bPressure config -state normal -label "Microphone Position" .left.pitch config -state normal -label "MIDI Note Number" @@ -298,22 +341,13 @@ proc patchChange {value} { set cont4 64.0 set cont11 96.0 set press 64.0 - printWhatz "ControlChange 0.0 1 " 1 $cont1 - printWhatz "ControlChange 0.0 1 " 2 $cont2 - printWhatz "ControlChange 0.0 1 " 4 $cont4 - printWhatz "ControlChange 0.0 1 " 11 $cont11 + printWhatz "ControlChange -1.0 1 " 1 $cont1 + printWhatz "ControlChange -1.0 1 " 2 $cont2 + printWhatz "ControlChange -1.0 1 " 4 $cont4 + printWhatz "ControlChange -1.0 1 " 11 $cont11 changePress $press } - if {$value>=6 && $value<=8 } { # Modal Instruments - .pretty config -bitmap @$bitmappath/KModal.xbm - .left.bPressure config -state normal -label "Volume" - .left.pitch config -state normal -label "MIDI Note Number" - .left.cont2 config -label "Stick Hardness" - .right.cont4 config -label "Stick Position" - .right.cont11 config -state normal -label "Vibrato Frequency" - .right.cont1 config -state normal -label "Vibrato Amount" - } - if {$value>=9 && $value <=14} { # FM Instruments + if {$value>=7 && $value <=12} { # FM Instruments .pretty config -bitmap @$bitmappath/KFMod.xbm .left.bPressure config -state normal -label "Modulator ADSR Amplitudes" .left.pitch config -state normal -label "MIDI Note Number" @@ -322,7 +356,7 @@ proc patchChange {value} { .right.cont11 config -state normal -label "Vibrato Rate" .right.cont1 config -state normal -label "Vibrato Amount" } - if {$value==15} { # Moog + if {$value==13} { # Moog .pretty config -bitmap @$bitmappath/prcFunny.xbm .left.bPressure config -state normal -label "Volume" .left.pitch config -state normal -label "MIDI Note Number" @@ -331,7 +365,7 @@ proc patchChange {value} { .right.cont11 config -state normal -label "Vibrato Rate" .right.cont1 config -state normal -label "Vibrato Amount" } - if {$value==16} { # FM Voices + if {$value==14} { # FM Voices .pretty config -bitmap @$bitmappath/KVoiceFM.xbm .left.bPressure config -state normal -label "Loudness (Spectral Tilt)" .left.pitch config -state normal -label "MIDI Note Number" @@ -340,7 +374,7 @@ proc patchChange {value} { .right.cont11 config -state normal -label "Vibrato Rate" .right.cont1 config -state normal -label "Vibrato Amount" } - if {$value==18} { # Drum Kit + if {$value==16} { # Drum Kit # Given the vastly different interface for the Drum Kit, we open # a new GUI popup window with the appropriate controls and lock # focus there until the user hits the "Close" button. We then @@ -402,63 +436,89 @@ proc patchChange {value} { pack $p.buttons.right -side right -pady 5 -padx 5 pack $p.buttons -padx 5 -pady 10 + set temp $oldpatch button $p.close -text "Close" -bg grey66 \ -command { destroy $p - set patchnum 0 + set patchnum $temp patchChange $patchnum} pack $p.close -side bottom -padx 5 -pady 10 } - if {$value>=19 && $value <=31} { # Shakers + if {$value>=17 && $value <=29} { # Shakers .pretty config -bitmap @$bitmappath/phism.xbm .left.bPressure config -state normal -label "Shake Energy" .left.pitch config -state disabled -label "Disabled" .left.cont2 config -state disabled -label "Disabled" - .right.cont4 config -state normal -label "(<--High) Damping (Low-->)" - .right.cont11 config -state normal -label "Number of Objects" + .right.cont4 config -state normal -label "Number of Objects" + .right.cont11 config -state normal -label "(<--High) Damping (Low-->)" .right.cont1 config -state normal -label "Resonance Center Frequency" switch $value { - 19 { + 17 { set pitch 0 .pretty config -bitmap @$bitmappath/maraca.xbm } - 20 {set pitch 2} - 21 { + 18 {set pitch 2} + 19 { set pitch 1 .pretty config -bitmap @$bitmappath/cabasa.xbm } - 22 { + 20 { set pitch 5 .pretty config -bitmap @$bitmappath/bamboo.xbm } - 23 {set pitch 4} - 24 { + 21 {set pitch 4} + 22 { set pitch 6 .pretty config -bitmap @$bitmappath/tambourine.xbm } - 25 { + 23 { set pitch 7 .pretty config -bitmap @$bitmappath/sleighbell.xbm } - 26 { + 24 { set pitch 3 .pretty config -bitmap @$bitmappath/guiro.xbm } - 27 {set pitch 8} - 28 {set pitch 9} - 29 { + 25 {set pitch 8} + 26 {set pitch 9} + 27 { set pitch 10 .pretty config -bitmap @$bitmappath/rachet.xbm } - 30 {set pitch 11} - 31 {set pitch 12} + 28 {set pitch 11} + 29 {set pitch 12} } set cont1 64.0 set cont2 64.0 set cont4 64.0 set cont11 64.0 - puts $outID [format "NoteOn 0.0 1 %3.2f %3.2f" $pitch $press] + puts $outID [format "NoteOn -1.0 1 %3.2f %3.2f" $pitch $press] flush $outID } + if {$value>=30 && $value<=36 } { # Modal Instruments + .pretty config -bitmap @$bitmappath/KModal.xbm + .left.bPressure config -state normal -label "Strike Vigor" + .left.pitch config -state normal -label "MIDI Note Number" + .left.cont2 config -state normal -label "Stick Hardness" + .right.cont4 config -state normal -label "Stick Position" + .right.cont11 config -state normal -label "Vibrato Frequency" + .right.cont1 config -state normal -label "Direct Stick Mix" + switch $value { + 30 {set preset 0} + 31 {set preset 1} + 32 {set preset 2} + 33 {set preset 3} + 34 {set preset 4} + 35 {set preset 5} + 36 {set preset 6} + } + set cont1 0.0 + set cont2 64.0 + set cont4 64.0 + set cont11 64.0 + puts $outID [format "ControlChange -1.0 1 16 %3.2f" $preset] + flush $outID + } + set oldpatch $value } } @@ -472,7 +532,7 @@ bind . +myExit proc playDrum {value} { global velocity outID - puts $outID [format "NoteOn 0.0 1 %3i %3.2f" $value $velocity] + puts $outID [format "NoteOn -1.0 1 %3i %3.2f" $value $velocity] flush $outID } @@ -484,17 +544,17 @@ proc printWhatz {tag value1 value2 } { proc changePress {value} { global outID patchnum - if { $patchnum == 5} { - puts $outID [format "ControlChange 0.0 1 411 %3.2f" $value] + if { $patchnum == 6} { + puts $outID [format "ControlChange -1.0 1 411 %3.2f" $value] } else { - puts $outID [format "AfterTouch 0.0 1 %3.2f" $value] + puts $outID [format "AfterTouch -1.0 1 %3.2f" $value] } flush $outID } proc changePitch {value} { global outID - puts $outID [format "PitchBend 0.0 1 %3.2f" $value] + puts $outID [format "PitchBend -1.0 1 %3.2f" $value] flush $outID } diff --git a/syntmono/tcl/TCLDrums.tcl b/projects/syntmono/tcl/TCLDrums.tcl similarity index 98% rename from syntmono/tcl/TCLDrums.tcl rename to projects/syntmono/tcl/TCLDrums.tcl index e827bc9..a650a37 100644 --- a/syntmono/tcl/TCLDrums.tcl +++ b/projects/syntmono/tcl/TCLDrums.tcl @@ -99,7 +99,7 @@ proc myExit {} { proc playDrum {value} { global press global outID - puts $outID [format "NoteOn 0.0 1 %i %f" $value $press] + puts $outID [format "NoteOn -1.0 1 %i %f" $value $press] flush $outID } diff --git a/syntmono/tcl/TCLStruk.tcl b/projects/syntmono/tcl/TCLModal.tcl similarity index 51% rename from syntmono/tcl/TCLStruk.tcl rename to projects/syntmono/tcl/TCLModal.tcl index 0ea7d94..1f82aa5 100644 --- a/syntmono/tcl/TCLStruk.tcl +++ b/projects/syntmono/tcl/TCLModal.tcl @@ -1,75 +1,82 @@ -# Tcl/Tk Plucked/Struck GUI for the Synthesis Toolkit (STK) - -# Set initial control values set pitch 64.0 set press 64.0 set cont1 0.0 set cont2 64.0 set cont4 64.0 -set cont11 127.0 +set cont11 64.0 +set cont99 24.0 set outID "stdout" set commtype "stdout" -set patchnum 5 +set preset 0 # Configure main window -wm title . "STK Struck-Pluck Model Controller" -wm iconname . "struck" +wm title . "STK Modal Bar GUI" +wm iconname . "modal" . config -bg black # Configure "communications" menu menu .menu -tearoff 0 menu .menu.communication -tearoff 0 .menu add cascade -label "Communication" -menu .menu.communication \ - -underline 0 + -underline 0 .menu.communication add radio -label "Console" -variable commtype \ - -value "stdout" -command { setComm } + -value "stdout" -command { setComm } .menu.communication add radio -label "Socket" -variable commtype \ - -value "socket" -command { setComm } -. configure -menu .menu + -value "socket" -command { setComm } -# Configure patch change buttons -frame .plucked -bg black -frame .modal -bg black -frame .fm -bg black +# Configure preset radio buttons +frame .radio1 -bg black +frame .radio2 -bg black -radiobutton .plucked.pluk1 -text Plucked -bg grey66 \ - -command { patchChange 4 } -variable patchnum -value 4 -radiobutton .plucked.mand -text Mandolin -bg grey66 \ --command { patchChange 5 } -variable patchnum -value 5 -radiobutton .modal.mari -text Marimba -bg grey66 \ --command { patchChange 6 } -variable patchnum -value 6 -radiobutton .modal.vibr -text Vibraphn -bg grey66 \ --command { patchChange 7 } -variable patchnum -value 7 -radiobutton .modal.agog -text AgogoBel -bg grey66 \ --command { patchChange 8 } -variable patchnum -value 8 -radiobutton .fm.rhod -text Rhodey -bg grey66 \ --command { patchChange 9 } -variable patchnum -value 9 -radiobutton .fm.wurl -text Wurley -bg grey66 \ --command { patchChange 10 } -variable patchnum -value 10 -radiobutton .fm.tube -text TubeBell -bg grey66 \ --command { patchChange 11 } -variable patchnum -value 11 +radiobutton .radio1.0 -text Marimba -bg grey66 \ + -command {printWhatz "ControlChange 0.0 1 " 16 0} \ + -variable preset -value 0 +radiobutton .radio1.1 -text Vibraphone -bg grey66 \ + -command {printWhatz "ControlChange 0.0 1 " 16 1} \ + -variable preset -value 1 +radiobutton .radio1.2 -text Agogo -bg grey66 \ + -command {printWhatz "ControlChange 0.0 1 " 16 2} \ + -variable preset -value 2 +radiobutton .radio1.3 -text Wood1 -bg grey66 \ + -command {printWhatz "ControlChange 0.0 1 " 16 3} \ + -variable preset -value 3 +radiobutton .radio2.4 -text Reso -bg grey66 \ + -command {printWhatz "ControlChange 0.0 1 " 16 4} \ + -variable preset -value 4 +radiobutton .radio2.5 -text Wood2 -bg grey66 \ + -command {printWhatz "ControlChange 0.0 1 " 16 5} \ + -variable preset -value 5 +radiobutton .radio2.6 -text Beats -bg grey66 \ + -command {printWhatz "ControlChange 0.0 1 " 16 6} \ + -variable preset -value 6 +radiobutton .radio2.7 -text 2Fix -bg grey66 \ + -command {printWhatz "ControlChange 0.0 1 " 16 7} \ + -variable preset -value 7 +radiobutton .radio2.8 -text Clump -bg grey66 \ + -command {printWhatz "ControlChange 0.0 1 " 16 8}\ + -variable preset -value 8 -pack .plucked.pluk1 -side left -padx 5 -pack .plucked.mand -side left -padx 5 -pady 10 -pack .plucked -pack .modal.mari -side left -padx 5 -pack .modal.vibr -side left -padx 5 -pack .modal.agog -side left -padx 5 -pady 10 -pack .modal -pack .fm.rhod -side left -padx 5 -pack .fm.wurl -side left -padx 5 -pack .fm.tube -side left -padx 5 -pady 10 -pack .fm +pack .radio1.0 -side left -padx 5 +pack .radio1.1 -side left -padx 5 -pady 10 +pack .radio1.2 -side left -padx 5 -pady 10 +pack .radio1.3 -side left -padx 5 -pady 10 +pack .radio1 +pack .radio2.4 -side left -padx 5 +pack .radio2.5 -side left -padx 5 +pack .radio2.6 -side left -padx 5 -pady 10 +pack .radio2.7 -side left -padx 5 -pady 10 +pack .radio2.8 -side left -padx 5 -pady 10 +pack .radio2 # Configure bitmap display if {[file isdirectory bitmaps]} { - set bitmappath bitmaps + set bitmappath bitmaps } else { - set bitmappath tcl/bitmaps + set bitmappath tcl/bitmaps } -button .pretty -bitmap @$bitmappath/prcFunny.xbm \ - -background white -foreground black -.pretty config -bitmap @$bitmappath/prc.xbm + +button .pretty -bitmap @$bitmappath/KModal.xbm \ + -background white -foreground black pack .pretty -padx 5 -pady 10 # Configure "note-on" buttons @@ -84,50 +91,62 @@ pack .noteOn.exit -side left -padx 5 -pady 10 pack .noteOn +# Configure reverb slider +frame .reverb -bg black + +scale .reverb.mix -from 0 -to 128 -length 200 \ +-command {printWhatz "ControlChange -1.0 1 " 99} \ +-orient horizontal -label "Reverb Mix" \ +-tickinterval 32 -showvalue true -bg grey66 \ +-variable cont99 + +pack .reverb.mix -padx 10 -pady 10 +pack .reverb + # Configure sliders frame .left -bg black frame .right -bg black -scale .left.bPressure -from 0 -to 128 -length 250 \ +scale .left.bPressure -from 0 -to 128 -length 200 \ -command {changePress } -variable press \ --orient horizontal -label "Breath Pressure" \ +-orient horizontal -label "Strike Vigor" \ -tickinterval 32 -showvalue true -bg grey66 -scale .left.pitch -from 0 -to 128 -length 250 \ --command {changePitch } -variable pitch \ +scale .left.pitch -from 0 -to 128 -length 200 \ +-command {changePitch } -variable pitch \ -orient horizontal -label "MIDI Note Number" \ -tickinterval 32 -showvalue true -bg grey66 -scale .left.cont1 -from 0 -to 128 -length 250 \ --command {printWhatz "ControlChange 0.0 1 " 2} \ --orient horizontal -label "Stick/Pick Hardness (Mand Body Size)" \ --tickinterval 32 -showvalue true -bg grey66 \ +scale .left.cont2 -from 0 -to 128 -length 200 \ +-command {printWhatz "ControlChange -1.0 1 " 2} \ +-orient horizontal -label "Stick Hardness" \ +-tickinterval 32 -showvalue true -bg grey66 \ -variable cont2 -scale .right.cont2 -from 0 -to 128 -length 250 \ --command {printWhatz "ControlChange 0.0 1 " 4} \ --orient horizontal -label "Strike/Pick Position" \ --tickinterval 32 -showvalue true -bg grey66 \ +scale .right.cont4 -from 0 -to 128 -length 200 \ +-command {printWhatz "ControlChange -1.0 1 " 4} \ +-orient horizontal -label "Stick Position" \ +-tickinterval 32 -showvalue true -bg grey66 \ -variable cont4 -scale .right.cont3 -from 0 -to 128 -length 250 \ --command {printWhatz "ControlChange 0.0 1 " 11} \ --orient horizontal -label "Vibrato Rate (String Sustain)" \ --tickinterval 32 -showvalue true -bg grey66 \ --variable cont11 +scale .right.cont11 -from 0 -to 128 -length 200 \ +-command {printWhatz "ControlChange -1.0 1 " 11} \ +-orient horizontal -label "Vibrato Rate" \ +-tickinterval 32 -showvalue true -bg grey66 \ +-variable cont11 -scale .right.vibrato -from 0 -to 128 -length 250 \ --command {printWhatz "ControlChange 0.0 1 " 1} \ --orient horizontal -label "Vibrato Amount (Mand Detune) " \ --tickinterval 32 -showvalue true -bg grey66\ +scale .right.cont1 -from 0 -to 128 -length 200 \ +-command {printWhatz "ControlChange -1.0 1 " 1} \ +-orient horizontal -label "Direct Stick Mix" \ +-tickinterval 32 -showvalue true -bg grey66 \ -variable cont1 pack .left.bPressure -padx 10 -pady 10 pack .left.pitch -padx 10 -pady 10 -pack .left.cont1 -padx 10 -pady 10 -pack .right.cont2 -padx 10 -pady 10 -pack .right.cont3 -padx 10 -pady 10 -pack .right.vibrato -padx 10 -pady 10 +pack .left.cont2 -padx 10 -pady 10 +pack .right.cont4 -padx 10 -pady 10 +pack .right.cont11 -padx 10 -pady 10 +pack .right.cont1 -padx 10 -pady 10 pack .left -side left pack .right -side right @@ -142,8 +161,6 @@ bind . +myExit proc myExit {} { global pitch outID - puts $outID [format "NoteOff 0.0 1 %f 127" $pitch ] - flush $outID puts $outID [format "ExitProgram"] flush $outID close $outID @@ -152,65 +169,31 @@ proc myExit {} { proc noteOn {pitchVal pressVal} { global outID - puts $outID [format "NoteOn 0.0 1 %f %f" $pitchVal $pressVal] + puts $outID [format "NoteOn -1.0 1 %3.2f %3.2f" $pitchVal $pressVal] flush $outID } proc noteOff {pitchVal pressVal} { global outID - puts $outID [format "NoteOff 0.0 1 %f %f" $pitchVal $pressVal] + puts $outID [format "NoteOff -1.0 1 %3.2f %3.2f" $pitchVal $pressVal] flush $outID } -proc patchChange {value} { - global outID bitmappath cont1 cont2 cont4 cont11 - puts $outID [format "ProgramChange 0.0 1 %i" $value] - if {$value==4} { - .pretty config -bitmap @$bitmappath/KPluk.xbm - } - if {$value==5} { - .pretty config -bitmap @$bitmappath/KPluk.xbm - } - if {$value==6} { - .pretty config -bitmap @$bitmappath/KModal.xbm - } - if {$value==7} { - .pretty config -bitmap @$bitmappath/KModal.xbm - } - if {$value==8} { - .pretty config -bitmap @$bitmappath/KModal.xbm - } - if {$value==9} { - .pretty config -bitmap @$bitmappath/KFMod.xbm - } - if {$value==10} { - .pretty config -bitmap @$bitmappath/KFMod.xbm - } - if {$value==11} { - .pretty config -bitmap @$bitmappath/KFMod.xbm - } - flush $outID - set cont1 0.0 - set cont2 20.0 - set cont4 64.0 - set cont11 64.0 -} - proc printWhatz {tag value1 value2 } { global outID - puts $outID [format "%s %i %f" $tag $value1 $value2] + puts $outID [format "%s %2i %3.2f" $tag $value1 $value2] flush $outID } proc changePress {value} { global outID - puts $outID [format "AfterTouch 0.0 1 %f" $value] + puts $outID [format "AfterTouch -1.0 1 %3.2f" $value] flush $outID } proc changePitch {value} { global outID - puts $outID [format "PitchBend 0.0 1 %.3f" $value] + puts $outID [format "PitchBend -1.0 1 %3.2f" $value] flush $outID } @@ -276,3 +259,5 @@ proc setComm {} { pack $d.buttons -side bottom -padx 5 -pady 10 } } + + diff --git a/syntmono/tcl/TCLPhys.tcl b/projects/syntmono/tcl/TCLPhys.tcl similarity index 92% rename from syntmono/tcl/TCLPhys.tcl rename to projects/syntmono/tcl/TCLPhys.tcl index 826640b..eb96bb6 100644 --- a/syntmono/tcl/TCLPhys.tcl +++ b/projects/syntmono/tcl/TCLPhys.tcl @@ -84,25 +84,25 @@ scale .left.pitch -from 0 -to 128 -length 200 \ -tickinterval 32 -showvalue true -bg grey66 scale .left.cont1 -from 0 -to 128 -length 200 \ --command {printWhatz "ControlChange 0.0 1 " 2} \ +-command {printWhatz "ControlChange -1.0 1 " 2} \ -orient horizontal -label "Reed, Emb., Lip., Bow Pres." \ -tickinterval 32 -showvalue true -bg grey66 \ -variable cont2 scale .right.cont2 -from 0 -to 128 -length 200 \ --command {printWhatz "ControlChange 0.0 1 " 4} \ +-command {printWhatz "ControlChange -1.0 1 " 4} \ -orient horizontal -label "Noise, Slide Len.,Bow Pos." \ -tickinterval 32 -showvalue true -bg grey66 \ -variable cont4 scale .right.cont3 -from 0 -to 128 -length 200 \ --command {printWhatz "ControlChange 0.0 1 " 11} \ +-command {printWhatz "ControlChange -1.0 1 " 11} \ -orient horizontal -label "Vibrato Rate" \ -tickinterval 32 -showvalue true -bg grey66 \ -variable cont11 scale .right.vibrato -from 0 -to 128 -length 200 \ --command {printWhatz "ControlChange 0.0 1 " 1} \ +-command {printWhatz "ControlChange -1.0 1 " 1} \ -orient horizontal -label "Vibrato Amount" \ -tickinterval 32 -showvalue true -bg grey66 \ -variable cont1 @@ -122,8 +122,6 @@ bind . +myExit proc myExit {} { global pitch outID - puts $outID [format "NoteOff 0.0 1 %f 127" $pitch ] - flush $outID puts $outID [format "ExitProgram"] flush $outID close $outID @@ -132,19 +130,19 @@ proc myExit {} { proc noteOn {pitchVal pressVal} { global outID - puts $outID [format "NoteOn 0.0 1 %f %f" $pitchVal $pressVal] + puts $outID [format "NoteOn -1.0 1 %f %f" $pitchVal $pressVal] flush $outID } proc noteOff {pitchVal pressVal} { global outID - puts $outID [format "NoteOff 0.0 1 %f %f" $pitchVal $pressVal] + puts $outID [format "NoteOff -1.0 1 %f %f" $pitchVal $pressVal] flush $outID } proc patchChange {value} { global outID bitmappath cont1 cont2 cont4 cont11 - puts $outID [format "ProgramChange 0.0 1 %i" $value] + puts $outID [format "ProgramChange -1.0 1 %i" $value] if {$value==0} { .pretty config -bitmap @$bitmappath/Klar.xbm } @@ -172,13 +170,13 @@ proc printWhatz {tag value1 value2 } { proc changePress {value} { global outID - puts $outID [format "AfterTouch 0.0 1 %f" $value] + puts $outID [format "AfterTouch -1.0 1 %f" $value] flush $outID } proc changePitch {value} { global outID - puts $outID [format "PitchBend 0.0 1 %.3f" $value] + puts $outID [format "PitchBend -1.0 1 %.3f" $value] flush $outID } diff --git a/syntmono/tcl/TCLShakers.tcl b/projects/syntmono/tcl/TCLShakers.tcl similarity index 92% rename from syntmono/tcl/TCLShakers.tcl rename to projects/syntmono/tcl/TCLShakers.tcl index 89fb878..dff380f 100644 --- a/syntmono/tcl/TCLShakers.tcl +++ b/projects/syntmono/tcl/TCLShakers.tcl @@ -5,6 +5,7 @@ set press 64.0 set cont1 64.0 set cont4 64.0 set cont11 64.0 +set cont99 24.0 set outID "stdout" set commtype "stdout" set patchnum 0 @@ -34,27 +35,34 @@ scale .right.bPressure -from 0 -to 128 -length 300 \ -tickinterval 32 -showvalue true -bg grey66 scale .right.cont2 -from 0 -to 128 -length 300 \ --command {printWhatz "ControlChange 0.0 1 " 4} \ +-command {printWhatz "ControlChange -1.0 1 " 11} \ -orient horizontal -label "(<--High) System Damping (Low-->)" \ -tickinterval 32 -showvalue true -bg grey66 \ -variable cont4 scale .right.cont3 -from 0 -to 128 -length 300 \ --command {printWhatz "ControlChange 0.0 1 " 11} \ +-command {printWhatz "ControlChange -1.0 1 " 4} \ -orient horizontal -label "Number of Objects" \ -tickinterval 32 -showvalue true -bg grey66 \ -variable cont11 scale .right.vibrato -from 0 -to 128 -length 300 \ --command {printWhatz "ControlChange 0.0 1 " 1} \ +-command {printWhatz "ControlChange -1.0 1 " 1} \ -orient horizontal -label "Resonance Center Freq." \ -tickinterval 32 -showvalue true -bg grey66 \ -variable cont1 +scale .right.reverb -from 0 -to 128 -length 300 \ +-command {printWhatz "ControlChange -1.0 1 " 99} \ +-orient horizontal -label "Reverb Mix" \ +-tickinterval 32 -showvalue true -bg grey66 \ +-variable cont99 + pack .right.bPressure -padx 10 -pady 10 pack .right.vibrato -padx 10 -pady 10 pack .right.cont2 -padx 10 -pady 10 pack .right.cont3 -padx 10 -pady 10 +pack .right.reverb -padx 10 -pady 10 pack .right -side right -padx 5 -pady 5 @@ -139,7 +147,7 @@ proc myExit {} { proc patchChange {value} { global outID press - puts $outID [format "NoteOn 0.0 1 %i $press" $value] + puts $outID [format "NoteOn -1.0 1 %i $press" $value] flush $outID } @@ -151,7 +159,7 @@ proc printWhatz {tag value1 value2 } { proc changePress {value} { global outID - puts $outID [format "AfterTouch 0.0 1 %f" $value] + puts $outID [format "AfterTouch -1.0 1 %f" $value] flush $outID } diff --git a/syntmono/tcl/TCLVoice.tcl b/projects/syntmono/tcl/TCLVoice.tcl similarity index 91% rename from syntmono/tcl/TCLVoice.tcl rename to projects/syntmono/tcl/TCLVoice.tcl index 8460e42..1461b51 100644 --- a/syntmono/tcl/TCLVoice.tcl +++ b/projects/syntmono/tcl/TCLVoice.tcl @@ -78,25 +78,25 @@ scale .left.pitch -from 0 -to 128 -length 200 \ -tickinterval 32 -showvalue true -bg grey66 scale .left.cont1 -from 0 -to 128 -length 200 \ --command {printWhatz "ControlChange 0.0 1 " 2} \ +-command {printWhatz "ControlChange -1.0 1 " 2} \ -orient horizontal -label "Formant Q / Voiced/Un." \ -tickinterval 32 -showvalue true -bg grey66 \ -variable cont2 scale .right.cont2 -from 0 -to 128 -length 200 \ --command {printWhatz "ControlChange 0.0 1 " 4} \ +-command {printWhatz "ControlChange -1.0 1 " 4} \ -orient horizontal -label "Vowel (Bass, Tenor, Alto, Sop.)" \ -tickinterval 32 -showvalue true -bg grey66 \ -variable cont4 scale .right.cont3 -from 0 -to 128 -length 200 \ --command {printWhatz "ControlChange 0.0 1 " 11} \ +-command {printWhatz "ControlChange -1.0 1 " 11} \ -orient horizontal -label "Vibrato Rate" \ -tickinterval 32 -showvalue true -bg grey66 \ -variable cont11 scale .right.vibrato -from 0 -to 128 -length 200 \ --command {printWhatz "ControlChange 0.0 1 " 1} \ +-command {printWhatz "ControlChange -1.0 1 " 1} \ -orient horizontal -label "Vibrato Amount" \ -tickinterval 32 -showvalue true -bg grey66\ -variable cont1 @@ -117,8 +117,6 @@ bind . +myExit proc myExit {} { global pitch global outID - puts $outID [format "NoteOff 0.0 1 %f 127" $pitch ] - flush $outID puts $outID [format "ExitProgram"] flush $outID close $outID @@ -127,13 +125,13 @@ proc myExit {} { proc noteOn {pitchVal pressVal} { global outID - puts $outID [format "NoteOn 0.0 1 %f %f" $pitchVal $pressVal] + puts $outID [format "NoteOn -1.0 1 %f %f" $pitchVal $pressVal] flush $outID } proc noteOff {pitchVal pressVal} { global outID - puts $outID [format "NoteOff 0.0 1 %f %f" $pitchVal $pressVal] + puts $outID [format "NoteOff -1.0 1 %f %f" $pitchVal $pressVal] flush $outID } @@ -144,7 +142,7 @@ proc patchChange {value} { global cont2 global cont4 global cont11 - puts $outID [format "ProgramChange 0.0 1 %i" $value] + puts $outID [format "ProgramChange -1.0 1 %i" $value] if {$value==16} { .pretty config -bitmap @$bitmappath/KVoiceFM.xbm } @@ -166,13 +164,13 @@ proc printWhatz {tag value1 value2 } { proc changePress {value} { global outID - puts $outID [format "AfterTouch 0.0 1 %f" $value] + puts $outID [format "AfterTouch -1.0 1 %f" $value] flush $outID } proc changePitch {value} { global outID - puts $outID [format "PitchBend 0.0 1 %.3f" $value] + puts $outID [format "PitchBend -1.0 1 %.3f" $value] flush $outID } diff --git a/syntmono/tcl/bitmaps/KFMod.xbm b/projects/syntmono/tcl/bitmaps/KFMod.xbm similarity index 100% rename from syntmono/tcl/bitmaps/KFMod.xbm rename to projects/syntmono/tcl/bitmaps/KFMod.xbm diff --git a/syntmono/tcl/bitmaps/KFiddl.xbm b/projects/syntmono/tcl/bitmaps/KFiddl.xbm similarity index 100% rename from syntmono/tcl/bitmaps/KFiddl.xbm rename to projects/syntmono/tcl/bitmaps/KFiddl.xbm diff --git a/syntmono/tcl/bitmaps/KFloot.xbm b/projects/syntmono/tcl/bitmaps/KFloot.xbm similarity index 100% rename from syntmono/tcl/bitmaps/KFloot.xbm rename to projects/syntmono/tcl/bitmaps/KFloot.xbm diff --git a/syntmono/tcl/bitmaps/KHose.xbm b/projects/syntmono/tcl/bitmaps/KHose.xbm similarity index 100% rename from syntmono/tcl/bitmaps/KHose.xbm rename to projects/syntmono/tcl/bitmaps/KHose.xbm diff --git a/syntmono/tcl/bitmaps/KModal.xbm b/projects/syntmono/tcl/bitmaps/KModal.xbm similarity index 100% rename from syntmono/tcl/bitmaps/KModal.xbm rename to projects/syntmono/tcl/bitmaps/KModal.xbm diff --git a/syntmono/tcl/bitmaps/KPluk.xbm b/projects/syntmono/tcl/bitmaps/KPluk.xbm similarity index 100% rename from syntmono/tcl/bitmaps/KPluk.xbm rename to projects/syntmono/tcl/bitmaps/KPluk.xbm diff --git a/syntmono/tcl/bitmaps/KVoicForm.xbm b/projects/syntmono/tcl/bitmaps/KVoicForm.xbm similarity index 100% rename from syntmono/tcl/bitmaps/KVoicForm.xbm rename to projects/syntmono/tcl/bitmaps/KVoicForm.xbm diff --git a/syntmono/tcl/bitmaps/KVoiceFM.xbm b/projects/syntmono/tcl/bitmaps/KVoiceFM.xbm similarity index 100% rename from syntmono/tcl/bitmaps/KVoiceFM.xbm rename to projects/syntmono/tcl/bitmaps/KVoiceFM.xbm diff --git a/syntmono/tcl/bitmaps/Klar.xbm b/projects/syntmono/tcl/bitmaps/Klar.xbm similarity index 100% rename from syntmono/tcl/bitmaps/Klar.xbm rename to projects/syntmono/tcl/bitmaps/Klar.xbm diff --git a/syntmono/tcl/bitmaps/bamboo.xbm b/projects/syntmono/tcl/bitmaps/bamboo.xbm similarity index 100% rename from syntmono/tcl/bitmaps/bamboo.xbm rename to projects/syntmono/tcl/bitmaps/bamboo.xbm diff --git a/syntmono/tcl/bitmaps/cabasa.xbm b/projects/syntmono/tcl/bitmaps/cabasa.xbm similarity index 100% rename from syntmono/tcl/bitmaps/cabasa.xbm rename to projects/syntmono/tcl/bitmaps/cabasa.xbm diff --git a/syntmono/tcl/bitmaps/guiro.xbm b/projects/syntmono/tcl/bitmaps/guiro.xbm similarity index 100% rename from syntmono/tcl/bitmaps/guiro.xbm rename to projects/syntmono/tcl/bitmaps/guiro.xbm diff --git a/syntmono/tcl/bitmaps/kasm.xbm b/projects/syntmono/tcl/bitmaps/kasm.xbm similarity index 100% rename from syntmono/tcl/bitmaps/kasm.xbm rename to projects/syntmono/tcl/bitmaps/kasm.xbm diff --git a/syntmono/tcl/bitmaps/maraca.xbm b/projects/syntmono/tcl/bitmaps/maraca.xbm similarity index 100% rename from syntmono/tcl/bitmaps/maraca.xbm rename to projects/syntmono/tcl/bitmaps/maraca.xbm diff --git a/syntmono/tcl/bitmaps/phism.xbm b/projects/syntmono/tcl/bitmaps/phism.xbm similarity index 100% rename from syntmono/tcl/bitmaps/phism.xbm rename to projects/syntmono/tcl/bitmaps/phism.xbm diff --git a/syntmono/tcl/bitmaps/prc.xbm b/projects/syntmono/tcl/bitmaps/prc.xbm similarity index 100% rename from syntmono/tcl/bitmaps/prc.xbm rename to projects/syntmono/tcl/bitmaps/prc.xbm diff --git a/syntmono/tcl/bitmaps/prcFunny.xbm b/projects/syntmono/tcl/bitmaps/prcFunny.xbm similarity index 100% rename from syntmono/tcl/bitmaps/prcFunny.xbm rename to projects/syntmono/tcl/bitmaps/prcFunny.xbm diff --git a/syntmono/tcl/bitmaps/rachet.xbm b/projects/syntmono/tcl/bitmaps/rachet.xbm similarity index 100% rename from syntmono/tcl/bitmaps/rachet.xbm rename to projects/syntmono/tcl/bitmaps/rachet.xbm diff --git a/syntmono/tcl/bitmaps/sleighbell.xbm b/projects/syntmono/tcl/bitmaps/sleighbell.xbm similarity index 100% rename from syntmono/tcl/bitmaps/sleighbell.xbm rename to projects/syntmono/tcl/bitmaps/sleighbell.xbm diff --git a/syntmono/tcl/bitmaps/tambourine.xbm b/projects/syntmono/tcl/bitmaps/tambourine.xbm similarity index 100% rename from syntmono/tcl/bitmaps/tambourine.xbm rename to projects/syntmono/tcl/bitmaps/tambourine.xbm diff --git a/projects/syntmono/utilities.cpp b/projects/syntmono/utilities.cpp new file mode 100644 index 0000000..6165e42 --- /dev/null +++ b/projects/syntmono/utilities.cpp @@ -0,0 +1,285 @@ +// Miscellaneous parsing and error functions for use with syntmono. +// +// Gary P. Scavone, 1999. + +#include "utilities.h" +#include "Controller.h" + +// STK Instrument Classes +#include "Object.h" +#include "Clarinet.h" +#include "Flute.h" +#include "Brass.h" +#include "Bowed.h" +#include "Plucked.h" +#include "Mandolin.h" +#include "ModalBar.h" +#include "Rhodey.h" +#include "Wurley.h" +#include "TubeBell.h" +#include "HeavyMtl.h" +#include "PercFlut.h" +#include "BeeThree.h" +#include "Moog1.h" +#include "FMVoices.h" +#include "VoicForm.h" +#include "DrumSynt.h" +#include "Shakers.h" +#include "BowedBar.h" +#include "BlowHole.h" + +// STK WvOut classes +#include "WvOut.h" +#include "SndWvOut.h" +#include "WavWvOut.h" +#include "MatWvOut.h" +#include "AifWvOut.h" +#if defined(__STK_REALTIME_) + #include "RtWvOut.h" +#endif + +#define NUM_INSTS 20 + +// The order of the following list is important. The location of a particular +// instrument in the list should correspond to that instrument's ProgramChange +// number (i.e. Clarinet = ProgramChange 0). +char insts[NUM_INSTS][10] = { "Clarinet", "Flute", "Brass", "Bowed", "BlowHole", + "Plucked", "Mandolin", "Rhodey", "Wurley", "TubeBell", + "HeavyMtl", "PercFlut", "BeeThree", "Moog1", + "FMVoices", "VoicForm", "DrumSynt", "Shakers", + "BowedBar", "ModalBar", }; + +int newInstByNum(int instNum) +{ + int temp = instNum; + extern Instrmnt *instrument; + + if (instNum==0) instrument = new Clarinet(20.0); + else if (instNum==1) instrument = new Flute(20.0); + else if (instNum==2) instrument = new Brass(20.0); + else if (instNum==3) instrument = new Bowed(20.0); + else if (instNum==4) instrument = new BlowHole(20.0); + else if (instNum==5) instrument = new Plucked(20.0); + else if (instNum==6) instrument = new Mandolin(20.0); + + else if (instNum==7) instrument = new Rhodey; + else if (instNum==8) instrument = new Wurley; + else if (instNum==9) instrument = new TubeBell; + else if (instNum==10) instrument = new HeavyMtl; + else if (instNum==11) instrument = new PercFlut; + else if (instNum==12) instrument = new BeeThree; + else if (instNum==13) instrument = new Moog1; + + else if (instNum==14) instrument = new FMVoices; + else if (instNum==15) instrument = new VoicForm; + + else if (instNum==16) instrument = new DrumSynt; + else if (instNum==17) instrument = new Shakers; + else if (instNum==18) instrument = new BowedBar; + else if (instNum==19) instrument = new ModalBar; + + else { + printf("\nUnknown instrument or program change requested!\n"); + temp = -1; + } + + return temp; +} + +int newInstByName(char *instName) +{ + int i = 0, temp = -1, notFound = 1;; + + while (i for .snd audio output file,\n"); + printf(" -ow for .wav audio output file,\n"); + printf(" -om for .mat audio output file,\n"); + printf(" -oa for .aif audio output file,\n"); +#if defined(__STK_REALTIME_) + printf(" -or for realtime audio output,\n"); + printf(" -ip for realtime control input by pipe,\n"); + printf(" (won't work under Win95/98),\n"); + printf(" -is for realtime control input by socket,\n"); + printf(" -im for realtime control input by MIDI,\n"); +#endif + printf(" and Instrument = one of these:\n"); + for (i=0;i are not\n"); + printf("specified, default names will be indicated. Each flag\n"); + printf("must include its own '-' sign.\n\n"); + exit(0); +} + +int checkArgs(int numArgs, char *args[]) +{ + int w, i = 2, j = 0; + int numOutputs = 0; + char flags[16] = ""; + + if (numArgs < 3 || numArgs > 10) usage(args[0]); + + while (i < numArgs) { + if (args[i][0] == '-') { + if (args[i][1] == 'o') { + if ( (args[i][2] == 'r') || (args[i][2] == 's') || + (args[i][2] == 'w') || (args[i][2] == 'm') + || (args[i][2] == 'a') ) + numOutputs++; + } + else if (args[i][1] == 'i') { + if ( (args[i][2] != 's') && (args[i][2] != 'p') && + (args[i][2] != 'm') ) usage(args[0]); + } + else usage(args[0]); + flags[j] = args[i][2]; + j++; + } + i++; + } + + /* Check for multiple flags of the same type */ + for (i=0; i<=j; i++) { + w = i+1; + while (w <= j) { + if (flags[i] == flags[w]) { + printf("\nError: Multiple command line flags of the same type specified.\n\n"); + usage(args[0]); + } + w++; + } + } + + /* Make sure we have at least one output type */ + if (numOutputs < 1) usage(args[0]); + + return numOutputs; +} + +int parseArgs(int numArgs, char *args[]) +{ + int i = 2, j = 0; + int inputMask = 0; + char fileName[256]; + extern WvOut **output; + + while (i < numArgs) { + if ( (args[i][0] == '-') && (args[i][1] == 'i') ) { + switch(args[i][2]) { + + case 'p': +#if defined(__STK_REALTIME_) + inputMask |= STK_PIPE; + break; +#else + usage(args[0]); +#endif + + case 's': +#if defined(__STK_REALTIME_) + inputMask |= STK_SOCKET; + break; +#else + usage(args[0]); +#endif + + case 'm': +#if defined(__STK_REALTIME_) + inputMask |= STK_MIDI; + break; +#else + usage(args[0]); +#endif + + default: + usage(args[0]); + break; + } + } + else if ( (args[i][0] == '-') && (args[i][1] == 'o') ) { + switch(args[i][2]) { + + case 'r': +#if defined(__STK_REALTIME_) + output[j] = new RtWvOut(); + j++; + break; +#else + usage(args[0]); +#endif + + case 'w': + if ((i+1 < numArgs) && args[i+1][0] != '-') { + i++; + strcpy(fileName,args[i]); + } + else strcpy(fileName,"testwav"); + output[j] = new WavWvOut(fileName,1); + j++; + break; + + case 's': + if ((i+1 < numArgs) && args[i+1][0] != '-') { + i++; + strcpy(fileName,args[i]); + } + else strcpy(fileName,"testsnd"); + output[j] = new SndWvOut(fileName,1); + j++; + break; + + case 'm': + if ((i+1 < numArgs) && args[i+1][0] != '-') { + i++; + strcpy(fileName,args[i]); + } + else strcpy(fileName,"testmat"); + output[j] = new MatWvOut(fileName,1); + j++; + break; + + case 'a': + if ((i+1 < numArgs) && args[i+1][0] != '-') { + i++; + strcpy(fileName,args[i]); + } + else strcpy(fileName,"testaif"); + output[j] = new AifWvOut(fileName,1); + j++; + break; + + default: + usage(args[0]); + break; + } + } + i++; + } + return inputMask; +} diff --git a/syntmono/utilities.h b/projects/syntmono/utilities.h similarity index 82% rename from syntmono/utilities.h rename to projects/syntmono/utilities.h index bc8f833..2090341 100644 --- a/syntmono/utilities.h +++ b/projects/syntmono/utilities.h @@ -2,13 +2,13 @@ // // Gary P. Scavone, 1999. -#include "../STK/Instrmnt.h" +#include "Instrmnt.h" int newInstByNum(int instNum); int newInstByName(char *instName); -void usage(char *func); +void usage(char *function); int checkArgs(int numArgs, char *args[]); diff --git a/ragamatic/ragamat.plg b/ragamatic/ragamat.plg deleted file mode 100755 index c872352..0000000 --- a/ragamatic/ragamat.plg +++ /dev/null @@ -1,53 +0,0 @@ ---------------------Configuration: ragamatic - Win32 Release-------------------- -Begining build with project "C:\gary\STKRelease\ragamatic\ragamat.dsp", at root. -Active configuration is Win32 (x86) Console Application (based on Win32 (x86) Console Application) - -Project's tools are: - "32-bit C/C++ Compiler for 80x86" with flags "/nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__OS_Win_" /Fp"Release/ragamat.pch" /YX /Fo"Release/" /Fd"Release/" /FD /c " - "Win32 Resource Compiler" with flags "/l 0x409 /d "NDEBUG" " - "Browser Database Maker" with flags "/nologo /o"ragamat.bsc" " - "COFF Linker for 80x86" with flags "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 winmm.lib /nologo /subsystem:console /incremental:no /pdb:"ragamat.pdb" /machine:I386 /out:"ragamat.exe" " - "Custom Build" with flags "" - "" with flags "" - -Creating temp file "C:\WINDOWS\TEMP\RSP53A0.TMP" with contents -Creating command line "cl.exe @C:\WINDOWS\TEMP\RSP53A0.TMP" -Creating temp file "C:\WINDOWS\TEMP\RSP53A1.TMP" with contents -Creating command line "link.exe @C:\WINDOWS\TEMP\RSP53A1.TMP" -Compiling... -RTWvOut.cpp -Linking... - - - -ragamat.exe - 0 error(s), 0 warning(s) diff --git a/ragamatic/ragamatic.dsw b/ragamatic/ragamatic.dsw deleted file mode 100755 index 648f733..0000000 --- a/ragamatic/ragamatic.dsw +++ /dev/null @@ -1,29 +0,0 @@ -Microsoft Developer Studio Workspace File, Format Version 5.00 -# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! - -############################################################################### - -Project: "ragamatic"=.\ragamatic.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### - diff --git a/ragamatic/threads.cpp b/ragamatic/threads.cpp deleted file mode 100644 index 4313af0..0000000 --- a/ragamatic/threads.cpp +++ /dev/null @@ -1,279 +0,0 @@ -// Thread functions for use with syntmono. -// -// No mutexes are currently being used when accessing -// the global variables shared between these threads -// and the main() routine. In a single processor -// environment, no problems have resulted from such data -// sharing. However, if STK is to be run on a true parallel -// processing platform, it is likely that mutexes will be -// necessary. While the mutex calls are simple to code, I -// am trying to keep the code as generic as possible. A -// quick investigation of threads under Windoze indicates -// that mutex functionality is not available, at least with -// the standard libraries. -// -// Gary P. Scavone, 2000. - -#include "threads.h" - -#if defined(__STK_REALTIME_) - -// Default STK socket port ID number -#define SERVICE_PORT 2001 - -// Do OS dependent declarations and includes -#if (defined(__OS_IRIX_) || defined(__OS_Linux_)) -#include -#include -#include -#include -#include -#include - -pthread_t string_thread; - -#elif defined(__OS_Win_) -#include -#include - -unsigned long string_thread; - -#endif - - -// The thread function protocols are slightly different -// under Windoze ... but of course! - -#if (defined(__OS_IRIX_) || defined(__OS_Linux_)) - -void *newStringByPipe(void *) - -#elif defined(__OS_Win_) - -void newStringByPipe(void *) - -#endif - -{ - extern int numStrings, notDone; - extern char **inputString; - int i; - - // Malloc inputString. - inputString = (char **) malloc(MAX_IN_STRINGS * sizeof(char *)); - for ( i=0;i MAX_IN_STRINGS) { - fprintf(stderr,"Losing MIDI data ... try increasing MAX_IN_STRINGS.\n"); - numStrings--; - } - inOne++; - if (inOne == MAX_IN_STRINGS) inOne = 0; - } - } - - // Free inputString. - for ( i=0;i maxfd) maxfd = accept_id; - FD_CLR(soc_id, &rmask); - } - for (fd=0;fd<=maxfd;fd++) { // look for other sockets with data - if (FD_ISSET(fd, &rmask)) { // process the data - parsing = 1; - while (parsing) { - i = recv(fd, socBuf, STRING_LEN,0); - if (i==0) { - printf("Closing a socket connection.\n"); - FD_CLR(fd, &mask); -#if defined(__OS_Win_) - closesocket(fd); -#else - close(fd); -#endif - parsing = 0; - } - n = 0; - while (n < i) { - inputString[inOne][m++] = socBuf[n]; - if (socBuf[n++] == '\n') { - if (inputString[inOne][2] == 'i' && inputString[inOne][3] == 't' - && inputString[inOne][1] == 'x' && inputString[inOne][0] == 'E') { - notDone = 0; - n = i; - parsing = 0; - } - else { - m = 0; - if (n >= i) parsing = 0; - numStrings++; - if (numStrings > MAX_IN_STRINGS) { - fprintf(stderr,"Losing MIDI data ... try increasing MAX_IN_STRINGS.\n"); - numStrings--; - } - inOne++; - if (inOne == MAX_IN_STRINGS) inOne = 0; - memset(inputString[inOne], 0, STRING_LEN); - } - } - } - } - } - } - } -#if defined(__OS_Win_) // Stupid Windoze only stuff - closesocket(soc_id); - WSACleanup(); -#else - shutdown(soc_id,0); -#endif - - // Free inputString. - for ( i=0;i>= 1; + } + if (last & 0x00000001) mantissa++; + rate = (MY_FLOAT) (mantissa/SRATE); // set default rate based on file sampling rate + + // Find "data" chunk + fread(&id,4,1,fd); + while (strncmp(id,"SSND",4)) { + fread(&chunkSize,4,1,fd); +#ifdef __LITTLE_ENDIAN__ + swap32((unsigned char *)&chunkSize); +#endif + fseek(fd,chunkSize,SEEK_CUR); + fread(&id,4,1,fd); + } + + // Skip over chunk size, offset, and blocksize fields + fseek(fd,12,SEEK_CUR); + + if ((fileSize*channels) > MAX_FILE_LOAD_SIZE) { + printf("\nAifWvIn: The .AIF file (%s) has more than %d samples and\n", + fileName, MAX_FILE_LOAD_SIZE); + printf("will be loaded incrementally from disk. Normalization will be disabled.\n"); + chunking = 1; + bufferSize = LOAD_BUFFER_SIZE; + } + + // Setup for looping or one-shot playback + if (!strcmp(mode,"looping")) + looping = 1; + else // default = oneshot + looping = 0; + + data = (MY_FLOAT *) new MY_FLOAT[(bufferSize+1)*channels]; + dataOffset = ftell(fd); + this->getData(0); // Read samples into data[] + + if (fmod(rate, 1.0) != 0.0) interpolate = 1; + else interpolate = 0; + phaseOffset = (MY_FLOAT) 0.0; + lastOutput = (MY_FLOAT *) new MY_FLOAT[channels]; + this->reset(); + + // finally, let's normalize the data by default + this->normalize(); +} + +AifWvIn :: ~AifWvIn() +{ +} + +void AifWvIn :: getData(long index) +{ + /* Compare index to current readPointer and modify as needed. + * The following while() loops will only execute on calls subsequent + * to class instantiation ... and thus, only when "chunking". + */ + while (index < readPointer) { + readPointer -= LOAD_BUFFER_SIZE; + bufferSize = LOAD_BUFFER_SIZE; + if (readPointer < 0) { + bufferSize += readPointer; + readPointer = 0; + } + } + while (index >= readPointer+bufferSize) { + readPointer += LOAD_BUFFER_SIZE; + bufferSize = LOAD_BUFFER_SIZE; + if (readPointer+LOAD_BUFFER_SIZE >= fileSize) { + bufferSize = fileSize - readPointer; + } + } + + fseek(fd, dataOffset+(long)(readPointer*channels*2), SEEK_SET); + long length = bufferSize; + int end_of_file = (readPointer+bufferSize == fileSize); + if (!end_of_file) length += 1; + + // Read samples into data[]. Use MY _FLOAT data structure to store INT16 samples + INT16 *buf = (INT16 *)data; + fread(buf, 2, length*channels, fd); + // Convert in place (unpack) to MY_FLOAT from the end of the array + for (int i=length*channels-1; i>=0; i--) { +#ifdef __LITTLE_ENDIAN__ + swap16((unsigned char *)(buf+i)); +#endif + data[i] = buf[i]; + if (chunking) data[i] *= 0.00003051; + } + + // fill in the extra sample frame for interpolation + if (end_of_file) { + for (int j=0; j>= 1; + if (!exp) break; + } + i += 16383; +#ifdef __LITTLE_ENDIAN__ + swap16((unsigned char *)&i); +#endif + *(INT16 *)(hdr.srate) = (INT16) 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; + + strcpy(tempName,fileName); + if (strstr(tempName,".aif") == NULL) strcat(tempName,".aif"); + fd = fopen(tempName,"wb"); + if (!fd) { + sprintf(msg, "AifWvOut: Could not create soundfile: %s\n", tempName); + throw StkError(msg, StkError::FILE_ERROR); + } + +#ifdef __LITTLE_ENDIAN__ + 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 *)&hdr.ssnd_size); + swap32((unsigned char *)&hdr.offset); + swap32((unsigned char *)&hdr.block_size); +#endif + + printf("\nCreating soundfile: %s\n", tempName); + + /* I found it necessary to break the fwrite() calls as + * follows ... a single write of 54 bytes didn't work. + */ + fwrite(&hdr,4,5,fd); + fwrite(&hdr.num_chans,2,1,fd); + fwrite(&hdr.sample_frames,4,1,fd); + fwrite(&hdr.sample_size,2,1,fd); + fwrite(&hdr.srate,10,1,fd); + fwrite(&hdr.ssnd,4,4,fd); + + return fd; +} + +AifWvOut :: AifWvOut(char *fileName, int chans) +{ + char msg[256]; + if (chans < 1) { + sprintf(msg, "AifWvOut: number of channels = %d not supported!\n", chans); + throw StkError(msg, StkError::FUNCTION_SYNTAX); + } + channels = chans; + fd = openAifFile(chans,fileName); + data_length = FILE_BUFFER_SIZE*channels; + data = (INT16 *) new INT16[data_length]; +} + +AifWvOut :: ~AifWvOut() +{ + MY_FLOAT time; + unsigned long bytes; + unsigned long frames; + + fwrite(data,2,counter,fd); + time = (double) totalCount * ONE_OVER_SRATE; + printf("%f Seconds Computed\n\n", time); + + frames = (unsigned long) totalCount; +#ifdef __LITTLE_ENDIAN__ + swap32((unsigned char *)&frames); +#endif + fseek(fd,22,SEEK_SET); // jump to "COMM" sample_frames + fwrite(&frames,4,1,fd); + + bytes = totalCount*2*channels + 46; +#ifdef __LITTLE_ENDIAN__ + swap32((unsigned char *)&bytes); +#endif + fseek(fd,4,SEEK_SET); // jump to file size + fwrite(&bytes,4,1,fd); + + bytes = totalCount*2*channels + 8; +#ifdef __LITTLE_ENDIAN__ + swap32((unsigned char *)&bytes); +#endif + fseek(fd,42,SEEK_SET); // jump to "SSND" chunk size + fwrite(&bytes,4,1,fd); + + fclose(fd); +} + +void AifWvOut :: tick(MY_FLOAT sample) +{ + INT16 isample; + + isample = (INT16) (sample * 32000.0); +#ifdef __LITTLE_ENDIAN__ + swap16((unsigned char *)&isample); +#endif + for (int i=0;i> 1); + // delays[2] is the delay line between the tonehole and the end of the bore + delays[2].setDelay(4.0); + reedTable = new ReedTabl; + reedTable->setOffset((MY_FLOAT) 0.7); + reedTable->setSlope((MY_FLOAT) -0.3); + filter = new OneZero; + envelope = new Envelope; + noise = new Noise; + + // Calculate the initial tonehole three-port scattering coefficient + double r_b = 0.0075; /* main bore radius */ + r_th = 0.003; /* tonehole radius */ + scatter = -pow(r_th,2) / ( pow(r_th,2) + 2*pow(r_b,2) ); + + // Calculate tonehole coefficients + MY_FLOAT te = 1.4 * r_th; /* effective length of the open hole */ + th_coeff = (te*2*SRATE - 347.23) / (te*2*SRATE + 347.23); + tonehole = new PoleZero; + // Start with tonehole open + tonehole->setA1(-th_coeff); + tonehole->setB0(th_coeff); + tonehole->setB1(-1.0); + + // Calculate register hole filter coefficients + double r_rh = 0.0015; /* register vent radius */ + te = 1.4 * r_rh; /* effective length of the open hole */ + double xi = 0.0; /* series resistance term */ + double zeta = 347.23 + 2*PI*pow(r_b,2)*xi/1.1769; + double psi = 2*PI*pow(r_b,2)*te / (PI*pow(r_rh,2)); + rh_coeff = (zeta - 2*SRATE*psi) / (zeta + 2*SRATE*psi); + rh_gain = -347.23 / (zeta + 2*SRATE*psi); + vent = new PoleZero; + vent->setA1(rh_coeff); + vent->setB0(1.0); + vent->setB1(1.0); + // Start with register vent closed + vent->setGain(0.0); + + // Concatenate the STK RAWWAVE_PATH to the rawwave file + char file[128]; + strcpy(file, RAWWAVE_PATH); + vibr = new RawWvIn(strcat(file,"rawwaves/sinewave.raw"),"looping"); + vibr->setFreq((MY_FLOAT) 5.735); + outputGain = (MY_FLOAT) 1.0; + noiseGain = (MY_FLOAT) 0.2; + vibrGain = (MY_FLOAT) 0.01; +} + +BlowHole :: ~BlowHole() +{ + delete [] delays; + delete reedTable; + delete filter; + delete tonehole; + delete vent; + delete envelope; + delete noise; + delete vibr; +} + +void BlowHole :: clear() +{ + delays[0].clear(); + delays[1].clear(); + filter->tick((MY_FLOAT) 0.0); + tonehole->tick((MY_FLOAT) 0.0); + vent->tick((MY_FLOAT) 0.0); +} + +void BlowHole :: setFreq(MY_FLOAT frequency) +{ + MY_FLOAT new_length = (SRATE / frequency) * (MY_FLOAT) 0.5 - (MY_FLOAT) 1.5; + new_length -= 9; + + if (new_length <= 1.0) new_length = 1.0; + else if (new_length >= length) new_length = length; + delays[1].setDelay(new_length); +} + +void BlowHole :: setVent(MY_FLOAT newValue) +{ + /* + This method allows setting of the register vent "open-ness" at + any point between "Open" (newValue = 1) and "Closed" + (newValue = 0). + */ + + MY_FLOAT gain; + + if (newValue <= 0.0) gain = 0.0; + else if (newValue >= 1.0) gain = rh_gain; + else gain = newValue * rh_gain; + vent->setGain(gain); +} + +void BlowHole :: setTonehole(MY_FLOAT newValue) +{ + /* + This method allows setting of the tonehole "open-ness" at + any point between "Open" (newValue = 1) and "Closed" + (newValue = 0). + */ + MY_FLOAT new_coeff; + + if (newValue <= 0.0) new_coeff = 0.9995; + else if (newValue >= 1.0) new_coeff = th_coeff; + else new_coeff = (newValue * (th_coeff - 0.9995)) + 0.9995; + tonehole->setA1(-new_coeff); + tonehole->setB0(new_coeff); +} + +void BlowHole :: startBlowing(MY_FLOAT amplitude,MY_FLOAT rate) +{ + envelope->setRate(rate); + envelope->setTarget(amplitude); +} + +void BlowHole :: stopBlowing(MY_FLOAT rate) +{ + envelope->setRate(rate); + envelope->setTarget((MY_FLOAT) 0.0); +} + +void BlowHole :: noteOn(MY_FLOAT freq, MY_FLOAT amp) +{ + this->setFreq(freq); + this->startBlowing((MY_FLOAT) 0.55 + (amp * (MY_FLOAT) 0.30),amp * (MY_FLOAT) 0.005); + outputGain = amp + (MY_FLOAT) 0.001; +} + +void BlowHole :: noteOff(MY_FLOAT amp) +{ + this->stopBlowing(amp * (MY_FLOAT) 0.01); +} + +MY_FLOAT BlowHole :: tick() +{ + MY_FLOAT pressureDiff; + MY_FLOAT breathPressure; + MY_FLOAT temp; + + // Calculate the breath pressure (envelope + noise + vibrator) + breathPressure = envelope->tick(); + breathPressure += breathPressure * noiseGain * noise->tick(); + breathPressure += breathPressure * vibrGain * vibr->tick(); + + // Calculate the differential pressure = reflected - mouthpiece pressures + pressureDiff = delays[0].lastOut() - breathPressure; + + // Do two-port junction scattering for register vent + MY_FLOAT pa = breathPressure + pressureDiff * reedTable->lookup(pressureDiff); + MY_FLOAT pb = delays[1].lastOut(); + vent->tick(pa+pb); + + lastOutput = delays[0].tick(vent->lastOut()+pb); + lastOutput *= outputGain; + + // Do three-port junction scattering (under tonehole) + pa += vent->lastOut(); + pb = delays[2].lastOut(); + MY_FLOAT pth = tonehole->lastOut(); + temp = scatter * (pa + pb - 2 * pth); + + delays[2].tick(filter->tick(pa + temp) * -0.95); + delays[1].tick(pb + temp); + tonehole->tick(pa + pb - pth + temp); + + return lastOutput; +} + +void BlowHole :: controlChange(int number, MY_FLOAT value) +{ + if (number == __SK_ReedStiffness_) + reedTable->setSlope((MY_FLOAT) -0.44 + ((MY_FLOAT) 0.26 * value * NORM_7)); + else if (number == __SK_NoiseLevel_) + noiseGain = (value * NORM_7 * (MY_FLOAT) 0.4); + else if (number == __SK_ModFrequency_) + //vibr->setFreq((value * NORM_7 * (MY_FLOAT) 12.0)); + this->setTonehole(value * NORM_7); + else if (number == __SK_ModWheel_) + //vibrGain = (value * NORM_7 * (MY_FLOAT) 0.5); + this->setVent(value * NORM_7); + else if (number == __SK_AfterTouch_Cont_) { + envelope->setValue(value * NORM_7); + } + else { + printf("BlowHole : Undefined Control Number!!\n"); + } +} diff --git a/STK/BowTabl.cpp b/src/BowTabl.cpp similarity index 100% rename from STK/BowTabl.cpp rename to src/BowTabl.cpp diff --git a/STK/Bowed.cpp b/src/Bowed.cpp similarity index 99% rename from STK/Bowed.cpp rename to src/Bowed.cpp index d789081..84c81a6 100644 --- a/STK/Bowed.cpp +++ b/src/Bowed.cpp @@ -48,7 +48,6 @@ Bowed :: Bowed(MY_FLOAT lowestFreq) bodyFilt->setEqualGainZeroes(); bodyFilt->setGain((MY_FLOAT) 0.2); - vibr->normalize(); vibr->setFreq((MY_FLOAT) 6.12723); adsr->setAllTimes((MY_FLOAT) 0.02,(MY_FLOAT) 0.005,(MY_FLOAT) 0.9,(MY_FLOAT) 0.01); diff --git a/STK/BowedBar.cpp b/src/BowedBar.cpp similarity index 73% rename from STK/BowedBar.cpp rename to src/BowedBar.cpp index 7a7bb57..4a557f2 100644 --- a/STK/BowedBar.cpp +++ b/src/BowedBar.cpp @@ -11,28 +11,27 @@ #include "SKINI11.msg" #include "Noise.h" -/* Number of banded waveguide modes */ - -int NR_MODES=4; - /* Contructor */ - -BowedBar :: BowedBar(MY_FLOAT lowestFreq) +BowedBar :: BowedBar() { long i; - pluck_ = 1; - + doPluck = 1; + + /* Number of banded waveguide modes */ + NR_MODES = 4; + modes[0] = (MY_FLOAT) 1.0; modes[1] = (MY_FLOAT) 2.756; modes[2] = (MY_FLOAT) 5.404; modes[3] = (MY_FLOAT) 8.933; + for (i=0;i<4;i++) { gains[i] = (MY_FLOAT) pow(0.9,(double) i); } bowTabl = new BowTabl; adsr = new ADSR; - bandpass_ = new BiQuad[NR_MODES]; + bandpass = new BiQuad[NR_MODES]; bowTabl->setSlope((MY_FLOAT) 3.0); adsr->setAllTimes((MY_FLOAT) 0.02,(MY_FLOAT) 0.005,(MY_FLOAT) 0.9,(MY_FLOAT) 0.01); @@ -43,46 +42,45 @@ BowedBar :: BowedBar(MY_FLOAT lowestFreq) bowPos = 0; lastBowPos = 0; - for(i = 0; ituneBandPasses(); } BowedBar :: ~BowedBar() { delete bowTabl; delete adsr; + delete [] bandpass; } void BowedBar :: clear() { long i; - for(i = 0; i 4) - delay[i].setDelay((int)(length/modes[i])); - else { - NR_MODES = i; - break; - } - /* FIX THIS BETTER!!!!! */ - delay[i].clear(); - - bandpass_[i].clear(); - Zs[i][1] = 0.0; - Zs[i][2] = 0.0; - filtOut[i] = 0.0; - filtIn[i] = 0.0; + for(i = 0; i 4) + delay[i].setDelay((int)(length/modes[i])); + else { + NR_MODES = i; + break; } + /* FIX THIS BETTER!!!!! */ + delay[i].clear(); + + bandpass[i].clear(); + Zs[i][1] = 0.0; + Zs[i][2] = 0.0; + filtOut[i] = 0.0; + filtIn[i] = 0.0; + } tuneBandPasses(); } @@ -130,18 +127,17 @@ void BowedBar :: tuneBandPasses() { long i; - for(i=0; istartBowing(amp,amp * (MY_FLOAT) 0.001); this->setFreq(freq); - pluck_ = 0; + doPluck = 0; #if defined(_debug_) printf("BowedBar : NoteOn: Freq=%lf Amp=%lf\n",freq,amp); #endif } else { for(int i=0; isetFreq(freq); this->pluck(amp); - pluck_ = 1; + doPluck = 1; } } void BowedBar :: noteOff(MY_FLOAT amp) { - if(!pluck_) { + if(!doPluck) { this->stopBowing(((MY_FLOAT) 1.0 - amp) * (MY_FLOAT) 0.005); } #if defined(_debug_) @@ -220,10 +216,10 @@ MY_FLOAT BowedBar :: tick() input = 0.0; - if(integration_const_ == 0.0) + if(integration_const == 0.0) velinput = 0.0; else - velinput = integration_const_ * velinput; + velinput = integration_const * velinput; for(k=0; ktick()*maxVelocity; } - if(pluck_) + if(doPluck) { input = 0.0; } @@ -255,9 +251,9 @@ MY_FLOAT BowedBar :: tick() for(k=0; kclear(); - vibr->normalize(); vibr->setFreq((MY_FLOAT) 6.137); vibrGain = (MY_FLOAT) 0.05; /* breath periodic vibrato component */ diff --git a/src/ByteSwap.cpp b/src/ByteSwap.cpp new file mode 100644 index 0000000..03e607b --- /dev/null +++ b/src/ByteSwap.cpp @@ -0,0 +1,55 @@ +#include "ByteSwap.h" + +void swap16(unsigned char *ptr) +{ + register unsigned char val; + + /* Swap 1st and 2nd bytes */ + val = *(ptr); + *(ptr) = *(ptr+1); + *(ptr+1) = val; +} + +void swap32(unsigned char *ptr) +{ + register unsigned char val; + + /* Swap 1st and 4th bytes */ + val = *(ptr); + *(ptr) = *(ptr+3); + *(ptr+3) = val; + + /* Swap 2nd and 3rd bytes */ + ptr += 1; + val = *(ptr); + *(ptr) = *(ptr+1); + *(ptr+1) = val; +} + +void swap64(unsigned char *ptr) +{ + register unsigned char val; + + /* Swap 1st and 8th bytes */ + val = *(ptr); + *(ptr) = *(ptr+7); + *(ptr+7) = val; + + /* Swap 2nd and 7th bytes */ + ptr += 1; + val = *(ptr); + *(ptr) = *(ptr+5); + *(ptr+5) = val; + + /* Swap 3rd and 6th bytes */ + ptr += 1; + val = *(ptr); + *(ptr) = *(ptr+3); + *(ptr+3) = val; + + /* Swap 4th and 5th bytes */ + ptr += 1; + val = *(ptr); + *(ptr) = *(ptr+1); + *(ptr+1) = val; +} diff --git a/STK/Clarinet.cpp b/src/Clarinet.cpp similarity index 99% rename from STK/Clarinet.cpp rename to src/Clarinet.cpp index 1133b8f..ba0a33e 100644 --- a/STK/Clarinet.cpp +++ b/src/Clarinet.cpp @@ -31,7 +31,6 @@ Clarinet :: Clarinet(MY_FLOAT lowestFreq) char file[128]; strcpy(file, RAWWAVE_PATH); vibr = new RawWvIn(strcat(file,"rawwaves/sinewave.raw"),"looping"); - vibr->normalize(); vibr->setFreq((MY_FLOAT) 5.735); outputGain = (MY_FLOAT) 1.0; noiseGain = (MY_FLOAT) 0.2; diff --git a/src/Controller.cpp b/src/Controller.cpp new file mode 100644 index 0000000..2310819 --- /dev/null +++ b/src/Controller.cpp @@ -0,0 +1,490 @@ +/******************************************/ +/* + Controller Class, + by Gary P. Scavone, 2000 + + This object will accept control messages + from a variety of sources, such as a MIDI + port, scorefile, socket connection, or + pipe. MIDI messages are retrieved with + the RtMidi class. All other input sources + (scorefile, socket, or pipe) are assumed + to provide SKINI formatted messages. + + For each call of getNextMessage(), the + active input devices are queried to see + if a new control message is available. + Only one message per call is returned, so + a subsequent call begins querying the + next available device "after" the previously + handled one. + + This class is primarily for use in STK + main() event loops. + + One of my original goals in creating this class + was to simplify the message acquisition process + by removing all threads. If the windoze + select() function behaved just like the unix one, + that would have been possible. Since it does not + (it can't be used to poll STDIN), I am using a + thread to acquire messages from STDIN, which are + then sent via a socket connection to the message + socket server. Perhaps in the future, I will be + able to simplify things. +*/ +/******************************************/ + +#include "Controller.h" + +Controller :: Controller(int inputMask) +{ + source = inputMask; + default_ticks = RT_BUFFER_SIZE; + msg_index = 0; + num_messages = 0; + score = new SKINI11(); + +#if defined(__STK_REALTIME_) + + maxfd = 0; + char msg[256]; + struct sockaddr_in mysocket; + FD_ZERO(&mask); + + /* + The fd array is used to hold the file descriptors for + all connected sockets. This saves some time incrementing + through file descriptors when using select(). + */ + for (int i=0; i<16; i++) + fd[i] = 0; + + if ( source & STK_MIDI ) + midi_input = new RtMidi(); + + /* + If no input source is specified, we assume the input is coming + from a SKINI scorefile. If any input source is specified, we + will always check STDIN, even in STK_PIPE is not specified. + This provides a means to exit cleanly when reading MIDI or + in case a socket connection cannot be made after STK_SOCKET has + been specified. The current means of polling STDIN is via a + thread. + */ + if (source) { +#if (defined(__OS_IRIX_) || defined(__OS_Linux_)) + if (pthread_create(&stdin_thread, NULL, stdinHandler, NULL)) { +#elif defined(__OS_Win_) + stdin_thread = _beginthread(stdinHandler, 0, NULL); + if (stdin_thread == 0) { +#endif + sprintf(msg, "Controller: unable to create stdin socket thread!\n"); + throw StkError(msg, StkError::PROCESS_THREAD); + } + source |= STK_SOCKET; + } + + /* Let the user know that they can exit the program via the console + if necessary. + */ + if ( !(source & STK_PIPE) && inputMask ) + printf("\nType `Exit' to quit.\n\n"); + + if ( source & STK_SOCKET ) { + // Set up the socket server to accept remote connections +#if defined(__OS_Win_) // Windoze-only stuff + WSADATA wsaData; + WORD wVersionRequested = MAKEWORD(1,1); + + WSAStartup(wVersionRequested, &wsaData); + if (wsaData.wVersion != wVersionRequested) { + sprintf(msg, "Controller: Wrong Windoze socket library version!\n"); + throw StkError(msg, StkError::PROCESS_SOCKET); + } +#endif + + // Create the server-side socket + local_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (local_socket < 0) { + sprintf(msg, "Controller: Couldn't create socket!\n"); + throw StkError(msg, StkError::PROCESS_SOCKET); + } + + mysocket.sin_family=AF_INET; + mysocket.sin_addr.s_addr=INADDR_ANY; + mysocket.sin_port=htons(STK_SOCKET_PORT); + + // Bind socket to the appropriate port and interface (INADDR_ANY) + if (bind(local_socket, (struct sockaddr *)&mysocket, sizeof(mysocket)) < 0) { + sprintf(msg, "Controller: Couldn't bind socket!\n"); + throw StkError(msg, StkError::PROCESS_SOCKET); + } + + // Listen for one incoming connection + if (listen(local_socket, 1) < 0) { + sprintf(msg, "Controller: Couldn't set up listen on socket!\n"); + throw StkError(msg, StkError::PROCESS_SOCKET); + } + if (inputMask & STK_SOCKET) + // Only print the message if STK_SOCKET was initially specified + printf("Listening for a connection on port %d\n\n", STK_SOCKET_PORT); + + FD_SET(local_socket, &mask); + if (local_socket > maxfd) maxfd = local_socket; + } +#endif // __STK_REALTIME +} + +Controller :: ~Controller() +{ + delete score; + +#if defined(__STK_REALTIME_) + + if ( source & STK_MIDI ) + delete midi_input; + + if ( source & STK_SOCKET ) { +#if (defined(__OS_IRIX_) || defined(__OS_Linux_)) + shutdown(local_socket,0); + pthread_cancel(stdin_thread); + pthread_join(stdin_thread, NULL); +#elif defined(__OS_Win_) + TerminateThread((HANDLE)stdin_thread,0); + closesocket(local_socket); + WSACleanup(); +#endif + } +#endif // __STK_REALTIME +} + +int Controller :: getType() +{ + return type; +} + +MY_FLOAT Controller :: getByte2() +{ + return byte2; +} + +MY_FLOAT Controller :: getByte3() +{ + return byte3; +} + +MY_FLOAT Controller :: getChannel() +{ + return channel; +} + +void Controller :: setDefaultTicks(long nSamples) +{ + default_ticks = nSamples; +} + +int Controller :: getNextMessage() +{ +#if defined(__STK_REALTIME_) + static fd_set rmask; + static struct timeval timeout = {0, 0}; + static int device = 0; + static int nSockets = 0; + static int fd_thread = 0; + int checked = 0, i; + char msg[256]; +#endif + + // reset message type + type = 0; + + if (!source) { + // no realtime flags ... assuming scorefile input + memset(message[msg_index], 0, MESSAGE_LENGTH); + if ( fgets(message[msg_index], MESSAGE_LENGTH, stdin) == 0 ) + return -1; + goto have_message; + } + +#if defined(__STK_REALTIME_) + + if (num_messages > 0) + goto have_message; + + while (checked < nSockets+1) { + + if ( source & STK_SOCKET ) { + + rmask = mask; + if (select(maxfd+1, &rmask, (fd_set *)0, (fd_set *)0, &timeout)) { + // there is a file descriptor set + + // check whether there's a new socket connection available + if ( FD_ISSET(local_socket, &rmask) ) { + // accept and service new connection + int remote_socket=accept(local_socket, NULL, NULL); + if (remote_socket < 0) { + sprintf(msg, "Controller: Couldn't accept connection request!\n"); + throw StkError(msg, StkError::PROCESS_SOCKET); + } + if (nSockets != 0) + // print message for connections subsequent to "piping" socket + printf("New socket connection made.\n\n"); + + // set the socket non-blocking +#if (defined(__OS_IRIX_) || defined(__OS_Linux_)) + fcntl(remote_socket, F_SETFL, O_NONBLOCK); +#elif defined(__OS_Win_) + unsigned long non_block = 1; + ioctlsocket(remote_socket, FIONBIO, &non_block); +#endif + + fd[nSockets] = remote_socket; + if (nSockets == 0) fd_thread = remote_socket; + nSockets++; + FD_SET(remote_socket, &mask); + if ( remote_socket > maxfd) maxfd = remote_socket; + FD_CLR(local_socket, &rmask); + } + + + + // check socket connections + while (device < nSockets) { + if (FD_ISSET(fd[device], &rmask)) { + // this socket has data + i = parseSocketData(fd[device]); + if (i == 0) { + // the socket connection closed + nSockets--; + if ( nSockets == 0 ) + return -1; + if ( nSockets == 1 && FD_ISSET(fd_thread, &mask) ) { + // the "piping" socket is still running + if (source & STK_MIDI) { + printf("MIDI input still running ... type 'Exit' to quit.\n\n"); + return 0; + } + else if (!(source & STK_PIPE) ) + return -1; + } + if (device < nSockets) { + // move descriptors down in the list + for (int j=device; j= nSockets+1) break; + } + } + else { // no file descriptors were set + device += nSockets; + checked += nSockets; + } + } + + // check MIDI + if (device >= nSockets) { + //printf("got here, nSockets = %d, checked = %d, device = %d\n", nSockets, checked, device); + device = 0; + if (source & STK_MIDI) { + if ( midi_input->nextMessage() > 0 ) { + // get MIDI message info + type = midi_input->getType(); + channel = midi_input->getChannel(); + byte2 = midi_input->getByteTwo(); + byte3 = midi_input->getByteThree(); + return default_ticks; + } + } + if (++checked >= nSockets+1) break; + } + } + // if we get here, we checked all devices but found no messages + return default_ticks; + +#endif // __STK_REALTIME + + have_message: + + //printf("%s", message[msg_index]); + long ticks; + score->parseThis(message[msg_index++]); + num_messages--; + if (msg_index >= MAX_MESSAGES) msg_index = 0; + type = score->getType(); + if (type > 0) { + MY_FLOAT temp = score->getDelta(); + if ( temp >= 0.0 ) + ticks = (long) (temp * SRATE); + else + // negative delta times specify realtime messages + ticks = default_ticks; + + channel = score->getChannel(); + byte2 = score->getByteTwo(); + byte3 = score->getByteThree(); + } + else { + // Don't tick for comments or improperly formatted messages + ticks = 0; + } + + return ticks; +} + +#if defined(__STK_REALTIME_) + +int Controller :: parseSocketData(int fd) +{ + /* + Parsing the socket data buffer is complicated by the fact that + multiple and sometimes incomplete socket messages can be returned + from a single recv() call, especially during high socket activity. + This method will read all data available from a socket connection, + filling the message buffer. This is necessary because the select() + function triggers on socket activity, not on the presence of + (buffered) data. So, whenever activity is indicated, we need to + grab all available data. + */ + + static char socket_buffer[MESSAGE_LENGTH]; + int index = 0, m = 0, bufsize = 0; + int fill_msg; + + fill_msg = (msg_index + num_messages) % MAX_MESSAGES; + memset(message[fill_msg], 0, MESSAGE_LENGTH); + +#if (defined(__OS_IRIX_) || defined(__OS_Linux_)) + errno = 0; + while (bufsize != -1 && errno != EAGAIN) { +#elif defined(__OS_Win_) + while (bufsize != SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK) { +#endif + while (index < bufsize) { + message[fill_msg][m++] = socket_buffer[index]; + if (socket_buffer[index++] == '\n') { + m = 0; + num_messages++; + fill_msg = (msg_index + num_messages) % MAX_MESSAGES; + memset(message[fill_msg], 0, MESSAGE_LENGTH); + } + } + index = 0; + + // receive a new socket buffer + memset(socket_buffer, 0, MESSAGE_LENGTH); + bufsize = recv(fd, socket_buffer, MESSAGE_LENGTH, 0); + if (bufsize == 0) { + FD_CLR(fd, &mask); +#if defined(__OS_Win_) + closesocket(fd); +#else + close(fd); +#endif + return 0; + } + } + + return 1; +} + +#if (defined(__OS_IRIX_) || defined(__OS_Linux_)) + +void *stdinHandler(void *) + +#elif defined(__OS_Win_) + +void stdinHandler(void *) + +#endif +{ + char message[MESSAGE_LENGTH]; + char msg[256]; + int local_socket; + struct sockaddr_in server_address; + +#if defined(__OS_Win_) // Windoze-only stuff + WSADATA wsaData; + WORD wVersionRequested = MAKEWORD(1,1); + + WSAStartup(wVersionRequested, &wsaData); + if (wsaData.wVersion != wVersionRequested) { + sprintf(msg, "Controller: Wrong Windoze socket library version!\n"); + throw StkError(msg, StkError::PROCESS_SOCKET); + } +#endif + + // Create the client-side socket + local_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (local_socket < 0) { + sprintf(msg, "Controller: Couldn't create socket!\n"); + throw StkError(msg, StkError::PROCESS_SOCKET); + } + + struct hostent *hostp; + hostp = gethostbyname("localhost"); + + // Fill in the address structure + server_address.sin_family = AF_INET; + memcpy((void *)&server_address.sin_addr, hostp->h_addr, hostp->h_length); + server_address.sin_port = htons(STK_SOCKET_PORT); + + // Connect to the server + if (connect(local_socket, (struct sockaddr *)&server_address, + sizeof(server_address) ) < 0) { +#if defined(__OS_Win_) + closesocket(local_socket); + WSACleanup(); +#else + close(local_socket); +#endif + sprintf(msg, "Controller: Couldn't connect stdin socket thread to server!\n"); + throw StkError(msg, StkError::PROCESS_SOCKET); + } + + for (;;) { + memset(message, 0, MESSAGE_LENGTH); + if ( fgets(message, MESSAGE_LENGTH, stdin) == 0 ) + break; + // check for an "Exit" message + if ( !strncmp(message, "Exit", 4) || !strncmp(message, "exit", 4) ) + break; + + if (send(local_socket, (const char *)message, strlen(message), 0) < 0) { +#if defined(__OS_Win_) + closesocket(local_socket); + WSACleanup(); +#else + close(local_socket); +#endif + sprintf(msg, "Controller: connection to socket server failed!\n"); + throw StkError(msg, StkError::PROCESS_SOCKET); + } + } + +#if defined(__OS_Win_) + closesocket(local_socket); + _endthread(); +#else + close(local_socket); + return NULL; +#endif +} + +#endif // __STK_REALTIME diff --git a/STK/DCBlock.cpp b/src/DCBlock.cpp similarity index 100% rename from STK/DCBlock.cpp rename to src/DCBlock.cpp diff --git a/STK/DLineA.cpp b/src/DLineA.cpp similarity index 100% rename from STK/DLineA.cpp rename to src/DLineA.cpp diff --git a/src/DLineL.cpp b/src/DLineL.cpp new file mode 100644 index 0000000..cf86593 --- /dev/null +++ b/src/DLineL.cpp @@ -0,0 +1,172 @@ +/*******************************************/ +/* + Linearly Interpolating Delay Line + Object by Perry R. Cook 1995-96. + Added methods by Julius Smith, 2000. + + This one uses a delay line of maximum + length specified on creation, and + linearly interpolates fractional + length. It is designed to be more + efficient if the delay length is not + changed very often. +*/ +/*******************************************/ + +#include "DLineL.h" + +DLineL :: DLineL() +{ + // Default max delay length set to 2047. + length = 2048; + inputs = (MY_FLOAT *) malloc(length * sizeof(MY_FLOAT)); + this->clear(); + inPoint = 0; + outPoint = length >> 1; + currentDelay = outPoint; +} + +DLineL :: DLineL(long max_length) +{ + length = max_length; + inputs = (MY_FLOAT *) malloc(length * sizeof(MY_FLOAT)); + this->clear(); + inPoint = 0; + outPoint = length >> 1; + currentDelay = outPoint; +} + +DLineL :: ~DLineL() +{ + free(inputs); +} + +void DLineL :: clear() +{ + long i; + for (i=0;i length-1) { + // delay is too big, + printf("DLineL: Delay length too big.\n"); + printf("Setting to maximum length of %ld.\n",length-1); + // force delay to max_length + outPointer = inPoint + 1; + currentDelay = length - 1; + } + else { + // read chases write + outPointer = inPoint - lag; + currentDelay = lag; + } + + while (outPointer<0) + // modulo maximum length + outPointer += length; + + // integer part + outPoint = (long) outPointer; + // fractional part + alpha = outPointer - outPoint; + omAlpha = (MY_FLOAT) 1.0 - alpha; +} + +MY_FLOAT DLineL :: delay(void) +{ + return currentDelay; +} + +MY_FLOAT DLineL :: energy(void) +{ + int i; + register MY_FLOAT e = 0; + if (inPoint>=outPoint) { + for (i=outPoint;i= length) i = length-1; + if (i != n) { + fprintf(stderr, + "DLineL: contentsAt(%d) overflows length %ld delay line\n", + n, length); + } + return inputs[i]; +} + +MY_FLOAT DLineL :: contentsAtNowMinus(int n) +{ + /* "Now" is always where inPoint points which is not yet written. */ + /* outPoint points to "now - delay". Thus, valid values for n are 1 to delay. */ + int i = n; + if (i<1) i=1; + if (i>length) i = length; + if (i != n) { + fprintf(stderr, + "DLineL: contentsAtNowMinus(%d) overflows length %ld delay line\n" + "Clipped\n", n,length); + } + int ndx = inPoint-i; + if (ndx < 0) { /* Check for wraparound */ + ndx += length; + if (ndx < 0 || ndx >= length) + fprintf(stderr,"DLineL: contentsAtNowMinus(): can't happen\n"); + } + return inputs[ndx]; +} + +MY_FLOAT DLineL :: tick(MY_FLOAT sample) +{ + inputs[inPoint++] = sample; + + // Check for end condition + if (inPoint == length) + inPoint -= length; + + // First 1/2 of interpolation + lastOutput = inputs[outPoint++] * omAlpha; + // Check for end condition + if (outPointclear(); + inPoint = 0; + outPoint = length >> 1; + currentDelay = outPoint; +} + +DLineN :: DLineN(long max_length) +{ + // Writing before reading allows delays from 0 to length-1. + // Thus, if we want to allow a delay of max_length, we need + // a delay-line of length = max_length+1. + length = max_length+1; + inputs = (MY_FLOAT *) malloc(length * sizeof(MY_FLOAT)); + this->clear(); + inPoint = 0; + outPoint = length >> 1; + currentDelay = outPoint; +} + +DLineN :: ~DLineN() +{ + free(inputs); +} + +void DLineN :: clear(void) +{ + long i; + for (i=0;i length-1) { + // delay is too big + printf("DLineN: Delay length too big ... setting to maximum length of %ld.\n",length-1); + // force delay to max_length + outPoint = inPoint + 1; + currentDelay = length - 1; + } + else { + outPoint = inPoint - (long) lag; // read chases write + currentDelay = lag; + } + + while (outPoint<0) outPoint += length; // modulo maximum length +} + +MY_FLOAT DLineN :: delay(void) +{ + return currentDelay; +} + +MY_FLOAT DLineN :: energy(void) +{ + int i; + register MY_FLOAT e = 0; + if (inPoint>=outPoint) { + for (i=outPoint;i= length) i = length-1; + if (i != n) { + fprintf(stderr, + "DLineN: contentsAt(%d) overflows length %ld delay line\n", + n, length); + } + return inputs[i]; +} + +MY_FLOAT DLineN :: contentsAtNowMinus(int n) +{ + /* "Now" is always where inPoint points which is not yet written. */ + /* outPoint points to "now - delay". Thus, valid values for n are 1 to delay. */ + + int i = n; + if (i<1) i=1; + if (i>length) i = length; + if (i != n) { + fprintf(stderr, + "DLineN: contentsAtNowMinus(%d) overflows length %ld delay line\n" + "Clipped\n", n, length); + } + int ndx = inPoint-i; + if (ndx < 0) { /* Check for wraparound */ + ndx += length; + if (ndx < 0 || ndx >= length) + fprintf(stderr,"DLineN: contentsAtNowMinus(): can't happen\n"); + } + return inputs[ndx]; +} + +MY_FLOAT DLineN :: tick(MY_FLOAT sample) +{ + inputs[inPoint++] = sample; + + // Check for end condition + if (inPoint == length) + inPoint -= length; + // Read out next value + lastOutput = inputs[outPoint++]; + + if (outPoint>=length) + outPoint -= length; + return lastOutput; +} diff --git a/STK/DrumSynt.cpp b/src/DrumSynt.cpp similarity index 98% rename from STK/DrumSynt.cpp rename to src/DrumSynt.cpp index b9d7072..a4ef9ee 100644 --- a/STK/DrumSynt.cpp +++ b/src/DrumSynt.cpp @@ -91,7 +91,7 @@ void DrumSynt :: noteOn(MY_FLOAT freq, MY_FLOAT amp) OnePole *tempFilt; /* Yes I know, this is tres kludgey */ - noteNum = (int) ((12*log(freq/220)/log(2)) + 57.01); + noteNum = (int) ((12*log(freq/220)/log(2.0)) + 57.01); vel = (int) (amp * 127); #if defined(_debug_) @@ -128,7 +128,6 @@ void DrumSynt :: noteOn(MY_FLOAT freq, MY_FLOAT amp) if (SRATE != 22050) { waves[numSounding-1]->setRate((MY_FLOAT) (22050.0/SRATE)); } - waves[numSounding-1]->normalize((MY_FLOAT) 0.4); filters[numSounding-1]->setPole((MY_FLOAT) 0.999 - ((MY_FLOAT) vel * NORM_7 * 0.6)); filters[numSounding-1]->setGain(vel / (MY_FLOAT) 128.0); } diff --git a/STK/Envelope.cpp b/src/Envelope.cpp similarity index 100% rename from STK/Envelope.cpp rename to src/Envelope.cpp diff --git a/src/FIR.cpp b/src/FIR.cpp new file mode 100644 index 0000000..3ee4165 --- /dev/null +++ b/src/FIR.cpp @@ -0,0 +1,67 @@ +/********************************************/ +/* + General Finite-Impulse-Response (FIR) + Digital Filter Class + by Julius Smith, 1997 +*/ +/********************************************/ + +#include "FIR.h" + +FIR :: FIR(int theLength) : Object() +{ + length = theLength; + coeffs = (MY_FLOAT *) malloc(length * sizeof(MY_FLOAT)); + pastInputs = (MY_FLOAT *) calloc(2*length, sizeof(MY_FLOAT)); + piOffset = length; +} + +FIR :: ~FIR() +{ + free(pastInputs); + free(coeffs); +} + +void FIR :: clear() +{ + int i; + for (i=0; i < 2*length; i++) { + pastInputs[i] = 0; + } + piOffset = length; +} + +void FIR :: setCoeffs(MY_FLOAT *theCoeffs) +{ + int i; + for (i=0; i < length; i++) { + coeffs[i] = theCoeffs[i]; + } +} + +MY_FLOAT FIR :: tick(MY_FLOAT input) { + int i; + lastOutput = input*coeffs[0]; + for (i=1; i= 2*length) { // sample 2*length-1 unused + piOffset = length; + for (i=0; inormalize(); vibWave->setFreq((MY_FLOAT) 6.0); /* should make this random?? */ modDepth = (MY_FLOAT) 0.0; /* We don't make the waves here yet, because */ @@ -82,14 +81,10 @@ FM4Op :: ~FM4Op() void FM4Op :: loadWaves(char* wave1, char* wave2, char* wave3, char* wave4) { - int i; waves[0] = new RawWvIn(wave1,"looping"); waves[1] = new RawWvIn(wave2,"looping"); waves[2] = new RawWvIn(wave3,"looping"); waves[3] = new RawWvIn(wave4,"looping"); - for (i=0;i<4;i++) { - waves[i]->normalize(); - } } void FM4Op :: setFreq(MY_FLOAT frequency) { diff --git a/STK/FMVoices.cpp b/src/FMVoices.cpp similarity index 100% rename from STK/FMVoices.cpp rename to src/FMVoices.cpp diff --git a/STK/Filter.cpp b/src/Filter.cpp similarity index 100% rename from STK/Filter.cpp rename to src/Filter.cpp diff --git a/STK/Flute.cpp b/src/Flute.cpp similarity index 99% rename from STK/Flute.cpp rename to src/Flute.cpp index ddffaf8..cb568e5 100644 --- a/STK/Flute.cpp +++ b/src/Flute.cpp @@ -41,7 +41,6 @@ Flute :: Flute(MY_FLOAT lowestFreq) filter->setPole((MY_FLOAT) 0.7 - ((MY_FLOAT) 0.1 * (MY_FLOAT) 22050.0 / SRATE)); filter->setGain((MY_FLOAT) -1.0); - vibr->normalize(); vibr->setFreq((MY_FLOAT) 5.925); adsr->setAllTimes((MY_FLOAT) 0.005, (MY_FLOAT) 0.01, (MY_FLOAT) 0.8, (MY_FLOAT) 0.010); endRefl = (MY_FLOAT) 0.5; diff --git a/STK/FormSwep.cpp b/src/FormSwep.cpp similarity index 100% rename from STK/FormSwep.cpp rename to src/FormSwep.cpp diff --git a/STK/HeavyMtl.cpp b/src/HeavyMtl.cpp similarity index 100% rename from STK/HeavyMtl.cpp rename to src/HeavyMtl.cpp diff --git a/STK/Instrmnt.cpp b/src/Instrmnt.cpp similarity index 100% rename from STK/Instrmnt.cpp rename to src/Instrmnt.cpp diff --git a/STK/JCRev.cpp b/src/JCRev.cpp similarity index 100% rename from STK/JCRev.cpp rename to src/JCRev.cpp diff --git a/STK/JetTabl.cpp b/src/JetTabl.cpp similarity index 100% rename from STK/JetTabl.cpp rename to src/JetTabl.cpp diff --git a/STK/LipFilt.cpp b/src/LipFilt.cpp similarity index 100% rename from STK/LipFilt.cpp rename to src/LipFilt.cpp diff --git a/STK/MD2SKINI.cpp b/src/MD2SKINI.cpp similarity index 98% rename from STK/MD2SKINI.cpp rename to src/MD2SKINI.cpp index 765bdc7..8716a47 100644 --- a/STK/MD2SKINI.cpp +++ b/src/MD2SKINI.cpp @@ -10,7 +10,7 @@ /* messages. */ /*******************************************/ -#include "MIDIIO.h" +#include "RtMidi.h" #include "SKINI11.msg" #if defined(__STK_REALTIME_) @@ -94,7 +94,7 @@ int main(int argc,char *argv[]) int firstMessage = 1; int writeFileOut = 0; FILE *fileOut = NULL; - MIDIIO *controller; + RtMidi *controller; char hostName[256]; char fileName[256]; int useSocket = 0; @@ -141,7 +141,13 @@ int main(int argc,char *argv[]) } MY_FLOAT dt=0.0; - controller = new MIDIIO(); + try { + controller = new RtMidi(); + } + catch (StkError& m) { + m.printMessage(); + exit(0); + } // If using sockets, setup the client socket if (useSocket) { diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..b1409f2 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,52 @@ +# stklib Makefile - for Linux or SGI with GNU Makefile utilities + +LIBRARY = stklib.a +AR = ar -qsc +RM = /bin/rm +INCLUDE = -I../include + +OS = $(shell uname) + +O_FILES = Object.o Envelope.o ADSR.o Noise.o SubNoise.o \ + Filter.o OneZero.o OnePole.o PoleZero.o DCBlock.o FIR.o \ + TwoZero.o TwoPole.o BiQuad.o DLineA.o DLineL.o DLineN.o \ + BowTabl.o JetTabl.o ReedTabl.o LipFilt.o TablLook.o \ + \ + Instrmnt.o Modal4.o ModalBar.o Shakers.o \ + Plucked.o Plucked2.o Mandolin.o Bowed.o Clarinet.o \ + Flute.o Brass.o BlowHole.o BowedBar.o \ + FM4Op.o FM4Alg3.o FM4Alg4.o FM4Alg5.o FM4Alg6.o FM4Alg8.o \ + Rhodey.o Wurley.o TubeBell.o HeavyMtl.o \ + PercFlut.o BeeThree.o DrumSynt.o Moog1.o \ + Sampler.o SamplFlt.o Simple.o SingWave.o \ + VoicForm.o FMVoices.o FormSwep.o Modulatr.o VoicMang.o \ + \ + WvOut.o SndWvOut.o WavWvOut.o MatWvOut.o RawWvOut.o AifWvOut.o \ + WvIn.o SndWvIn.o WavWvIn.o MatWvIn.o RawWvIn.o AifWvIn.o \ + StrmWvIn.o StrmWvOut.o \ + RtWvOut.o RtAudio.o RtWvIn.o RtMidi.o RtDuplex.o \ + Reverb.o PRCRev.o JCRev.o NRev.o \ + \ + SKINI11.o Controller.o ByteSwap.o StkError.o + +ifeq ($(OS),IRIX) # These are for SGI + CC = CC -D__OS_IRIX_ +endif + +ifeq ($(OS),Linux) # These are for Linux + CC = g++ -O3 -Wall -D__OS_Linux_ +endif + +%.o : %.cpp + $(CC) $(INCLUDE) -c $(<) -o $@ + +debug all: $(LIBRARY) + +$(LIBRARY): $(O_FILES) + /bin/rm -f $(LIBRARY) + $(AR) $(LIBRARY) $(O_FILES) + ranlib -t $(LIBRARY) + +clean : + rm *.o + rm $(LIBRARY) diff --git a/STK/Mandolin.cpp b/src/Mandolin.cpp similarity index 99% rename from STK/Mandolin.cpp rename to src/Mandolin.cpp index cd30db8..a659ad0 100644 --- a/STK/Mandolin.cpp +++ b/src/Mandolin.cpp @@ -124,7 +124,7 @@ MY_FLOAT Mandolin :: tick() temp + (delayLine2->lastOut() * loopGain))); } - lastOutput *= (MY_FLOAT) 0.3 / 32768.0; + lastOutput *= (MY_FLOAT) 0.3; return lastOutput; } diff --git a/src/MatWvIn.cpp b/src/MatWvIn.cpp new file mode 100644 index 0000000..740a805 --- /dev/null +++ b/src/MatWvIn.cpp @@ -0,0 +1,235 @@ +/*******************************************/ +/* MatWvIn Input Class, */ +/* by Gary P. Scavone, 1999 */ +/* */ +/* This object inherits from WvIn and is */ +/* used to open Matlab MAT-file data */ +/* (doubles) files for playback. In */ +/* order for this class to work, the */ +/* MAT-file must contain a single array */ +/* (matrix) of double-precision floating */ +/* point values (can be multi-channel). */ +/* It does not work for any other data */ +/* formats. */ +/* */ +/* MAT-file data is either big- or */ +/* little-endian, which can be determined */ +/* from the header. */ +/*******************************************/ + +#include "MatWvIn.h" +#include "ByteSwap.h" + +MatWvIn :: MatWvIn(char *fileName, char *mode) +{ + char msg[256]; + + // check mode string + if ( strcmp(mode,"oneshot") && strcmp(mode,"looping") ) { + sprintf(msg, "MatWvIn: constructor parameter 'mode' must be oneshot or looping only.\n"); + throw StkError(msg, StkError::FUNCTION_SYNTAX); + } + + // Open the file and get header info + fd = fopen(fileName,"rb"); + if (!fd) { + sprintf(msg, "MatWvIn: Couldn't open or find MAT-file (%s).\n", fileName); + throw StkError(msg, StkError::FILE_NOT_FOUND); + } + + // Make sure this is a version 5 MAT-file format and find its endian-ness + char head[4]; + fseek(fd,0,SEEK_SET); + fread(&head,4,1,fd); // If any of the first 4 characters of the header = 0, + if (strstr(head,"0")) { // then this is a Version 4 MAT-file. + fclose(fd); + sprintf(msg, "MatWvIn: %s appears to be a Version 4 \nMAT-file, which is not currently supported.\n", + fileName); + throw StkError(msg, StkError::FILE_ERROR); + } + char mi[2]; + doSwap = 0; + fseek(fd,126,SEEK_SET); // Locate "M" and "I" characters in header + fread(&mi,2,1,fd); +#ifdef __LITTLE_ENDIAN__ + if (!strncmp(mi,"MI",2)) { + doSwap = 1; + } else if (strncmp(mi,"IM",2)) { + fclose(fd); + sprintf(msg, "MatWvIn: %s doesn't appear to be a MAT-file.\n", fileName); + throw StkError(msg, StkError::FILE_ERROR); + } +#else + if (!strncmp(mi,"IM",2)) { + doSwap = 1; + } else if (strncmp(mi,"MI",2)) { + fclose(fd); + sprintf(msg, "MatWvIn: %s doesn't appear to be a MAT-file.\n", fileName); + throw StkError(msg, StkError::FILE_ERROR); + } +#endif + + // Check the data element type + INT32 datatype; + fread(&datatype,4,1,fd); + if (doSwap) swap32((unsigned char *)&datatype); + if (datatype != 14) { + fclose(fd); + sprintf(msg, "MatWvIn: I'm expecting a single array (or matrix) data element.\n"); + throw StkError(msg, StkError::FILE_ERROR); + } + + // Check the array data type + INT32 tmp; + INT32 size; + fseek(fd,168,SEEK_SET); + fread(&tmp,4,1,fd); + if (doSwap) swap32((unsigned char *)&tmp); + if (tmp == 1) { // array name > 4 characters + fread(&tmp,4,1,fd); // get array name length + if (doSwap) swap32((unsigned char *)&tmp); + size = (INT32) ceil((float)tmp/8); + fseek(fd,size*8,SEEK_CUR); // jump over array name + } + else { // array name <= 4 characters, compressed data element + fseek(fd,4,SEEK_CUR); + } + fread(&tmp,4,1,fd); + if (doSwap) swap32((unsigned char *)&tmp); + if (tmp != 9) { + fclose(fd); + sprintf(msg, "MatWvIn: I'm expecting the array data to be in double precision floating-point format.\n"); + throw StkError(msg, StkError::FILE_ERROR); + } + + // Get number of rows from the header + INT32 rows; + fseek(fd,160,SEEK_SET); + fread(&rows,4,1,fd); + if (doSwap) swap32((unsigned char *)&rows); + + // Get number of columns from the header + INT32 columns; + fread(&columns,4,1,fd); // columns + if (doSwap) swap32((unsigned char *)&columns); + + // Make channels = smaller of rows or columns + if (rows < columns) { + channels = rows; + fileSize = columns; + interleaved = 1; + } + else { + channels = columns; + fileSize = rows; + interleaved = 0; + } + bufferSize = fileSize; + + if ((fileSize*channels) > MAX_FILE_LOAD_SIZE) { + printf("\nMatWvIn: The MAT-file (%s) has more than %d samples and\n", + fileName, MAX_FILE_LOAD_SIZE); + printf("will be loaded incrementally from disk. Normalization will be disabled.\n"); + chunking = 1; + bufferSize = LOAD_BUFFER_SIZE; + } + + // Setup for looping or one-shot playback + if (!strcmp(mode,"looping")) + looping = 1; + else // default = oneshot + looping = 0; + + data = (MY_FLOAT *) new MY_FLOAT[(bufferSize+1)*channels]; + + // Move read pointer to the data in the file + INT32 headsize; + fseek(fd,132,SEEK_SET); + fread(&headsize,4,1,fd); // file size from 132nd byte + if (doSwap) swap32((unsigned char *)&headsize); + headsize -= fileSize * 8 * channels; + fseek(fd,headsize,SEEK_CUR); + dataOffset = ftell(fd); + + this->getData(0); // Read samples into data[] + + rate = (MY_FLOAT) 1.0; + interpolate = 0; + phaseOffset = (MY_FLOAT) 0.0; + lastOutput = (MY_FLOAT *) new MY_FLOAT[channels]; + this->reset(); +} + +MatWvIn :: ~MatWvIn() +{ +} + +void MatWvIn :: getData(long index) +{ + /* Compare index to current readPointer and modify as needed. + * The following while() loops will only execute on calls subsequent + * to class instantiation ... and thus, only when "chunking". + */ + while (index < readPointer) { + readPointer -= LOAD_BUFFER_SIZE; + bufferSize = LOAD_BUFFER_SIZE; + if (readPointer < 0) { + bufferSize += readPointer; + readPointer = 0; + } + } + while (index >= readPointer+bufferSize) { + readPointer += LOAD_BUFFER_SIZE; + bufferSize = LOAD_BUFFER_SIZE; + if (readPointer+LOAD_BUFFER_SIZE >= fileSize) { + bufferSize = fileSize - readPointer; + } + } + + long length = bufferSize; + int end_of_file = (readPointer+bufferSize == fileSize); + if (!end_of_file) length += 1; + + // Read samples into data[]. Use MY _FLOAT data structure to store doubles + double *buf = (double *)data; + if (interleaved) { + fseek(fd, dataOffset+(long)(readPointer*channels*8), SEEK_SET); + fread(data, 8, length*channels, fd); + for (int i=length*channels-1; i>=0; i--) { + if (doSwap) + swap64((unsigned char *)(buf+i)); + data[i] = buf[i]; + } + } + else { + long i = 0; + long j = 0; + double temp; + fseek(fd, dataOffset+(long)(readPointer*8), SEEK_SET); + while (j < channels) { + fread(&temp,8,1,fd); + if (doSwap) swap64((unsigned char *)&temp); + data[channels*i+j] = (MY_FLOAT) temp; + i++; + if (i>=length) { + i = 0; + j++; + fseek(fd, dataOffset+(long)(((j*fileSize)+readPointer)*8), SEEK_SET); + } + } + } + + // fill in the extra sample frame for interpolation + if (end_of_file) { + for (int j=0; jsetFreq((MY_FLOAT) 6.0); + vibrGain = (MY_FLOAT) 0.0; // zero gain by default + + directGain = (MY_FLOAT) 0.0; + masterGain = (MY_FLOAT) 1.0; + baseFreq = (MY_FLOAT) 440.0; + this->setRatioAndReson(0,(MY_FLOAT) 1.00,(MY_FLOAT) 0.9997); /* Set some */ + this->setRatioAndReson(1,(MY_FLOAT) 1.30,(MY_FLOAT) 0.9997); /* silly */ + this->setRatioAndReson(2,(MY_FLOAT) 1.77,(MY_FLOAT) 0.9997); /* default */ + this->setRatioAndReson(3,(MY_FLOAT) 2.37,(MY_FLOAT) 0.9997); /* values here */ + this->setFiltGain(0,(MY_FLOAT) 0.01); + this->setFiltGain(1,(MY_FLOAT) 0.01); + this->setFiltGain(2,(MY_FLOAT) 0.01); + this->setFiltGain(3,(MY_FLOAT) 0.01); + this->clear(); + filters[0]->setEqualGainZeroes(); + filters[1]->setEqualGainZeroes(); + filters[2]->setEqualGainZeroes(); + filters[3]->setEqualGainZeroes(); + stickHardness = (MY_FLOAT) 0.5; + strikePosition = (MY_FLOAT) 0.561; +} + +Modal4 :: ~Modal4() +{ + delete envelope; + delete filters[0]; + delete filters[1]; + delete filters[2]; + delete filters[3]; + delete onepole; + delete vibr; +} + +void Modal4 :: clear() +{ + onepole->clear(); + filters[0]->clear(); + filters[1]->clear(); + filters[2]->clear(); + filters[3]->clear(); +} + +void Modal4 :: setFreq(MY_FLOAT frequency) +{ + baseFreq = frequency; + this->setRatioAndReson(0,ratios[0],resons[0]); + this->setRatioAndReson(1,ratios[1],resons[1]); + this->setRatioAndReson(2,ratios[2],resons[2]); + this->setRatioAndReson(3,ratios[3],resons[3]); +} + +#include + +void Modal4 :: setRatioAndReson(int whichOne, MY_FLOAT ratio,MY_FLOAT reson) +{ + MY_FLOAT temp; + + if (ratio*baseFreq < SRATE_OVER_TWO) { + ratios[whichOne] = ratio; + } + else { + temp = ratio; + while (temp*baseFreq > SRATE_OVER_TWO) temp *= (MY_FLOAT) 0.5; + ratios[whichOne] = temp; +#if defined(_debug_) + printf("Modal4 : Aliasing would occur here, correcting.\n"); +#endif + } + resons[whichOne] = reson; + if (ratio < 0) + temp = -ratio; + else + temp = ratio*baseFreq; + + filters[whichOne]->setFreqAndReson(temp,reson); +} + +void Modal4 :: setMasterGain(MY_FLOAT aGain) +{ + masterGain = aGain; +} + +void Modal4 :: setDirectGain(MY_FLOAT aGain) +{ + directGain = aGain; +} + +void Modal4 :: setFiltGain(int whichOne, MY_FLOAT gain) +{ + filters[whichOne]->setGain(gain); +} + +void Modal4 :: strike(MY_FLOAT amplitude) +{ + int i; + MY_FLOAT temp; + + envelope->setRate((MY_FLOAT) 1.0); + envelope->setTarget(amplitude); + onepole->setPole((MY_FLOAT) 1.0 - amplitude); + envelope->tick(); + wave->reset(); + + for (i=0; i<4; i++) { + if (ratios[i] < 0) + temp = -ratios[i]; + else + temp = ratios[i] * baseFreq; + filters[i]->setFreqAndReson(temp,resons[i]); + } +} + +void Modal4 :: noteOn(MY_FLOAT freq, MY_FLOAT amp) +{ + this->strike(amp); + this->setFreq(freq); +#if defined(_debug_) + printf("Modal4 : NoteOn: Freq=%lf Amp=%lf\n",freq,amp); +#endif +} + +/* This calls damp, but inverts the meaning of amplitude + * (high amplitude means fast damping). + */ +void Modal4 :: noteOff(MY_FLOAT amp) +{ + this->damp((MY_FLOAT) 1.0 - (amp * (MY_FLOAT) 0.03)); +#if defined(_debug_) + printf("Modal4 : NoteOff: Amp=%lf\n",amp); +#endif +} + +void Modal4 :: damp(MY_FLOAT amplitude) +{ + int i; + MY_FLOAT temp; + + for (i=0; i<4; i++) { + if (ratios[i] < 0) + temp = -ratios[i]; + else + temp = ratios[i] * baseFreq; + filters[i]->setFreqAndReson(temp,resons[i]*amplitude); + } +} + +void Modal4 :: controlChange(int number, MY_FLOAT value) +{ +} + +MY_FLOAT Modal4 :: tick() +{ + MY_FLOAT temp,temp2; + + temp = masterGain * onepole->tick(wave->tick() * envelope->tick()); + temp2 = filters[0]->tick(temp); + temp2 += filters[1]->tick(temp); + temp2 += filters[2]->tick(temp); + temp2 += filters[3]->tick(temp); + temp2 = temp2 - (temp2 * directGain); + temp2 += directGain * temp; + + if (vibrGain != 0.0) { + // Calculate AM and apply to master out + temp = (MY_FLOAT) 1.0 + (vibr->tick() * vibrGain); + temp2 = temp * temp2; + } + + lastOutput = temp2 * (MY_FLOAT) 2.0; + return lastOutput; +} + diff --git a/src/ModalBar.cpp b/src/ModalBar.cpp new file mode 100644 index 0000000..48a69e2 --- /dev/null +++ b/src/ModalBar.cpp @@ -0,0 +1,149 @@ +/*******************************************/ +/* + ModalBar SubClass of Modal4 Instrument + by Perry R. Cook, 1999-2000 + + Controls: CONTROL1 = stickHardness + CONTROL2 = strikePosition + CONTROL3 = Mode Presets +*/ +/*******************************************/ + +#include "ModalBar.h" +#include "SKINI11.msg" + +ModalBar :: ModalBar() : Modal4() +{ + // Concatenate the STK RAWWAVE_PATH to the rawwave file + char file[128]; + strcpy(file, RAWWAVE_PATH); + wave = new RawWvIn(strcat(file,"rawwaves/marmstk1.raw"),"oneshot"); + wave->setRate((MY_FLOAT) 0.5); /* normal stick */ + + this->setRatioAndReson(0, (MY_FLOAT) 1.00,(MY_FLOAT) 0.9996); /* Set all 132.0 */ + this->setRatioAndReson(1, (MY_FLOAT) 3.99,(MY_FLOAT) 0.9994); /* of our 523.0 */ + this->setRatioAndReson(2,(MY_FLOAT) 10.65,(MY_FLOAT) 0.9994); /* default 1405.0 */ + this->setRatioAndReson(3,-(MY_FLOAT) 2443.0,(MY_FLOAT) 0.999); /* resonances 2443.0 */ + this->setFiltGain(0,(MY_FLOAT) 0.04); /* and */ + this->setFiltGain(1,(MY_FLOAT) 0.01); /* gains */ + this->setFiltGain(2,(MY_FLOAT) 0.01); /* for each */ + this->setFiltGain(3,(MY_FLOAT) 0.008); /* resonance */ + directGain = (MY_FLOAT) 0.1; +} + +ModalBar :: ~ModalBar() +{ + delete wave; +} + +void ModalBar :: setStickHardness(MY_FLOAT hardness) +{ + stickHardness = hardness; + wave->setRate((MY_FLOAT) (0.25 * (MY_FLOAT) pow(4.0,stickHardness))); + masterGain = (MY_FLOAT) 0.1 + ((MY_FLOAT) 1.8 * stickHardness); +} + +void ModalBar :: setStrikePosition(MY_FLOAT position) +{ + MY_FLOAT temp,temp2; + temp2 = position * PI; + strikePosition = position; /* Hack only first three modes */ + temp = (MY_FLOAT) sin(temp2); + this->setFiltGain(0,(MY_FLOAT) 0.12 * temp); /* 1st mode function of pos. */ + temp = (MY_FLOAT) sin(0.05 + (3.9 * temp2)); + this->setFiltGain(1,(MY_FLOAT) -0.03 * temp); /* 2nd mode function of pos. */ + temp = (MY_FLOAT) sin(-0.05 + (11 * temp2)); + this->setFiltGain(2,(MY_FLOAT) 0.11 * temp); /* 3rd mode function of pos. */ +} + +void ModalBar :: setModalPreset(int which) +{ + /* presets: + * first line: relative modal frequencies (negative number is + * a fixed mode that doesn't scale with frequency + * second line: resonances of the modes + * third line: mode volumes + * fourth line: stickHardness, strikePosition, and direct stick + * gain (mixed directly into the output + */ + int i, temp; + MY_FLOAT presets[9][4][4] = { + {{1.0, 3.99, 10.65, -2443}, // Marimba + {0.9996, 0.9994, 0.9994, 0.999}, + {0.04, 0.01, 0.01, 0.008}, + {0.429688, 0.445312, 0.093750}}, + {{1.0, 2.01, 3.9, 14.37}, // Vibraphone + {0.99995, 0.99991, 0.99992, 0.9999}, + {0.025, 0.015, 0.015, 0.015 }, + {0.390625,0.570312,0.078125}}, + {{1.0, 4.08, 6.669, -3725.0}, // Agogo + {0.999, 0.999, 0.999, 0.999}, + {0.06, 0.05, 0.03, 0.02}, + {0.609375,0.359375,0.140625}}, + {{1.0, 2.777, 7.378, 15.377}, // Wood1 + {0.996, 0.994, 0.994, 0.99}, + {0.04, 0.01, 0.01, 0.008}, + {0.460938,0.375000,0.046875}}, + {{1.0, 2.777, 7.378, 15.377}, // Reso + {0.99996, 0.99994, 0.99994, 0.9999}, + {0.02, 0.005, 0.005, 0.004}, + {0.453125,0.250000,0.101562}}, + {{1.0, 1.777, 2.378, 3.377}, // Wood2 + {0.996, 0.994, 0.994, 0.99}, + {0.04, 0.01, 0.01, 0.008}, + {0.312500,0.445312,0.109375}}, + {{1.0, 1.004, 1.013, 2.377}, // Beats + {0.9999, 0.9999, 0.9999, 0.999}, + {0.02, 0.005, 0.005, 0.004}, + {0.398438,0.296875,0.070312}}, + {{1.0, 4.0, -1320.0, -3960.0}, // 2Fix + {0.9996, 0.999, 0.9994, 0.999}, + {0.04, 0.01, 0.01, 0.008}, + {0.453125,0.453125,0.070312}}, + {{1.0, 1.217, 1.475, 1.729}, // Clump + {0.999, 0.999, 0.999, 0.999}, + {0.03, 0.03, 0.03, 0.03 }, + {0.390625,0.570312,0.078125}}, + }; + + temp = (which % 9); + for (i=0; i<4; i++) { + this->setRatioAndReson(i, presets[temp][0][i], presets[temp][1][i]); + this->setFiltGain(i,presets[temp][2][i]); + } + this->setStickHardness(presets[temp][3][0]); + this->setStrikePosition(presets[temp][3][1]); + directGain = presets[temp][3][2]; + + if (temp == 1) // vibraphone + vibrGain = 0.2; + else + vibrGain = 0.0; +} + +void ModalBar :: controlChange(int number, MY_FLOAT value) +{ +#if defined(_debug_) + printf("ModalBar : ControlChange: Number=%i Value=%f\n",number,value); +#endif + if (number == __SK_StickHardness_) + this->setStickHardness(value * NORM_7); + else if (number == __SK_StrikePosition_) + this->setStrikePosition(value * NORM_7); + else if (number == __SK_ProphesyRibbon_) + this->setModalPreset((int) value); + else if (number == __SK_ModWheel_) + directGain = value * NORM_7; + else if (number == __SK_AfterTouch_Cont_) + envelope->setTarget(value * NORM_7); + else if (number == __SK_ModFrequency_) + vibr->setFreq(value * NORM_7 * 12.0); + else if (number == 1024) { // HACKED Poop message + printf("StickHard=%f StrikePos=%f directGain=%f\n", + stickHardness, strikePosition, directGain); + } + else { + printf("ModalBar : Undefined Control Number!!\n"); + } +} + diff --git a/STK/Modulatr.cpp b/src/Modulatr.cpp similarity index 98% rename from STK/Modulatr.cpp rename to src/Modulatr.cpp index 3303a8c..da0917b 100644 --- a/STK/Modulatr.cpp +++ b/src/Modulatr.cpp @@ -16,7 +16,6 @@ Modulatr :: Modulatr() char file[128]; strcpy(file, RAWWAVE_PATH); vibwave = new RawWvIn(strcat(file,"rawwaves/sinewave.raw"),"looping"); - vibwave->normalize(); vibwave->setFreq((MY_FLOAT) 6.0); vibAmt = (MY_FLOAT) 0.04; noise = new SubNoise(330); diff --git a/STK/Moog1.cpp b/src/Moog1.cpp similarity index 97% rename from STK/Moog1.cpp rename to src/Moog1.cpp index 5cedace..20768f3 100644 --- a/STK/Moog1.cpp +++ b/src/Moog1.cpp @@ -24,9 +24,6 @@ Moog1 :: Moog1() : SamplFlt() loops[0] = new RawWvIn(strcat(file,"rawwaves/impuls20.raw"),"looping"); strcpy(file,temp); loops[1] = new RawWvIn(strcat(file,"rawwaves/sinewave.raw"),"looping"); /* Steal one for vibrato */ - attacks[0]->normalize(); - loops[0]->normalize(); - loops[1]->normalize(); loops[1]->setFreq((MY_FLOAT) 6.122); adsr->setAllTimes((MY_FLOAT) 0.001,(MY_FLOAT) 1.5,(MY_FLOAT) 0.6,(MY_FLOAT) 0.250); filterQ = (MY_FLOAT) 0.85; diff --git a/STK/NRev.cpp b/src/NRev.cpp similarity index 100% rename from STK/NRev.cpp rename to src/NRev.cpp diff --git a/STK/Noise.cpp b/src/Noise.cpp similarity index 100% rename from STK/Noise.cpp rename to src/Noise.cpp diff --git a/src/Object.cpp b/src/Object.cpp new file mode 100644 index 0000000..ac985f0 --- /dev/null +++ b/src/Object.cpp @@ -0,0 +1,24 @@ +/*********************************************/ +/* Object Class, by Perry R. Cook, 1995-99 */ +/* */ +/* This is mostly here for compatibility */ +/* with Objective C. We'll also stick */ +/* global defines here, so everyone will */ +/* see them. */ +/*********************************************/ + +#include "Object.h" + +/* This is just here for compatibility and convenience, + so there's no need to do any real calculations. + I do set up some redefinable variables in Object.h. +*/ + +Object :: Object() +{ +} + +Object :: ~Object() +{ +} + diff --git a/src/OnePole.cpp b/src/OnePole.cpp new file mode 100644 index 0000000..fed7666 --- /dev/null +++ b/src/OnePole.cpp @@ -0,0 +1,101 @@ +/*******************************************/ +/* + One Pole Filter Class, + by Perry R. Cook, 1995-96. + Added methods by Julius Smith, 2000. + + The parameter gain is an additional + gain parameter applied to the filter + on top of the normalization that takes + place automatically. So the net max + gain through the system equals the + value of gain. sgain is the combina- + tion of gain and the normalization + parameter, so if you set the poleCoeff + to alpha, sgain is always set to + gain * (1.0 - fabs(alpha)). +*/ +/*******************************************/ + +#include "OnePole.h" + +OnePole :: OnePole() : Filter() +{ + poleCoeff = (MY_FLOAT) 0.9; + gain = (MY_FLOAT) 1.0; + sgain = (MY_FLOAT) 0.1; + outputs = (MY_FLOAT *) malloc(sizeof(MY_FLOAT)); + outputs[0] = (MY_FLOAT) 0.0; + lastOutput = (MY_FLOAT) 0.0; +} + +OnePole :: OnePole(MY_FLOAT thePole) : Filter() +{ + poleCoeff = thePole; + gain = (MY_FLOAT) 1.0; + sgain = (MY_FLOAT) 1.0 - fabs(thePole); + outputs = (MY_FLOAT *) malloc(sizeof(MY_FLOAT)); + outputs[0] = (MY_FLOAT) 0.0; + lastOutput = (MY_FLOAT) 0.0; +} + +OnePole :: ~OnePole() +{ + free(outputs); +} + +void OnePole :: clear() +{ + outputs[0] = (MY_FLOAT) 0.0; + lastOutput = (MY_FLOAT) 0.0; +} + +void OnePole :: setB0(MY_FLOAT aValue) +{ + sgain = aValue; +} + +void OnePole :: setNum(MY_FLOAT *values) +{ + sgain = values[0]; +} + +void OnePole :: setA1(MY_FLOAT aValue) +{ + poleCoeff = -aValue; +} + +void OnePole :: setDen(MY_FLOAT *values) +{ + poleCoeff = -values[0]; +} + +void OnePole :: setPole(MY_FLOAT aValue) +{ + poleCoeff = aValue; + // Normalize gain to 1.0 max + if (poleCoeff > (MY_FLOAT) 0.0) + sgain = gain * ((MY_FLOAT) 1.0 - poleCoeff); + else + sgain = gain * ((MY_FLOAT) 1.0 + poleCoeff); +} + +void OnePole :: setGain(MY_FLOAT aValue) +{ + gain = aValue; + + // Normalize gain to 1.0 max + if (poleCoeff > (MY_FLOAT) 0.0) + sgain = gain * ((MY_FLOAT) 1.0 - poleCoeff); + else + sgain = gain * ((MY_FLOAT) 1.0 + poleCoeff); +} + +// Perform Filter Operation +MY_FLOAT OnePole :: tick(MY_FLOAT sample) +{ + outputs[0] = (sgain * sample) + (poleCoeff * outputs[0]); + lastOutput = outputs[0]; + return lastOutput; +} + diff --git a/STK/OneZero.cpp b/src/OneZero.cpp similarity index 100% rename from STK/OneZero.cpp rename to src/OneZero.cpp diff --git a/STK/PRCRev.cpp b/src/PRCRev.cpp similarity index 100% rename from STK/PRCRev.cpp rename to src/PRCRev.cpp diff --git a/STK/PercFlut.cpp b/src/PercFlut.cpp similarity index 100% rename from STK/PercFlut.cpp rename to src/PercFlut.cpp diff --git a/STK/Plucked.cpp b/src/Plucked.cpp similarity index 100% rename from STK/Plucked.cpp rename to src/Plucked.cpp diff --git a/STK/Plucked2.cpp b/src/Plucked2.cpp similarity index 100% rename from STK/Plucked2.cpp rename to src/Plucked2.cpp diff --git a/STK/PoleZero.cpp b/src/PoleZero.cpp similarity index 62% rename from STK/PoleZero.cpp rename to src/PoleZero.cpp index 2b9d70a..b4ccdfd 100644 --- a/STK/PoleZero.cpp +++ b/src/PoleZero.cpp @@ -12,8 +12,10 @@ PoleZero :: PoleZero() : Filter() { inputs = (MY_FLOAT *) malloc(sizeof(MY_FLOAT)); - zeroCoeff = (MY_FLOAT) 0.0; - poleCoeff = (MY_FLOAT) 0.0; + outputs = (MY_FLOAT *) malloc(sizeof(MY_FLOAT)); + b0Coeff = (MY_FLOAT) 1.0; + b1Coeff = (MY_FLOAT) 0.0; + a1Coeff = (MY_FLOAT) 0.0; gain = (MY_FLOAT) 1.0; this->clear(); } @@ -21,22 +23,29 @@ PoleZero :: PoleZero() : Filter() PoleZero :: ~PoleZero() { free(inputs); + free(outputs); } void PoleZero :: clear() { inputs[0] = (MY_FLOAT) 0.0; + outputs[0] = (MY_FLOAT) 0.0; lastOutput = (MY_FLOAT) 0.0; } -void PoleZero :: setPoleCoeff(MY_FLOAT coeff) +void PoleZero :: setA1(MY_FLOAT coeff) { - poleCoeff = coeff; + a1Coeff = coeff; } -void PoleZero :: setZeroCoeff(MY_FLOAT coeff) +void PoleZero :: setB0(MY_FLOAT coeff) { - zeroCoeff = coeff; + b0Coeff = coeff; +} + +void PoleZero :: setB1(MY_FLOAT coeff) +{ + b1Coeff = coeff; } void PoleZero :: setGain(MY_FLOAT aValue) @@ -48,15 +57,11 @@ void PoleZero :: setGain(MY_FLOAT aValue) // Look it up in your favorite DSP text MY_FLOAT PoleZero :: tick(MY_FLOAT sample) { - MY_FLOAT temp; + MY_FLOAT in_sample = gain*sample; - // Direct Form II Implementation - only 1 state variable - temp = sample * gain; - temp += inputs[0] * poleCoeff; - - lastOutput = temp; - lastOutput += (inputs[0] * zeroCoeff); - inputs[0] = temp; + lastOutput = b0Coeff*in_sample + b1Coeff*inputs[0] - a1Coeff*outputs[0]; + inputs[0] = in_sample; + outputs[0] = lastOutput; return lastOutput; } diff --git a/src/RawWvIn.cpp b/src/RawWvIn.cpp new file mode 100644 index 0000000..bd545ba --- /dev/null +++ b/src/RawWvIn.cpp @@ -0,0 +1,134 @@ +/*******************************************/ +/* RawWvIn Input Class, */ +/* by Gary P. Scavone, 2000 */ +/* */ +/* This object inherits from WvIn and is */ +/* used to open raw 16-bit data (signed */ +/* integer) files for playback. */ +/* */ +/* STK RawWave files are assumed to be */ +/* monaural and big-endian. */ +/*******************************************/ + +#include "RawWvIn.h" +#include +#include + +#ifdef __LITTLE_ENDIAN__ + #include "ByteSwap.h" +#endif + +RawWvIn :: RawWvIn(char *fileName, const char *mode) +{ + char msg[256]; + + // check mode string + if ( strcmp(mode,"oneshot") && strcmp(mode,"looping") ) { + sprintf(msg, "RawWvIn: constructor parameter 'mode' must be oneshot or looping only.\n"); + throw StkError(msg, StkError::FUNCTION_SYNTAX); + } + + // Use the system call "stat" to determine the file length + struct stat filestat; + if (stat(fileName, &filestat) == -1) { + // Opening file failed + sprintf(msg, "RawWvIn: Couldn't stat or find file (%s).\n", fileName); + throw StkError(msg, StkError::FILE_NOT_FOUND); + } + fileSize = (long) filestat.st_size / 2; // length in 2-byte samples + bufferSize = fileSize; + + if (fileSize > MAX_FILE_LOAD_SIZE) { + printf("\nRawWvIn: The .WAV file (%s) has more than %d samples and\n", + fileName, MAX_FILE_LOAD_SIZE); + printf("will be loaded incrementally from disk. Normalization will be disabled.\n"); + chunking = 1; + bufferSize = LOAD_BUFFER_SIZE; + } + + // Open the file and read samples into data[] + fd = fopen(fileName,"rb"); + if (!fd) { + sprintf(msg, "RawWvIn: Couldn't open or find file (%s).\n", fileName); + throw StkError(msg, StkError::FILE_NOT_FOUND); + } + + // Setup for looping or one-shot playback + if (!strcmp(mode,"looping")) + looping = 1; + else // default = oneshot + looping = 0; + + channels = 1; // All STK rawwave files are mono + data = (MY_FLOAT *) new MY_FLOAT[(bufferSize+1)*channels]; + + fseek(fd,0,SEEK_SET); + dataOffset = 0; + this->getData(0); // Read samples into data[] + + phaseOffset = (MY_FLOAT) 0.0; + rate = (MY_FLOAT) 1.0; + interpolate = 0; + lastOutput = (MY_FLOAT *) new MY_FLOAT[channels]; + this->reset(); + + // finally, let's normalize the data by default + this->normalize(); +} + +RawWvIn :: ~RawWvIn() +{ +} + +void RawWvIn :: getData(long index) +{ + /* Compare index to current readPointer and modify as needed. + * The following while() loops will only execute on calls subsequent + * to class instantiation ... and thus, only when "chunking". + */ + while (index < readPointer) { + readPointer -= LOAD_BUFFER_SIZE; + bufferSize = LOAD_BUFFER_SIZE; + if (readPointer < 0) { + bufferSize += readPointer; + readPointer = 0; + } + } + while (index >= readPointer+bufferSize) { + readPointer += LOAD_BUFFER_SIZE; + bufferSize = LOAD_BUFFER_SIZE; + if (readPointer+LOAD_BUFFER_SIZE >= fileSize) { + bufferSize = fileSize - readPointer; + } + } + + fseek(fd, (long)(readPointer*2), SEEK_SET); + long length = bufferSize; + int end_of_file = (readPointer+bufferSize == fileSize); + if (!end_of_file) length += 1; + + // Read samples into data[]. Use MY _FLOAT data structure to store INT16 samples + INT16 *buf = (INT16 *)data; + fread(buf, length, 2, fd); + // Convert in place (unpack) to MY_FLOAT from the end of the array + for (int i=length-1; i>=0; i--) { +#ifdef __LITTLE_ENDIAN__ + swap16((unsigned char *)(buf+i)); +#endif + data[i] = buf[i]; + if (chunking) data[i] *= 0.00003051; + } + + // fill in the extra sample frame for interpolation + if (end_of_file) { + if (looping) + data[bufferSize] = data[0]; + else + data[bufferSize] = data[(bufferSize-1)]; + } + + if (!chunking) { + fclose(fd); + fd = 0; + } +} diff --git a/STK/RawWvOut.cpp b/src/RawWvOut.cpp similarity index 51% rename from STK/RawWvOut.cpp rename to src/RawWvOut.cpp index 0b34f21..6522a05 100644 --- a/STK/RawWvOut.cpp +++ b/src/RawWvOut.cpp @@ -10,49 +10,30 @@ /*******************************************/ #include "RawWvOut.h" - #ifdef __LITTLE_ENDIAN__ - #include "swapstuf.h" + #include "ByteSwap.h" #endif -RawWvOut :: RawWvOut(char *fileName) +RawWvOut :: RawWvOut(char *fileName, int chans) { char tempName[128]; + char msg[128]; - channels = 1; + if (chans != 1) { + sprintf(msg, "RawWvOut: STK rawwave files are always monaural (channels = %d not supported)!\n", chans); + throw StkError(msg, StkError::FUNCTION_SYNTAX); + } + channels = chans; strcpy(tempName,fileName); if (strstr(tempName,".raw") == NULL) strcat(tempName,".raw"); fd = fopen(tempName,"wb"); if (!fd) { - printf("Couldn't create soundfile %s !!!!!!!!\n",fileName); - exit(0); + sprintf(msg, "RawWvOut: Could not create soundfile: %s\n", tempName); + throw StkError(msg, StkError::FILE_ERROR); } - printf("\nCreating rawwave file %s\n\n", tempName); - - counter = 0; - totalCount = 0; -} - -RawWvOut :: RawWvOut(int chans, char *fileName) -{ - char tempName[128]; - - if (chans > 1) { - fprintf(stderr,"RawWvOut: Unsupported # of channels: %d\n", chans); - exit(0); - } - channels = chans; - strcpy(tempName,fileName); - strcat(tempName,".raw"); - fd = fopen(tempName,"wb"); - if (!fd) { - printf("Couldn't create soundfile %s !!!!!!!!\n",fileName); - exit(0); - } - printf("Creating soundfile %s.\n", tempName); - - counter = 0; - totalCount = 0; + printf("\nCreating soundfile: %s\n", tempName); + data_length = FILE_BUFFER_SIZE*channels; + data = (INT16 *) new INT16[data_length]; } RawWvOut :: ~RawWvOut() @@ -61,31 +42,21 @@ RawWvOut :: ~RawWvOut() fwrite(data,2,counter,fd); temp = (double) totalCount * ONE_OVER_SRATE; - printf("%f Seconds Computed\n",temp); + printf("%f Seconds Computed\n\n", temp); fclose(fd); } -long RawWvOut :: getCounter() -{ - return totalCount; -} - -MY_FLOAT RawWvOut :: getTime() -{ - return (MY_FLOAT) totalCount * ONE_OVER_SRATE; -} - void RawWvOut :: tick(MY_FLOAT sample) { data[counter] = (INT16) (sample * 32000.0); #ifdef __LITTLE_ENDIAN__ - data[counter] = SwapINT16 (data[counter]); + swap16 ((unsigned char *)&data[counter]); #endif counter++; totalCount++; - if (counter == RAW_BUFFER_SIZE) { - fwrite(data,2,RAW_BUFFER_SIZE,fd); + if (counter == data_length) { + fwrite(data,2,data_length,fd); counter = 0; } } @@ -94,13 +65,13 @@ void RawWvOut :: mtick(MY_MULTI samples) { data[counter] = (INT16) (*samples * 32000.0); #ifdef __LITTLE_ENDIAN__ - data[counter] = SwapINT16 (data[counter]); + swap16 ((unsigned char *)&data[counter]); #endif counter++; totalCount++; - if (counter == RAW_BUFFER_SIZE) { - fwrite(data,2,RAW_BUFFER_SIZE,fd); + if (counter == data_length) { + fwrite(data,2,data_length,fd); counter = 0; } } diff --git a/STK/ReedTabl.cpp b/src/ReedTabl.cpp similarity index 100% rename from STK/ReedTabl.cpp rename to src/ReedTabl.cpp diff --git a/STK/Reverb.cpp b/src/Reverb.cpp similarity index 100% rename from STK/Reverb.cpp rename to src/Reverb.cpp diff --git a/STK/Rhodey.cpp b/src/Rhodey.cpp similarity index 100% rename from STK/Rhodey.cpp rename to src/Rhodey.cpp diff --git a/src/RtAudio.cpp b/src/RtAudio.cpp new file mode 100644 index 0000000..d1012ad --- /dev/null +++ b/src/RtAudio.cpp @@ -0,0 +1,1810 @@ +/******************************************/ +/* + RtAudio.cpp + Realtime Sound I/O Object for STK + by Gary P. Scavone, 1998-2000. + + The sound output sections of this object + were originally based in part on code by + Doug Scott (SGI), Tim Stilson (Linux), + and R. Marsanyi (DirectSound). The latest + DirectSound code was re-written by Dave + Chisholm at CCRMA. + + This object provides a standard API + across all platforms for STK realtime + audio input/output. Multi-channel + support is supported when provided by + the soundcard. + + Only 16-bit integer input/output + routines are written for the moment + though it would be simple to overload + the methods for other data types. +*/ +/******************************************/ + +#include "RtAudio.h" + +#if (defined(__STK_REALTIME_) && defined(__OS_IRIX_)) + +#define NUM_FRAGMENTS 4 + +RtAudio :: RtAudio(int channels, MY_FLOAT srate, const char *mode, int device) +{ + ALconfig audio_port_config; + long queue_size; + ALpv pvs[2]; + char msg[256]; + + // initialize resources + audio_port_out = 0; + audio_port_in = 0; + + // check mode string + if (strcmp(mode,"play") && strcmp(mode,"record") && strcmp(mode,"duplex")) { + sprintf(msg, "RtAudio: constructor parameter 'mode' must be play, record, or duplex only.\n"); + throw StkError(msg, StkError::FUNCTION_SYNTAX); + } + + /* Create ALconfig structure */ + audio_port_config = alNewConfig(); + if (!audio_port_config) { + sprintf(msg,"RtAudio: Couldn't create SGI ALconfig: %s\n", + alGetErrorString(oserror())); + throw StkError(msg, StkError::SOUNDCARD_CONTROL); + } + + /* Configure channels */ + stk_chans = channels; + if(alSetChannels(audio_port_config, stk_chans) < 0) { + sprintf(msg,"RtAudio: SGI error configuring %d channels: %s\n", + channels, alGetErrorString(oserror())); + throw StkError(msg, StkError::SOUNDCARD_CAPS); + } + + /* Size the output queue */ + queue_size = RT_BUFFER_SIZE * NUM_FRAGMENTS; // in sample frames + if(alSetQueueSize(audio_port_config, queue_size) < 0) { + sprintf(msg,"RtAudio: SGI error configuring output queue size: %s\n", + alGetErrorString(oserror())); + throw StkError(msg, StkError::SOUNDCARD_CONTROL); + } + + if ( !strcmp(mode,"play") || !strcmp(mode,"duplex") ) { // playback only + + /* Open the output audio port */ + audio_port_out = alOpenPort("STK output port", "w", audio_port_config); + if(!audio_port_out) { + sprintf(msg,"RtAudio: SGI error ... cannot initialize output audio port: %s\n", + alGetErrorString(oserror())); + throw StkError(msg, StkError::SOUNDCARD_CONTROL); + } + + /* Set sample rate parameters */ + pvs[0].param = AL_MASTER_CLOCK; + pvs[0].value.i = AL_CRYSTAL_MCLK_TYPE; + pvs[1].param = AL_RATE; + pvs[1].value.ll = alDoubleToFixed((double)srate); + if (alSetParams(AL_DEFAULT_OUTPUT, pvs, 2) < 0) { /* set output SR */ + sprintf(msg,"RtAudio: SGI error ... cannot set sample rate parameters: %s\n", + alGetErrorString(oserror())); + throw StkError(msg, StkError::SOUNDCARD_CONTROL); + } + + /* Tell port to accept refill at buffers - 1 */ + alSetFillPoint(audio_port_out, RT_BUFFER_SIZE * (NUM_FRAGMENTS - 1)); + } + else if ( !strcmp(mode,"record") || !strcmp(mode,"duplex") ) { // record only + + /* Open the input audio port */ + audio_port_in = alOpenPort("STK input port", "r", audio_port_config); + if(!audio_port_in) { + sprintf(msg,"RtAudio: SGI error ... cannot initialize input audio port: %s\n", + alGetErrorString(oserror())); + throw StkError(msg, StkError::SOUNDCARD_CONTROL); + } + + /* Set sample rate parameters */ + pvs[0].param = AL_MASTER_CLOCK; + pvs[0].value.i = AL_CRYSTAL_MCLK_TYPE; + pvs[1].param = AL_RATE; + pvs[1].value.ll = alDoubleToFixed((double)srate); + if (alSetParams(AL_DEFAULT_INPUT, pvs, 2) < 0) { /* set input SR */ + sprintf(msg,"RtAudio: SGI error ... cannot set sample rate parameters: %s\n", + alGetErrorString(oserror())); + throw StkError(msg, StkError::SOUNDCARD_CONTROL); + } + + /* tell port to accept refill at buffers - 1 */ + alSetFillPoint(audio_port_in, 0); + } + + alFreeConfig(audio_port_config); + audio_port_config = 0; +} + +RtAudio :: ~RtAudio() +{ + if (audio_port_out) alClosePort(audio_port_out); + audio_port_out=0; + + if (audio_port_in) alClosePort(audio_port_in); + audio_port_in=0; +} + +int RtAudio :: playBuffer(INT16 *buf, int bufsize) +{ + alWriteFrames(audio_port_out, buf, bufsize/stk_chans); + return 0; +} + +int RtAudio :: recordBuffer(INT16 *buf, int bufsize) +{ + alReadFrames(audio_port_in, buf, bufsize/stk_chans); + return 0; +} + + +/* Linux ALSA Sound API here */ + +#elif (defined(__STK_REALTIME_) && defined(__ALSA_API_)) + +RtAudio :: RtAudio(int channels, MY_FLOAT srate, const char *mode, int device) +{ + int card, dev, err, nChoices = 0; + int data_format, default_card; + unsigned int mask; + snd_pcm_channel_params_t params; + struct snd_ctl_hw_info info; + snd_pcm_info_t pcminfo; + snd_pcm_channel_info_t chninfo; + snd_pcm_channel_setup_t setup; + snd_ctl_t *chandle; + bool print_list = FALSE; + char msg[256]; + + // check mode string + if (strcmp(mode,"play") && strcmp(mode,"record") && strcmp(mode,"duplex")) { + sprintf(msg, "RtAudio: constructor parameter 'mode' must be play, record, or duplex only.\n"); + throw StkError(msg, StkError::FUNCTION_SYNTAX); + } + + if (channels < 1) { + sprintf(msg, "RtAudio: number of channels = %d not supported!\n", channels); + throw StkError(msg, StkError::FUNCTION_SYNTAX); + } + + // check to make sure we have card(s) and/or ALSA drivers available + mask = snd_cards_mask(); + if (!mask) { + sprintf(msg, "RtAudio: no ALSA soundcards reported available.\n"); + throw StkError(msg, StkError::SOUNDCARD_NOT_FOUND); + } + + ohandle = 0; + ihandle = 0; + outbuf = 0; + inbuf = 0; + + if (!strcmp(mode, "play")) + direction = SND_PCM_INFO_PLAYBACK; + else if (!strcmp(mode, "record")) + direction = SND_PCM_INFO_CAPTURE; + else + direction = SND_PCM_INFO_DUPLEX; + + // The proliferation of multichannel soundcards carries with it a wide range + // of special requirements. Often, a card will need to be fed a special data + // or channel format. So, we need to probe the available card(s) to determine + // these requirements. If no device is specified as a constructor argument, + // I'll start probing at the default card number (which can be set with the + // ALSA_CARD environment variable) and then any other existing cards until I + // find a device that will meet our needs (or not). If a specified device + // does not exist or will not work, I'll print a list of available audio + // devices and let the user select one. + if (device == -1) { + default_card = snd_defaults_pcm_card(); + } + else { // check device specified as argument + if (!(mask & (1<= channels) && (chninfo.min_rate <= (int)srate) + && (chninfo.max_rate >= (int)srate)) { // this card will work + dev_ochans = (channels >= chninfo.min_voices) ? channels : chninfo.min_voices; + if (direction == SND_PCM_INFO_PLAYBACK) { + // playback only ... jump out of loop and proceed + // duplex case continue to capture check + if (print_list) { + printf("Audio Card %d, Device %d: %s\n", card, dev, info.name); + nChoices++; + snd_pcm_close(ohandle); + continue; + } + goto have_good_device; + } + } else { // this device won't work + snd_pcm_close(ohandle); + continue; + } + } + if ( (direction == SND_PCM_INFO_CAPTURE) || + (direction == SND_PCM_INFO_DUPLEX) ) { + if ((err=snd_pcm_open(&ihandle, card, dev, SND_PCM_OPEN_CAPTURE))!=0) { + fprintf(stderr,"RtAudio: ALSA PCM capture open error (%d): %s\n", + card, snd_strerror(err)); + if (direction == SND_PCM_INFO_DUPLEX) + snd_pcm_close(ohandle); + continue; + } + // we have a device open ... get the channel information (direction specific) + memset(&chninfo, 0, sizeof(chninfo)); + chninfo.channel = SND_PCM_CHANNEL_CAPTURE; + if ((err = snd_pcm_channel_info(ihandle, &chninfo)) < 0) { + fprintf(stderr,"RtAudio: ALSA error on PCM capture info (%d): %s\n", + card, snd_strerror(err)); + snd_pcm_close(ihandle); + if (direction == SND_PCM_INFO_DUPLEX) + snd_pcm_close(ohandle); + continue; + } + // check number of channels and sample rate + if ((chninfo.max_voices >= channels) && (chninfo.min_rate <= (int)srate) + && (chninfo.max_rate >= (int)srate)) { // this card will work + dev_ichans = (channels >= chninfo.min_voices) ? channels : chninfo.min_voices; + if (print_list) { + printf("Audio Card %d, Device %d: %s\n", card, dev, info.name); + nChoices++; + snd_pcm_close(ihandle); + if (direction == SND_PCM_INFO_DUPLEX) + snd_pcm_close(ohandle); + continue; + } + goto have_good_device; // jump out of loop and proceed + } else { // this device won't work + snd_pcm_close(ihandle); + if (direction == SND_PCM_INFO_DUPLEX) + snd_pcm_close(ohandle); + } + } + } + } + } + if (default_card == 0) card++; + else { // default card != 0, now start with card 0 and keep searching + if (card == default_card) card = 0; // first time only + else { + card++; + if (card == default_card) card++; // skip over default card + } + } + } + + if (print_list && nChoices) { + char choice[16]; + printf("\nType an audio card number from above: "); + fgets(choice, 16, stdin); + card = atoi(choice); + printf("Select a device for the same card: "); + fgets(choice, 16, stdin); + printf("\n"); + dev = atoi(choice); + // re-open the device(s) + if ( (direction == SND_PCM_INFO_PLAYBACK) || + (direction == SND_PCM_INFO_DUPLEX) ) { + if ((err=snd_pcm_open(&ohandle, card, dev, SND_PCM_OPEN_PLAYBACK))!=0) { + sprintf(msg, "RtAudio: ALSA PCM playback open error (%d:%d): %s\n", + card, dev, snd_strerror(err)); + throw StkError(msg, StkError::SOUNDCARD_CAPS); + } + } + if ( (direction == SND_PCM_INFO_CAPTURE) || + (direction == SND_PCM_INFO_DUPLEX) ) { + if ((err=snd_pcm_open(&ihandle, card, dev, SND_PCM_OPEN_CAPTURE))!=0) { + sprintf(msg, "RtAudio: ALSA PCM capture open error (%d:%d): %s\n", + card, dev, snd_strerror(err)); + if (direction == SND_PCM_INFO_DUPLEX) + snd_pcm_close(ohandle); + throw StkError(msg, StkError::SOUNDCARD_CAPS); + } + } + goto have_good_device; + } + + // if we got here, no devices were found to meet the requested functionality + sprintf(msg, "RtAudio: no ALSA device found for requested service!\n"); + throw StkError(msg, StkError::SOUNDCARD_CAPS); + + have_good_device: // the current value of card and dev are what we will use + + // The hardware sometimes requires more channels of data than we necessarily + // want to work with in STK. In fact, sometimes the hardware requires a + // different number of output channels than input channels. Thus, we need to + // remember all values. + stk_chans = channels; + + // If duplex mode, the format will come from the capture device info. I'm assuming + // that both directions will have the same data format. + if (chninfo.formats & SND_PCM_FMT_S16_LE) { + data_format = SND_PCM_SFMT_S16_LE; + bytes_per_sample = 2; + } + else if (chninfo.formats & SND_PCM_FMT_S32_LE) { + data_format = SND_PCM_SFMT_S32_LE; + bytes_per_sample = 4; + } + else { + sprintf(msg, "RtAudio: only ALSA S16_LE and S32_LE data formats at the moment!\n"); + throw StkError(msg); + } + + // global channel parameters (not direction specific) + memset(¶ms, 0, sizeof(params)); + params.mode=SND_PCM_MODE_BLOCK; + params.stop_mode=SND_PCM_STOP_ROLLOVER; + params.buf.block.frags_max=3; + params.buf.block.frags_min=1; + params.format.interleave=1; + params.format.format=data_format; // this should depend on the card, unless we use the plugin + params.format.rate=(int)srate; + + // We need to set the channel parameters, flush, and prepare for each direction of use. + // Thus, if doing duplex, we need to do these for both directions. First do it for + // playback and duplex. + if ((direction == SND_PCM_INFO_PLAYBACK) || (direction == SND_PCM_INFO_DUPLEX)) { + params.channel=SND_PCM_CHANNEL_PLAYBACK; + params.start_mode=SND_PCM_START_FULL; + params.format.voices=dev_ochans; + // The fragsize is in bytes per frame = RT_BUFFER_SIZE * dev_chans * bytes_per_sample. + // ALSA requires that all reads and write be done in fragsize increments. + ofragsize = (int) (dev_ochans * bytes_per_sample * RT_BUFFER_SIZE); + params.buf.block.frag_size=ofragsize; + if ((err=snd_pcm_channel_params(ohandle, ¶ms))!=0) { + // try to close what was opened! + snd_pcm_close(ohandle); + sprintf(msg, "RtAudio: Cannot set ALSA audio device parameters for playback: %s\n", + snd_strerror(err)); + throw StkError(msg, StkError::SOUNDCARD_CONTROL); + } + + // now check the actual values, because sometimes they are not what we requested + memset(&setup, 0, sizeof(setup)); + setup.channel=SND_PCM_CHANNEL_PLAYBACK; + if ((err=snd_pcm_channel_setup(ohandle, &setup))<0) { + snd_pcm_close(ohandle); + sprintf(msg, "RtAudio: Cannot get ALSA audio device setup info: %s\n", + snd_strerror(err)); + throw StkError(msg, StkError::SOUNDCARD_CONTROL); + } else { + if (setup.format.rate != (int) srate) { + // try to close what was opened! + snd_pcm_close(ohandle); + sprintf(msg, "RtAudio: Soundcard doesn't seem to support requested sample rate: %.2f!\n", + srate); + throw StkError(msg, StkError::SOUNDCARD_CAPS); + } + if (setup.buf.block.frag_size != ofragsize) ofragsize = setup.buf.block.frag_size; + } + + // allocate and clear the output buffer + outbuf = (unsigned char*) new char[ofragsize]; + memset(outbuf, 0, ofragsize); + + // I'm not sure what this does and I'm not sure it actually helps. + if ((err=snd_pcm_playback_flush(ohandle))!=0) { + // try to free and close what was opened! + snd_pcm_close(ohandle); + if (outbuf) delete [] outbuf; + sprintf(msg, "RtAudio: Cannot flush ALSA channel buffers for playback!\n"); + throw StkError(msg, StkError::SOUNDCARD_CONTROL); + } + + if ((err=snd_pcm_channel_prepare(ohandle, params.channel))!=0) { + // try to close what was opened! + snd_pcm_close(ohandle); + if (outbuf) delete [] outbuf; + sprintf(msg, "RtAudio: Cannot prepare ALSA channel for playback!\n"); + throw StkError(msg, StkError::SOUNDCARD_CONTROL); + } + } + + // Now do it for capture and duplex. + if ((direction == SND_PCM_INFO_CAPTURE) || (direction == SND_PCM_INFO_DUPLEX)) { + params.channel=SND_PCM_CHANNEL_CAPTURE; + params.start_mode=SND_PCM_START_DATA; + params.format.voices=dev_ichans; + // The fragsize is in bytes per frame = RT_BUFFER_SIZE * dev_chans * bytes_per_sample. + // ALSA requires that all reads and write be done in fragsize increments. + ifragsize = (int) (dev_ichans * bytes_per_sample * RT_BUFFER_SIZE); + params.buf.block.frag_size=ifragsize; + if ((err=snd_pcm_channel_params(ihandle, ¶ms))!=0) { + // try to close what was opened! + snd_pcm_close(ihandle); + if (direction == SND_PCM_INFO_DUPLEX) { + if (outbuf) delete [] outbuf; + snd_pcm_close(ohandle); + } + sprintf(msg, "RtAudio: Cannot set ALSA audio device parameters for capture: %s\n", + snd_strerror(err)); + throw StkError(msg, StkError::SOUNDCARD_CONTROL); + } + + // now check the actual values, because sometimes they are not what we requested + memset(&setup, 0, sizeof(setup)); + setup.channel=SND_PCM_CHANNEL_CAPTURE; + if ((err=snd_pcm_channel_setup(ihandle, &setup))<0) { + // try to close what was opened! + snd_pcm_close(ihandle); + if (direction == SND_PCM_INFO_DUPLEX) { + if (outbuf) delete [] outbuf; + snd_pcm_close(ohandle); + } + sprintf(msg, "RtAudio: Cannot get ALSA audio device setup info: %s\n", + snd_strerror(err)); + throw StkError(msg, StkError::SOUNDCARD_CONTROL); + } else { + if (setup.format.rate != (int) srate) { + // try to close what was opened! + snd_pcm_close(ihandle); + if (direction == SND_PCM_INFO_DUPLEX) { + if (outbuf) delete [] outbuf; + snd_pcm_close(ohandle); + } + sprintf(msg, "RtAudio: Soundcard doesn't seem to support requested sample rate: %.2f!\n", + srate); + throw StkError(msg, StkError::SOUNDCARD_CAPS); + } + + if (setup.buf.block.frag_size != ifragsize) ifragsize = setup.buf.block.frag_size; + } + + // allocate and clear the input buffer + inbuf = (unsigned char*) new char[ifragsize]; + memset(inbuf, 0, ifragsize); + + if ((err=snd_pcm_capture_flush(ihandle))!=0) { + // try to close what was opened! + snd_pcm_close(ihandle); + if (inbuf) delete [] inbuf; + if (direction == SND_PCM_INFO_DUPLEX) { + if (outbuf) delete [] outbuf; + snd_pcm_close(ohandle); + } + sprintf(msg, "RtAudio: Cannot flush ALSA channel buffers for capture!\n"); + throw StkError(msg, StkError::SOUNDCARD_CONTROL); + } + + if ((err=snd_pcm_channel_prepare(ihandle, params.channel))!=0) { + // try to close what was opened! + snd_pcm_close(ihandle); + if (inbuf) delete [] inbuf; + if (direction == SND_PCM_INFO_DUPLEX) { + if (outbuf) delete [] outbuf; + snd_pcm_close(ohandle); + } + sprintf(msg, "RtAudio: Cannot prepare ALSA channel for capture!\n"); + throw StkError(msg, StkError::SOUNDCARD_CONTROL); + } + } +} + +RtAudio :: ~RtAudio() +{ + if ((direction == SND_PCM_INFO_PLAYBACK) || (direction == SND_PCM_INFO_DUPLEX)) { + snd_pcm_playback_drain(ohandle); + snd_pcm_close(ohandle); + } + if ((direction == SND_PCM_INFO_CAPTURE) || (direction == SND_PCM_INFO_DUPLEX)) { + snd_pcm_close(ihandle); + } + if (outbuf) delete [] outbuf; + if (inbuf) delete [] inbuf; +} + +int RtAudio :: playBuffer(INT16 *buf, int bufsize) +{ + // The argument bufsize is the number of audio samples (INT16s) in buf. + int err, i; + static char msg[256]; + unsigned char *temp; + static int channel = 1; + static int counter = 0; + static int extra_chans = dev_ochans - stk_chans; + + // performance optimization occurs when the following conditions are met + if ((extra_chans == 0) && (bytes_per_sample == 2) && (bufsize * 2 == ofragsize)) { + // we don't need to use outbuf + if ((err=snd_pcm_write(ohandle, buf, ofragsize))!=ofragsize) { + sprintf(msg, "RtAudio: ALSA audio write error!\n"); + throw StkError(msg, StkError::SOUNDCARD_CONTROL); + } + } else { + for (i=0; i stk_chans) { + // because we created outbuf with calloc(), we shouldn't have to write zeros here + counter += bytes_per_sample * extra_chans; + channel = 1; + } + + if (counter >= ofragsize) { + if ((err=snd_pcm_write(ohandle, outbuf, ofragsize))!=ofragsize) { + sprintf(msg, "RtAudio: ALSA audio write error!\n"); + throw StkError(msg, StkError::SOUNDCARD_CONTROL); + } + counter = 0; + } + } + } + + return 0; +} + +int RtAudio :: recordBuffer(INT16 *buf, int bufsize) +{ + // The argument bufsize is the number of audio samples (INT16s) in buf. + int err, i; + static char msg[256]; + unsigned char *temp; + static int channel = 1; + static int counter = 0; + static int extra_chans = dev_ichans - stk_chans; + + // performance optimization occurs when the following conditions are met + if ((extra_chans == 0) && (bytes_per_sample == 2) && (bufsize * 2 == ifragsize)) { + // we don't need to use inbuf + if ((err=snd_pcm_read(ihandle, buf, ifragsize))!=ifragsize) { + sprintf(msg, "RtAudio: ALSA audio read error!\n"); + throw StkError(msg, StkError::SOUNDCARD_CONTROL); + } + } else { + for (i=0; i stk_chans) { + // just skip over the extra channels + counter += bytes_per_sample * extra_chans; + channel = 1; + } + if (counter >= ifragsize) counter = 0; + } + } + + return 0; +} + + +/* Linux OSS Sound API here */ + +#elif (defined(__STK_REALTIME_) && defined(__OSS_API_)) + +// Define the maximum number of dsp devices that we'll attempt +// to probe before giving up. +#define MAX_DSP_DEVS 8 +#define DAC_NAME "/dev/dsp" +// The number of fragments can be made larger than 2 if the sound +// system performance is poor. +#define NUM_FRAGMENTS 4 + +RtAudio :: RtAudio(int channels, MY_FLOAT srate, const char *mode, int device) +{ + char device_name[16]; + int fragsize; + int fragment_size_log; + int format; + int chans = channels; + int speed; + int i, nChoices = 0; + bool print_list = FALSE; + char msg[256]; + + // check mode string + if (strcmp(mode,"play") && strcmp(mode,"record") && strcmp(mode,"duplex")) { + sprintf(msg, "RtAudio: constructor parameter 'mode' must be play, record, or duplex only.\n"); + throw StkError(msg, StkError::FUNCTION_SYNTAX); + } + + if (channels < 1) { + sprintf(msg, "RtAudio: number of channels = %d not supported!\n", channels); + throw StkError(msg, StkError::FUNCTION_SYNTAX); + } + + fragsize = RT_BUFFER_SIZE * channels * 2; // in bytes + fragment_size_log = (int)(log10((double)fragsize)/log10(2.0)); + long temp = ((long) NUM_FRAGMENTS << 16) + fragment_size_log; + + // /dev/dsp should be a link to the default pcm device under OSS + strcpy(device_name, DAC_NAME); + + // The OSS API doesn't really give us a means for probing the + // capabilities of devices. Thus, we'll just pursue a brute + // force method of opening devices until we either find something + // that doesn't complain or we have to give up. We'll start with + // the default device, then try /dev/dsp0, /dev/dsp1, etc... + + if (device != -1) { + // start with device specified as argument + sprintf(device_name, "%s%d", DAC_NAME, device); + } + + for (i=0; i<=MAX_DSP_DEVS; i++) { + + // if the default device doesn't work, try some others + if (i > 0) sprintf(device_name, "%s%d", DAC_NAME, i-1); + + if (device != -1 && i == 1) { + // the specified device didn't work ... now print other options + print_list = TRUE; + printf("\n"); + } + + if (!strcmp(mode,"play")) { // playback only + if ((audio_fd = open(device_name, O_WRONLY, 0)) == -1) { + // Open device failed ... either busy or doesn't exist + if (errno == EBUSY) + fprintf(stderr,"RtAudio: OSS PCM playback device (%s) is busy and cannot be opened.\n", + device_name); + continue; + } + } + else if (!strcmp(mode,"record")) { // record only + if ((audio_fd = open(device_name, O_RDONLY, 0)) == -1) { + // Open device failed ... either busy or doesn't exist + if (errno == EBUSY) + fprintf(stderr,"RtAudio: OSS PCM record device (%s) is busy and cannot be opened.\n", + device_name); + continue; + } + } + else if (!strcmp(mode,"duplex")) { // duplex mode + if ((audio_fd = open(device_name, O_RDWR, 0)) == -1) { + // Open device failed ... either busy or doesn't exist + if (errno == EBUSY) + fprintf(stderr,"RtAudio: OSS PCM device (%s) is busy and cannot be opened for duplex operation.\n", + device_name); + continue; + } + int caps; + if (ioctl(audio_fd, SNDCTL_DSP_GETCAPS, &caps)) { + close(audio_fd); + fprintf(stderr,"RtAudio: OSS error getting device (%s) capabilities for duplex operation.\n", + device_name); + continue; + } + if (!(caps & DSP_CAP_DUPLEX)) { + close(audio_fd); + fprintf(stderr,"RtAudio: OSS reports device (%s) does not support duplex operation.\n", + device_name); + continue; + } + if (ioctl(audio_fd, SNDCTL_DSP_SETDUPLEX, 0)) { + close(audio_fd); + fprintf(stderr,"RtAudio: OSS error setting device (%s) for duplex operation.\n", + device_name); + continue; + } + } + + // Setup the number and size of the fragments + if (ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &temp)) { + close(audio_fd); + fprintf(stderr,"RtAudio: OSS error setting fragment size for device (%s).\n", + device_name); + continue; + } + + // Setup the data format ... we're only supporting 16-bit little-endian data for now + format = AFMT_S16_LE; + if (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &format) == -1) { + close(audio_fd); + fprintf(stderr,"RtAudio: OSS error setting data format for device (%s).\n", + device_name); + continue; + } + + // Check the see whether the device supports the requested format + if (format != AFMT_S16_LE) { + close(audio_fd); + fprintf(stderr,"RtAudio: OSS error ... audio device (%s) doesn't support 16-bit signed LE format.\n", + device_name); + continue; + } + + // Setup the number of channels + if (ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &chans) == -1) { + close(audio_fd); + fprintf(stderr,"RtAudio: OSS error setting %d channels on device (%s).\n", + channels, device_name); + continue; + } + + // Check to see whether the device supports the requested number of channels + if (chans != channels ) { + close(audio_fd); + fprintf(stderr,"RtAudio: OSS error ... audio device (%s) doesn't support %d channels.\n", + device_name, channels); + continue; + } + + // Setup the sampling rate + speed = (int) srate; + if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &speed)==-1) { + close(audio_fd); + fprintf(stderr,"RtAudio: OSS error setting sample rate = %f on device (%s).\n", + srate, device_name); + continue; + } + + // Check to see whether the device supports the requested sample rate + if (abs(speed - (int)srate) > 100) { + close(audio_fd); + fprintf(stderr,"RtAudio: OSS error ... audio device (%s) doesn't support sample rate of %f.\n", + device_name, srate); + continue; + } + + if (print_list) { + close(audio_fd); + printf("Audio Device %d: %s\n", i-1, device_name); + nChoices++; + continue; + } + + // If we got here, we found a device that meets our needs. Return to the caller. + return; + } + + // If we got here and print_list = TRUE, then we need to ask the user to specify + // a device from the printed list. Then we have to go through the whole process + // of opening and checking the device capabilities again, as we did above. We + // can't assume the user always types a valid device number. We can thank OSS + // for the kludgy-ness of this whole process. + if (print_list && nChoices ) { + char choice[16]; + printf("\nType an audio device number from above: "); + fgets(choice, 16, stdin); + i = atoi(choice); + printf("\n"); + sprintf(device_name, "%s%d", DAC_NAME, i); + + // Now redo the above with the specified card. + if (!strcmp(mode,"play")) { // playback only + if ((audio_fd = open(device_name, O_WRONLY, 0)) == -1) { + // Open device failed ... either busy or doesn't exist + sprintf(msg, "RtAudio: OSS PCM playback device (%s) cannot be opened.\n", + device_name); + throw StkError(msg, StkError::SOUNDCARD_CONTROL); + } + } + else if (!strcmp(mode,"record")) { // record only + if ((audio_fd = open(device_name, O_RDONLY, 0)) == -1) { + // Open device failed ... either busy or doesn't exist + sprintf(msg, "RtAudio: OSS PCM record device (%s) cannot be opened.\n", + device_name); + throw StkError(msg, StkError::SOUNDCARD_CONTROL); + } + } + else if (!strcmp(mode,"duplex")) { // duplex mode + if ((audio_fd = open(device_name, O_RDWR, 0)) == -1) { + // Open device failed ... either busy or doesn't exist + sprintf(msg, "RtAudio: OSS PCM device (%s) cannot be opened for duplex operation.\n", + device_name); + throw StkError(msg, StkError::SOUNDCARD_CONTROL); + } + int caps; + if (ioctl(audio_fd, SNDCTL_DSP_GETCAPS, &caps)) { + close(audio_fd); + sprintf(msg, "RtAudio: OSS error getting device (%s) capabilities for duplex operation.\n", + device_name); + throw StkError(msg, StkError::SOUNDCARD_CAPS); + } + if (!(caps & DSP_CAP_DUPLEX)) { + close(audio_fd); + sprintf(msg, "RtAudio: OSS reports device (%s) does not support duplex operation.\n", + device_name); + throw StkError(msg, StkError::SOUNDCARD_CAPS); + } + if (ioctl(audio_fd, SNDCTL_DSP_SETDUPLEX, 0)) { + close(audio_fd); + sprintf(msg, "RtAudio: OSS error setting device (%s) for duplex operation.\n", + device_name); + throw StkError(msg, StkError::SOUNDCARD_CONTROL); + } + } + + // Setup the number and size of the fragments + if (ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &temp)) { + close(audio_fd); + sprintf(msg, "RtAudio: OSS error setting fragment size for device (%s).\n", + device_name); + throw StkError(msg, StkError::SOUNDCARD_CONTROL); + } + + // Setup the data format ... we're only supporting 16-bit little-endian data for now + format = AFMT_S16_LE; + if (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &format) == -1) { + close(audio_fd); + sprintf(msg,"RtAudio: OSS error setting data format for device (%s).\n", + device_name); + throw StkError(msg, StkError::SOUNDCARD_CONTROL); + } + + // Check the see whether the device supports the requested format + if (format != AFMT_S16_LE) { + close(audio_fd); + sprintf(msg,"RtAudio: OSS error ... audio device (%s) doesn't support 16-bit signed LE format.\n", + device_name); + throw StkError(msg, StkError::SOUNDCARD_CAPS); + } + + // Setup the number of channels + if (ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &chans) == -1) { + close(audio_fd); + sprintf(msg, "RtAudio: OSS error setting %d channels on device (%s).\n", + channels, device_name); + throw StkError(msg, StkError::SOUNDCARD_CONTROL); + } + + // Check to see whether the device supports the requested number of channels + if (chans != channels ) { + close(audio_fd); + sprintf(msg, "RtAudio: OSS error ... audio device (%s) doesn't support %d channels.\n", + device_name, channels); + throw StkError(msg, StkError::SOUNDCARD_CAPS); + } + + // Setup the sampling rate + speed = (int) srate; + if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &speed)==-1) { + close(audio_fd); + sprintf(msg, "RtAudio: OSS error setting sample rate = %f on device (%s).\n", + srate, device_name); + throw StkError(msg, StkError::SOUNDCARD_CONTROL); + } + + // Check to see whether the device supports the requested sample rate + if (abs(speed - (int)srate) > 100) { + close(audio_fd); + sprintf(msg,"RtAudio: OSS error ... audio device (%s) doesn't support sample rate of %f.\n", + device_name, srate); + throw StkError(msg, StkError::SOUNDCARD_CAPS); + } + + // If we got here, the specified device works ... return to the caller. + return; + } + + // If we got here, no device was found to meet the requested functionality + sprintf(msg, "RtAudio: No OSS device found for requested service!\n"); + throw StkError(msg, StkError::SOUNDCARD_CAPS); +} + +RtAudio :: ~RtAudio() +{ + if (audio_fd) close(audio_fd); + audio_fd=0; +} + +int RtAudio :: playBuffer(INT16 *buf, int bufsize) +{ + // The argument bufsize is the number of audio samples (INT16s) in buf. + // The OSS write() routine takes its buffer size in bytes, thus the + // multiplication by two. While it is not necessary to call this function + // with fragsize buffers (which should equal RT_BUFFER_SIZE * channels * 2), + // its behavior is apparently optimized for such. + static char msg[256]; + + if (write(audio_fd, buf, 2*bufsize) == -1) { + sprintf(msg, "RtAudio: OSS audio write error!\n"); + throw StkError(msg, StkError::SOUNDCARD_CONTROL); + } + return 0; +} + +int RtAudio :: recordBuffer(INT16 *buf, int bufsize) +{ + // The argument bufsize is the number of audio samples (INT16s) in buf. + // The OSS read() routine takes its buffer size in bytes, thus the + // multiplication by two. While it is not necessary to call this function + // with fragsize buffers (which should equal RT_BUFFER_SIZE * channels * 2), + // its behavior is apparently optimized for such. + static char msg[256]; + + if (read(audio_fd, buf, 2*bufsize) == -1) { + sprintf(msg, "RtAudio: OSS audio read error!\n"); + throw StkError(msg, StkError::SOUNDCARD_CONTROL); + } + return 0; +} + + +#elif (defined(__STK_REALTIME_) && defined(__OS_Win_) ) +/* + WINDOZE: + + If anyone needed substantiation as to why Microsoft doesn't deserve + to exist, just read through the following code and compare it to + any of the other supported APIs in this file. Dave, thanks for + your hard work to get things running better ... it is appreciated. + But personally, I'm disgusted with Microsoft and their pure + incompetence (GPS, 10/2000). + + AUDIO OUTPUT: + + There are several ways to go about handling sound output + under DirectSound. We choose to always write new buffers of + data behind the read pointer of the DS play buffer. This is + safe (compared to trying to lead the pointer) but inherently + produces a delay equivalent to the entire sound buffer (plus + any other delays that Windows provides). Our default parameters + cause an inherent delay of about 30 ms b/c of this. To change + this, adjust the NUM_FRAGMENTS definition in RtAudio.h + + AUDIO INPUT: + + We chose to use a complex but stable scheme of keeping our own internal + buffer separate from the DS input buffer. This take up more CPU time + but is safer than using the Sleep() function for critical parts of + code. Users are then given copies of this data (or pointers into our + actual internal buffer, if they use the overloaded version of + recordBuffer(INT16**) A separate thread (under control of the WinMM + timer) takes care of transfering data from the DS buffer to our own buffer. + You can expect a total delay of about 100 - 150 ms for fully duplexed + audio - it seems impossible to get directx to perform any better than this. + + In addition, the windows version has stopPlay, startPlay, startRecord + and stopRecord methods b/c DirectX does not automatically stop I/O if + no fresh data is sent. + + The DirectSoundCapture API is only available with DirectX versions + 5.0 and higher. + */ + +RtAudio :: RtAudio(int channels, MY_FLOAT srate, const char *mode, int device) +{ + HRESULT result; + BYTE* audioPtr; + DWORD dataLen; + HWND hWnd = GetForegroundWindow(); + WAVEFORMATEX waveFormat; + LPGUID directSoundGuid = NULL; + int i, devNum = 0; + + // Initialize the DirectSound object and buffer pointers to NULL + directSoundObject = NULL; + directSoundBuffer = NULL; + directSoundCaptureObject = NULL; + directSoundCaptureBuffer = NULL; + inputBuffer = NULL; + + // Some basic initialization stuff + sampleRate = srate; + nextRecordRead = 0; + nextRecordWrite = 0; + internalError = false; + playing = false; + recording = false; + numDevices = 0; + nextWritePos = 0; + + // Define the wave format structure (16-bit PCM, srate, channels) + ZeroMemory(&waveFormat, sizeof(WAVEFORMATEX)); + waveFormat.wFormatTag = WAVE_FORMAT_PCM; + waveFormat.nChannels = channels; + waveFormat.nSamplesPerSec = (unsigned long) srate; + waveFormat.wBitsPerSample = 16; + waveFormat.nBlockAlign = waveFormat.nChannels * waveFormat.wBitsPerSample / 8; + waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign; + + // check mode string + if (strcmp(mode,"play") && strcmp(mode,"record") && strcmp(mode,"duplex")) { + sprintf(errormsg, "RtAudio: constructor parameter 'mode' must be play, record, or duplex only.\n"); + throw StkError(errormsg, StkError::FUNCTION_SYNTAX); + } + + if (channels < 1) { + sprintf(errormsg, "RtAudio: number of channels = %d not supported!\n", channels); + throw StkError(errormsg, StkError::FUNCTION_SYNTAX); + } + + // PLAYBACK INITIALIZATION + if ( (!strcmp(mode,"play")) || (!strcmp(mode,"duplex")) ) { + + DSBUFFERDESC directSoundBufferDescription; + + if (device == -1) { + // use default device + if (FAILED(result = DirectSoundCreate(NULL, &directSoundObject, NULL))) { + sprintf(errormsg,"RtAudio: Unable to create default direct sound object: %s\n", getErrorMessage(result)); + throw StkError(errormsg,StkError::SOUNDCARD_NOT_FOUND); + } + goto have_good_output_device; + } else { + // Enumerate through the devices, trying the user specified device first. + // If that fails, prompt for action. + if (FAILED(result = DirectSoundEnumerate((LPDSENUMCALLBACK)SoundDeviceEnumCallback, this))) { + sprintf(errormsg,"RtAudio: Unable to enumerate through sound devices: %s\n", getErrorMessage(result)); + throw StkError(errormsg,StkError::SOUNDCARD_NOT_FOUND); + } + if (device >=0 && device < numDevices) { + // try user specified device if within bounds + directSoundGuid = devices[device].guid; + result = DirectSoundCreate(directSoundGuid, &directSoundObject, NULL); + if (result == DS_OK) goto have_good_output_device; + } + } + + printf("\n"); + for (i=0; i=0 && devNum < numDevices) { + directSoundGuid = devices[devNum].guid; + if (FAILED(result = DirectSoundCreate(directSoundGuid, &directSoundObject, NULL))) { + sprintf(errormsg,"RtAudio: Unable to create direct sound object: %s\n", getErrorMessage(result)); + throw StkError(errormsg,StkError::SOUNDCARD_CAPS); + } + } else { + throw StkError("RtAudio: Invalid device number specified!",StkError::SOUNDCARD_NOT_FOUND); + } + + have_good_output_device: + + // Set cooperative level + if (FAILED(result = directSoundObject->SetCooperativeLevel(hWnd, DSSCL_PRIORITY))) { + sprintf(errormsg,"RtAudio: Unable to set cooperative level: %s\n", getErrorMessage(result)); + throw StkError(errormsg,StkError::SOUNDCARD_CONTROL); + } + + // Get DS device capabilites + DSCAPS directSoundCapabilities; + ZeroMemory(&directSoundCapabilities, sizeof(DSCAPS)); + directSoundCapabilities.dwSize = sizeof(DSCAPS); + if (FAILED(result = directSoundObject->GetCaps(&directSoundCapabilities))) { + sprintf(errormsg,"RtAudio: Unable to get DS capabilities: %s\n", getErrorMessage(result)); + throw StkError(errormsg,StkError::SOUNDCARD_CAPS); + } + + /* Even though we will write to the secondary buffer, we need + to access the primary buffer to set the correct output format. + The default is 8-bit, 22 kHz! + */ + LPDIRECTSOUNDBUFFER directSoundPrimaryBuffer; + // Setup the DS primary buffer description. + ZeroMemory(&directSoundBufferDescription, sizeof(DSBUFFERDESC)); + directSoundBufferDescription.dwSize = sizeof(DSBUFFERDESC); + directSoundBufferDescription.dwFlags = DSBCAPS_PRIMARYBUFFER; + // Obtain the primary buffer + if (FAILED(result = directSoundObject->CreateSoundBuffer(&directSoundBufferDescription, + &directSoundPrimaryBuffer, NULL))) { + sprintf(errormsg,"RtAudio: Unable to access DS primary buffer: %s\n", getErrorMessage(result)); + throw StkError(errormsg,StkError::SOUNDCARD_CONTROL); + } + + // Set the primary DS buffer sound format. + if (FAILED(result = directSoundPrimaryBuffer->SetFormat(&waveFormat))) { + sprintf(errormsg,"RtAudio: Unable to set DS primary buffer format: %s\n", getErrorMessage(result)); + throw StkError(errormsg,StkError::SOUNDCARD_CONTROL); + } + + // Setup the secondary DS buffer description. Try to do it in hardware + directSoundBufferSize = channels * RT_BUFFER_SIZE * NUM_FRAGMENTS * sizeof(INT16); + ZeroMemory(&directSoundBufferDescription, sizeof(DSBUFFERDESC)); + directSoundBufferDescription.dwSize = sizeof(DSBUFFERDESC); + directSoundBufferDescription.dwFlags = DSBCAPS_STICKYFOCUS | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_LOCHARDWARE; + directSoundBufferDescription.dwBufferBytes = directSoundBufferSize; + directSoundBufferDescription.lpwfxFormat = &waveFormat; + + // Try to create the secondary DS buffer. If that doesn't work, try for + // software - if that doesn't work, throw an exception. + if (FAILED(result = directSoundObject->CreateSoundBuffer(&directSoundBufferDescription, &directSoundBuffer, NULL))) { + directSoundBufferDescription.dwFlags = DSBCAPS_STICKYFOCUS | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_LOCSOFTWARE; + if (FAILED(result = directSoundObject->CreateSoundBuffer(&directSoundBufferDescription, &directSoundBuffer, NULL))) { + sprintf(errormsg,"RtAudio: Unable to create secondary DS buffer: %s\n", getErrorMessage(result)); + throw StkError(errormsg,StkError::SOUNDCARD_CONTROL); + } + } + + // Get the buffer size + DSBCAPS dsbcaps; + dsbcaps.dwSize = sizeof(DSBCAPS); + directSoundBuffer->GetCaps(&dsbcaps); + directSoundBufferSize = dsbcaps.dwBufferBytes; + + // Lock the DS buffer + if (FAILED(result = directSoundBuffer->Lock(0, directSoundBufferSize, (LPLPVOID) &audioPtr, &dataLen, NULL, NULL, 0))) { + sprintf(errormsg,"RtAudio: Unable to lock DS buffer: %s\n", getErrorMessage(result)); + throw StkError(errormsg,StkError::SOUNDCARD_CONTROL); + } + + // Zero the DS buffer + ZeroMemory(audioPtr, dataLen); + + // Unlock the DS buffer + if (FAILED(result = directSoundBuffer->Unlock(audioPtr, dataLen, NULL, 0))) { + sprintf(errormsg,"RtAudio: Unable to unlock DS buffer: %s\n", getErrorMessage(result)); + throw StkError(errormsg,StkError::SOUNDCARD_CONTROL); + } + } // end of play initialization + + + // RECORDING INITIALIZATION + if ( (!strcmp(mode,"record")) || (!strcmp(mode,"duplex")) ) { + + DSCBUFFERDESC directSoundCaptureDescription; + + if (device == -1) { + // use default device + if (FAILED(result = DirectSoundCaptureCreate(NULL, &directSoundCaptureObject, NULL))) { + sprintf(errormsg,"RtAudio: Unable to create default direct sound capture object: %s\n", getErrorMessage(result)); + throw StkError(errormsg,StkError::SOUNDCARD_NOT_FOUND); + } + goto have_good_input_device; + } else { + // Enumerate through the devices, trying the user specified device first. + // If that fails, prompt for action. + if (FAILED(result = DirectSoundCaptureEnumerate((LPDSENUMCALLBACK)SoundDeviceEnumCallback, this))) { + sprintf(errormsg,"RtAudio: Unable to enumerate through sound capture devices: %s\n", getErrorMessage(result)); + throw StkError(errormsg,StkError::SOUNDCARD_NOT_FOUND); + } + if (device >=0 && device < numDevices) { + // try user specified device if within bounds + directSoundGuid = devices[device].guid; + result = DirectSoundCaptureCreate(directSoundGuid, &directSoundCaptureObject, NULL); + if (result == DS_OK) goto have_good_input_device; + } + } + + printf("\n"); + for (i=0; i=0 && devNum < numDevices) { + directSoundGuid = devices[devNum].guid; + if (FAILED(result = DirectSoundCaptureCreate(directSoundGuid, &directSoundCaptureObject, NULL))) { + sprintf(errormsg,"RtAudio: Unable to create direct sound capture object: %s\n",getErrorMessage(result)); + throw StkError(errormsg,StkError::SOUNDCARD_CAPS); + } + } else { + throw StkError("RtAudio: Invalid device number specified!\n", StkError::SOUNDCARD_NOT_FOUND); + } + + have_good_input_device: + + // Setup the DS Capture buffer description + ZeroMemory(&directSoundCaptureDescription, sizeof(DSCBUFFERDESC)); + directSoundCaptureDescription.dwSize = sizeof(DSCBUFFERDESC); + directSoundCaptureDescription.dwFlags = 0; + directSoundCaptureBufferSize = (DWORD)(waveFormat.nAvgBytesPerSec * DS_CAPTURE_BUFFER_SIZE); + directSoundCaptureDescription.dwBufferBytes = directSoundCaptureBufferSize; + directSoundCaptureDescription.dwReserved = 0; + directSoundCaptureDescription.lpwfxFormat = &waveFormat; + + // Create the DS Capture buffer + if (FAILED(result = directSoundCaptureObject->CreateCaptureBuffer(&directSoundCaptureDescription, &directSoundCaptureBuffer, NULL))) { + sprintf(errormsg,"RtAudio: Unable to create DS capture buffer: %s\n", getErrorMessage(result)); + throw StkError(errormsg,StkError::SOUNDCARD_CONTROL); + } + + // Lock the DS Capture buffer + if (FAILED(result = directSoundCaptureBuffer->Lock(0, directSoundCaptureBufferSize, (LPLPVOID) &audioPtr, &dataLen, NULL, NULL, 0))) { + sprintf(errormsg,"RtAudio: Unable to lock DS capture buffer: %s\n", getErrorMessage(result)); + throw StkError(errormsg,StkError::SOUNDCARD_CONTROL); + } + + // Zero the DS Capture buffer + ZeroMemory(audioPtr, dataLen); + + // Size and allocate our inputBuffer + inputBufferSize = (long) (sampleRate * channels * 2 * sizeof(INT16)); + inputBuffer = (BYTE *) new BYTE[inputBufferSize]; + + //Zero our internal input buffer + ZeroMemory(inputBuffer, inputBufferSize); + + // Unlock the DS Capture buffer + if (FAILED(result = directSoundCaptureBuffer->Unlock(audioPtr, dataLen, NULL, 0))) { + sprintf(errormsg,"RtAudio: Unable to unlock DS capture buffer: %s\n", getErrorMessage(result)); + throw StkError(errormsg,StkError::SOUNDCARD_CONTROL); + } + + // Start the DS Capture buffer input + if (FAILED(result = directSoundCaptureBuffer->Start(DSCBSTART_LOOPING))) { + sprintf(errormsg,"RtAudio: Unable to start DS capture buffer looping: %s\n", getErrorMessage(result)); + throw StkError(errormsg,StkError::SOUNDCARD_CONTROL); + } + + //CALLBACK STUFF HERE + if ((timerID = timeSetEvent (TIMER_PERIOD, TIMER_RESOLUTION, PeriodicCallbackFn, (DWORD) this, TIME_PERIODIC)) == NULL) { + throw StkError("RtAudio: Couldn't start periodic timer callback function for audio input.\n",StkError::PROCESS_THREAD); + } + recording = true; + + } // end of record initialization + + if ( (!strcmp(mode,"play")) || (!strcmp(mode,"duplex")) ) { + // Start the DS buffer playback + if (FAILED(result = directSoundBuffer->Play(0, 0, DSBPLAY_LOOPING ))) { + sprintf(errormsg,"RtAudio: Unable to start DS buffer looping: %s\n", getErrorMessage(result)); + throw StkError(errormsg,StkError::SOUNDCARD_CONTROL); + } + playing = true; + } +} + +RtAudio :: ~RtAudio() +{ + // Cleanup the DS buffers + if (directSoundBuffer) { + directSoundBuffer->Stop(); + directSoundBuffer->Release(); + directSoundBuffer = NULL; + } + if (directSoundCaptureBuffer) { + directSoundCaptureBuffer->Stop(); + directSoundCaptureBuffer->Release(); + directSoundCaptureBuffer = NULL; + } + + // Cleanup the DS objects + if (directSoundObject) { + directSoundObject->Release(); + directSoundObject = NULL; + } + if (directSoundCaptureObject) { + directSoundCaptureObject->Release(); + directSoundCaptureObject = NULL; + } + if (timerID) { + timeKillEvent (timerID); + } + if (inputBuffer) { + delete [] inputBuffer; + inputBuffer = 0; + } +} + +int RtAudio :: playBuffer(short *buf, int bufsize) +{ + if (!playing) startPlay(); + + HRESULT result; + LPVOID buffer1 = NULL; + LPVOID buffer2 = NULL; + DWORD bufferSize1 = 0; + DWORD bufferSize2 = 0; + DWORD playPos, safePos; + int samplesToWrite; + + do { + // The user may send us a buffer of data that is too large + // for us to stream in at once, so set up a loop and check + // the size of their buffer. + samplesToWrite = bufsize; + if (samplesToWrite > RT_BUFFER_SIZE ) { + samplesToWrite = RT_BUFFER_SIZE ; + } + + // Find out where the read and "safe write" pointers are. + if (FAILED(result = directSoundBuffer->GetCurrentPosition(&playPos, &safePos))) { + sprintf(errormsg,"RtAudio: Unable to get current DS position: %s\n", getErrorMessage(result)); + throw StkError(errormsg,StkError::SOUNDCARD_CONTROL); + } + + if( playPos < nextWritePos ) playPos += directSoundBufferSize; // unwrap offset + DWORD endWrite = nextWritePos + samplesToWrite * sizeof(INT16); + + //printf("bufsize = %d ", bufsize); + // Check whether the entire write region is behind the play pointer. + while ( playPos < endWrite ) { + // If we are here, then we must wait until the play pointer + // gets beyond the write region. To do so, we can use the + // Sleep() function (which has questionable accuracy). + // Sleep until safePos catches up. Calculate number of + // milliseconds to wait as: + // time = distance * (milliseconds/second) * fudgefactor / + // ((bytes/sample) * (samples/second)) + // A "fudgefactor" less than 1 is used because it was found + // that sleeping too long was MUCH worse than sleeping for + // several shorter periods. + DWORD millis = (DWORD) (((endWrite - playPos) * 900.0) / ( sizeof(INT16) * sampleRate)); + //printf(". "); + Sleep( millis ); + + // Wake up, find out where we are now + result = directSoundBuffer->GetCurrentPosition( &playPos, &safePos ); + if( result != DS_OK ) return -1; + if( playPos < nextWritePos ) playPos += directSoundBufferSize; // unwrap offset + } + + // Lock free space in the buffer + result = directSoundBuffer->Lock (nextWritePos, samplesToWrite * sizeof(INT16), &buffer1, &bufferSize1, &buffer2, &bufferSize2, 0); + if (SUCCEEDED(result)) { + // Copy the buffer into the DS + CopyMemory(buffer1, buf, bufferSize1); + if(NULL != buffer2) CopyMemory(buffer2, buf+(bufferSize1/sizeof(INT16)), bufferSize2); + + // Update our buffer offset and unlock sound buffer + if (FAILED(directSoundBuffer->Unlock (buffer1, bufferSize1, buffer2, bufferSize2))) { + throw StkError("RtAudio: Unable to unlock DS buffer\n",StkError::SOUNDCARD_CONTROL); + } + nextWritePos = (nextWritePos + bufferSize1 + bufferSize2) % directSoundBufferSize; + } else { + sprintf(errormsg,"RtAudio: Unable to lock DS buffer: %s\n", getErrorMessage(result)); + throw StkError(errormsg,StkError::SOUNDCARD_CONTROL); + } + + //update how many samples still need to be written - possibly no more + bufsize -= samplesToWrite; + buf += samplesToWrite; + } while (bufsize > 0); + + return 0; +} + +int RtAudio :: recordBuffer(short *buf, int bufsize) +{ + if (!recording) startRecord(); + + if (internalError) { + throw StkError("RtAudio: Read failure in windoze capture thread.\n", + StkError::SOUNDCARD_CONTROL); + } + else { + UINT length; // length of data to copy + while (bufsize > 0) { + if (nextRecordWrite > nextRecordRead) { + length = nextRecordWrite - nextRecordRead; + if (length > bufsize * sizeof(INT16)) { + // there may be more data available than our user wants + length = bufsize * sizeof(INT16); + } + CopyMemory(buf, inputBuffer+nextRecordRead, length); + nextRecordRead += length; + bufsize -= length / sizeof(INT16); + buf += length / sizeof(INT16); + } + else if (nextRecordWrite == nextRecordRead) { + // no data is currently available to return to the user - + // so we sleep for the time necesary to produce the desired + // number of samples + Sleep((DWORD) (bufsize / sampleRate * 1000)); + } + else { + // this means that our write pointer must have wrapped around - + // in this case we return the last part ofthe buffer and save the + // readable beginning of the buffer to be copied next time around + // the loop, rather than do two copies here - just simpler code + length = inputBufferSize - nextRecordRead; + if (length > bufsize * sizeof(INT16)) { + // there may be more data available than our user wants + length = bufsize * sizeof(INT16); + CopyMemory(buf, inputBuffer+nextRecordRead, length); + // dont fully wrap around - we didn't use all data + nextRecordRead += length; + } + else { + CopyMemory(buf, inputBuffer+nextRecordRead, length); + nextRecordRead = 0; // we wrap around + } + bufsize -= length / sizeof(INT16); + buf += length / sizeof(INT16); + } + } + } + return 0; +} + +/**** Windoze specific overload of recordBuffer ****/ +int RtAudio :: recordBuffer(INT16** buf) +{ + if (!recording) startRecord(); + + if (internalError) { + throw StkError("RtAudio: Read failure in windoze capture thread.\n",StkError::SOUNDCARD_CONTROL); + + } else if (nextRecordRead == nextRecordWrite) { + // no new data + return 0; + + } else { + BYTE* temp = inputBuffer + nextRecordRead; + *buf = (INT16*) temp; + UINT length; + + if (nextRecordWrite > nextRecordRead) { + length = nextRecordWrite - nextRecordRead; + nextRecordRead = nextRecordWrite; + } else { + /* This means that our write pointer must have wrapped around - + in this case we return the last part ofthe buffer and save the + readable begining of the buffer to be returned next call to + recordBuffer, rather than have some complex two pointer wrap + around scheme. + */ + length = inputBufferSize - nextRecordRead; + nextRecordRead = 0; + } + + // We divide by two so that we return number of samples, not bytes + return (length/2); + } +} + +/**** Windows specific start and stop functions ****/ +void RtAudio :: stopPlay() +{ + if (!playing) return; + + HRESULT result; + BYTE* audioPtr; + DWORD dataLen; + + //stop the buffer + if (FAILED(result = directSoundBuffer->Stop())) { + sprintf(errormsg,"RtAudio: Unable to stop DS buffer looping: %s\n", getErrorMessage(result)); + throw StkError(errormsg,StkError::SOUNDCARD_CONTROL); + } + + // Lock the DS buffer and clear it so if we start to play again, we won't have old data playing + if (FAILED(result = directSoundBuffer->Lock(0, directSoundBufferSize, (LPLPVOID) &audioPtr, &dataLen, NULL, NULL, 0))) { + sprintf(errormsg,"RtAudio: Unable to lock DS buffer: %s\n", getErrorMessage(result)); + throw StkError(errormsg,StkError::SOUNDCARD_CONTROL); + } + + // Zero the DS buffer + ZeroMemory(audioPtr, dataLen); + + // Unlock the DS buffer + if (FAILED(result = directSoundBuffer->Unlock(audioPtr, dataLen, NULL, 0))) { + sprintf(errormsg,"RtAudio: Unable to unlock DS buffer: %s\n", getErrorMessage(result)); + throw StkError(errormsg,StkError::SOUNDCARD_CONTROL); + } + //if we start playing again, we must begin at beginning of buffer + nextWritePos = 0; + + playing = false; +} + +void RtAudio :: startPlay() +{ + if (playing) return; + + HRESULT result; + if (FAILED(result = directSoundBuffer->Play(0, 0, DSBPLAY_LOOPING ))) { + sprintf(errormsg,"RtAudio: Unable to restart DS buffer: %s\n", getErrorMessage(result)); + throw StkError(errormsg,StkError::SOUNDCARD_CONTROL); + } + playing = true; +} + +void RtAudio :: stopRecord() +{ + if (!recording) return; + + HRESULT result; + BYTE* audioPtr; + DWORD dataLen; + + // stop the buffer + if (FAILED(result = directSoundCaptureBuffer->Stop())) { + sprintf(errormsg,"RtAudio: Unable to stop DS capture buffer looping: %s\n", getErrorMessage(result)); + throw StkError(errormsg,StkError::SOUNDCARD_CONTROL); + } + + // Lock the DS buffer and clear it so if we start to play again, we won't have old data playing + if (FAILED(result = directSoundCaptureBuffer->Lock(0, directSoundCaptureBufferSize, (LPLPVOID) &audioPtr, &dataLen, NULL, NULL, 0))) { + sprintf(errormsg,"RtAudio: Unable to lock DS capture buffer: %s\n", getErrorMessage(result)); + throw StkError(errormsg,StkError::SOUNDCARD_CONTROL); + } + + // Zero the DS buffer + ZeroMemory(audioPtr, dataLen); + + // Unlock the DS buffer + if (FAILED(result = directSoundCaptureBuffer->Unlock(audioPtr, dataLen, NULL, 0))) { + sprintf(errormsg,"RtAudio: Unable to unlock DS capture buffer: %s\n", getErrorMessage(result)); + throw StkError(errormsg,StkError::SOUNDCARD_CONTROL); + } + // If we start playing again, we must begin at beginning of buffer + recording = false; +} + +void RtAudio :: startRecord() +{ + if (recording) return; + + HRESULT result; + if (FAILED(result = directSoundCaptureBuffer->Start(DSCBSTART_LOOPING))) { + sprintf(errormsg,"RtAudio: Unable to restart DS capture buffer looping: %s\n", getErrorMessage(result)); + throw StkError(errormsg,StkError::SOUNDCARD_CONTROL); + } + + recording = true; +} + + +/**** Internal Utilities ****/ + +void RtAudio::getInputSamples() +{ + /* This function is called periodically to get samples from + the direct sound capture buffer and transfer them into our + own buffer. + */ + HRESULT result; + LPVOID buffer1 = NULL; + LPVOID buffer2 = NULL; + DWORD size1 = 0; + DWORD size2 = 0; + DWORD capturePos, safePos; + static UINT nextDirectSoundReadPosition = 0; + int numBytesToLock; + + // Find out where the write and "safe read" pointers are. + if (FAILED(result = directSoundCaptureBuffer->GetCurrentPosition(&capturePos, &safePos))) { + internalError = true; + return; + } + + if (!recording) { + // The user doesn't want us to continue recording, so we must + // skip over info until they call startRecord(). + if (safePos < nextDirectSoundReadPosition) + safePos += directSoundCaptureBufferSize; //unwrap offset + numBytesToLock = safePos - nextDirectSoundReadPosition; //or in this case, num bytes to skip... + nextDirectSoundReadPosition = (nextDirectSoundReadPosition + numBytesToLock) % directSoundCaptureBufferSize; + nextRecordWrite = nextRecordRead; + return; + } + + if (safePos == nextDirectSoundReadPosition) { + // If this case, no input samples are yet ready so we must wait until + // some are. If this happens alot, we should increase the period of + // our callback function. + return; + } + + if ( safePos < nextDirectSoundReadPosition ) + safePos += directSoundCaptureBufferSize; //unwrap offset + numBytesToLock = safePos - nextDirectSoundReadPosition; + UINT availableSpace = inputBufferSize - nextRecordWrite; + + /* This code is rather long and complex, b/c it must handle the data + transfer from the direct sound capture buffer to our own internal + buffer, and both, one, or neither buffer may wrap around. + */ + if (SUCCEEDED(result = directSoundCaptureBuffer->Lock(nextDirectSoundReadPosition, numBytesToLock, &buffer1, &size1, &buffer2, &size2, 0))) { + if (availableSpace > size1) { + // we have more than enough space in our internal buffer to hold the data + CopyMemory((inputBuffer + nextRecordWrite), buffer1, size1); + availableSpace -= size1; + nextRecordWrite += size1; + + } else if (availableSpace == size1) { + // we have exactly enough space + CopyMemory((inputBuffer + nextRecordWrite), buffer1, size1); + availableSpace = inputBufferSize; + nextRecordWrite = 0; + + } else { + // we need to wrap around to the begining of the buffer, ie availableSpace < size1 + CopyMemory((inputBuffer + nextRecordWrite), buffer1, availableSpace); + size1 -= availableSpace; + CopyMemory(inputBuffer,(BYTE*)buffer1+availableSpace, size1); + availableSpace = inputBufferSize - size1; + nextRecordWrite = size1; + } + + if (buffer2 != NULL) { + // this means that the DS buffer wrapped around, and we need to + // deal with second data portion + if (availableSpace > size2) { + // we have more than enough space in our internal buffer to hold data + CopyMemory((inputBuffer + nextRecordWrite), buffer2, size2); + nextRecordWrite += size2; + + } else if (availableSpace == size2) { + // we have exactly enough space + CopyMemory((inputBuffer + nextRecordWrite), buffer2, size2); + nextRecordWrite = 0; + + } else { + // we need to wrap around to the begining of the buffer, ie availableSpace < size2 + CopyMemory((inputBuffer + nextRecordWrite), buffer2, availableSpace); + size2 -= availableSpace; + CopyMemory(inputBuffer,(BYTE*)buffer2+availableSpace, size2); + nextRecordWrite = size2; + } + } + + // Update our buffer offset and unlock sound buffer + directSoundCaptureBuffer->Unlock (buffer1, size1, buffer2, size2); + nextDirectSoundReadPosition = (nextDirectSoundReadPosition + size1 + size2) % directSoundCaptureBufferSize; + } else { + // we were unable to lock the buffer + internalError = true; + return; + } +} + +//This static callback function is used by the windows multimedia timer for recording +void CALLBACK RtAudio::PeriodicCallbackFn(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2) +{ + // dwUser contains ptr to our RtAudio object + RtAudio * soundIO = (RtAudio *) dwUser; + (soundIO->getInputSamples)(); +} + +//Windows forces you to use a callback function to enumerate through sound devices... +bool CALLBACK RtAudio::SoundDeviceEnumCallback(LPGUID lpguid,LPCSTR lpcstrDescription,LPCSTR lpcstrModule, LPVOID lpContext) +//bool CALLBACK RtAudio::SoundDeviceEnumCallback(LPGUID guid, LPCSTR desc, LPCSTR module, LPVOID context) +{ + ((RtAudio *) lpContext)->addDevice(lpguid,(char*) lpcstrDescription,(char*) lpcstrModule); + + /* + if (numDevices < MAX_DEVICES) { + if (guid != NULL) { + // make our own copy of the device ID, although probably not necesary + devices[numDevices].guid = (LPGUID) LocalAlloc(LPTR, sizeof(GUID)); + memcpy(devices[numDevices].guid, guid, sizeof(GUID)); + devices[numDevices].moduleName = module; + devices[numDevices].description = (char *)desc; + } + else { + devices[numDevices].guid = NULL; + devices[numDevices].description = "Default Device"; + devices[numDevices].moduleName = ""; + } + numDevices++; + } + */ + return true; +} + +void RtAudio::addDevice(LPGUID guid, char* description, char* moduleName) +{ + if (numDevices < MAX_DEVICES) { + if (guid != NULL) { + // make our own copy of the device ID, although probably not necesary + devices[numDevices].guid = (LPGUID) LocalAlloc(LPTR, sizeof(GUID)); + memcpy(devices[numDevices].guid,guid,sizeof(GUID)); + devices[numDevices].moduleName = moduleName; + devices[numDevices].description = description; + } + else { + devices[numDevices].guid = NULL; + devices[numDevices].description = "Default Device"; + devices[numDevices].moduleName = ""; + } + numDevices++; + } +} + +char* RtAudio::getErrorMessage(int code) { + switch (code) { + case DSERR_ALLOCATED: + return "Direct Sound already allocated"; + + case DSERR_CONTROLUNAVAIL: + return "Direct Sound control unavailable"; + + case DSERR_INVALIDPARAM: + return "Direct Sound invalid parameter"; + + case DSERR_INVALIDCALL: + return "Direct Sound invalid call"; + + case DSERR_GENERIC: + return "Direct Sound generic error"; + + case DSERR_PRIOLEVELNEEDED: + return "Direct Sound Priority level needed"; + + case DSERR_OUTOFMEMORY: + return "Direct Sound out of memory"; + + case DSERR_BADFORMAT: + return "Direct Sound bad format"; + + case DSERR_UNSUPPORTED: + return "Direct Sound unsupported error"; + + case DSERR_NODRIVER: + return "Direct Sound no driver error"; + + case DSERR_ALREADYINITIALIZED: + return "Direct Sound already initialized"; + + case DSERR_NOAGGREGATION: + return "Direct Sound no aggregation"; + + case DSERR_BUFFERLOST: + return "Direct Sound buffer lost"; + + case DSERR_OTHERAPPHASPRIO: + return "Direct Sound other app has priority"; + + case DSERR_UNINITIALIZED: + return "Direct Sound uninitialized"; + + default: + return "Direct Sound unknown error"; + } +} + +#endif diff --git a/STK/RTDuplex.cpp b/src/RtDuplex.cpp similarity index 60% rename from STK/RTDuplex.cpp rename to src/RtDuplex.cpp index a0dcd41..22be432 100644 --- a/STK/RTDuplex.cpp +++ b/src/RtDuplex.cpp @@ -1,6 +1,6 @@ /*******************************************/ /* Real-Time Duplex Input/Output Class, */ -/* by Gary P. Scavone, 1999 */ +/* by Gary P. Scavone, 1999-2000 */ /* */ /* This object opens the sound i/o */ /* device, reads buffers in from it, and */ @@ -11,17 +11,20 @@ /* Windows95/98 platforms. */ /*******************************************/ -#include "RTDuplex.h" +#include "RtDuplex.h" #if (defined(__STK_REALTIME_) ) -RTDuplex :: RTDuplex(MY_FLOAT srate, int chans) +RtDuplex :: RtDuplex(int chans, MY_FLOAT srate, int device) { // We'll let RTSoundIO deal with channel and srate limitations. channels = chans; - soundIO = new RTSoundIO(SRATE, channels, "duplex"); + sound_dev = new RtAudio(channels, srate, "duplex", device); writeCounter = 0; gain = 0.00003052; + data_length = RT_BUFFER_SIZE*channels; + indata = (INT16 *) new INT16[data_length+10]; + outdata = (INT16 *) new INT16[data_length+10]; insamples = new MY_FLOAT[channels]; #if (defined(__STK_REALTIME_) && defined(__OS_IRIX_)) // This is necessary under IRIX because it scales the input by 0.5 @@ -29,29 +32,31 @@ RTDuplex :: RTDuplex(MY_FLOAT srate, int chans) if (channels == 1) gain *= 2; #endif // Read half a buffer to get started - readCounter = RT_BUFFER_SIZE / 2; - soundIO->recordBuffer(&indata[readCounter],(RT_BUFFER_SIZE/2)); + readCounter = data_length / 2; + sound_dev->recordBuffer(&indata[readCounter],(data_length/2)); } -RTDuplex :: ~RTDuplex() +RtDuplex :: ~RtDuplex() { - soundIO->playBuffer(outdata,writeCounter); + sound_dev->playBuffer(outdata,writeCounter); writeCounter = 0; - while (writeCounterplayBuffer(outdata,writeCounter); - soundIO->playBuffer(outdata,writeCounter); // Are these extra writes necessary? - soundIO->playBuffer(outdata,writeCounter); - delete soundIO; + sound_dev->playBuffer(outdata,writeCounter); + sound_dev->playBuffer(outdata,writeCounter); // Are these extra writes necessary? + sound_dev->playBuffer(outdata,writeCounter); delete [ ] insamples; + delete [ ] indata; + delete [ ] outdata; + delete sound_dev; } -MY_FLOAT RTDuplex :: tick(MY_FLOAT outsample) +MY_FLOAT RtDuplex :: tick(MY_FLOAT outsample) { // We offset the data read and data write calls by RT_BUFFER_SIZE / 2 - if (readCounter >= RT_BUFFER_SIZE) { - soundIO->recordBuffer(indata,RT_BUFFER_SIZE); + if (readCounter >= data_length) { + sound_dev->recordBuffer(indata,data_length); readCounter = 0; } *insamples = (MY_FLOAT) indata[readCounter++]; @@ -66,19 +71,19 @@ MY_FLOAT RTDuplex :: tick(MY_FLOAT outsample) for (int i=0;i= RT_BUFFER_SIZE) { - soundIO->playBuffer(outdata,writeCounter); + if (writeCounter >= data_length) { + sound_dev->playBuffer(outdata,data_length); writeCounter = 0; } return *insamples; } -MY_MULTI RTDuplex :: mtick(MY_MULTI outsamples) +MY_MULTI RtDuplex :: mtick(MY_MULTI outsamples) { int i; // We offset the data read and data write calls by RT_BUFFER_SIZE / 2 - if (readCounter >= RT_BUFFER_SIZE) { - soundIO->recordBuffer(indata,RT_BUFFER_SIZE); + if (readCounter >= data_length) { + sound_dev->recordBuffer(indata,data_length); readCounter = 0; } for (i=0;i= RT_BUFFER_SIZE) { - soundIO->playBuffer(outdata,writeCounter); + if (writeCounter >= data_length) { + sound_dev->playBuffer(outdata,data_length); writeCounter = 0; } return insamples; diff --git a/src/RtMidi.cpp b/src/RtMidi.cpp new file mode 100644 index 0000000..900713b --- /dev/null +++ b/src/RtMidi.cpp @@ -0,0 +1,1078 @@ +/******************************************/ +/* + RtMidi.cpp + Realtime MIDI I/O Object for STK, + by Gary P. Scavone, 1998-2000. + Based in part on code by Perry + Cook (SGI), Paul Leonard (Linux), + the RoseGarden team (Linux), and + Bill Putnam (Win95/NT). + + At the moment, this object only + handles MIDI input, though MIDI + output code can go here when someone + decides they need it (and writes it). + + This object opens a MIDI input device + and parses MIDI messages into a MIDI + buffer. Time stamp info is converted + to deltaTime. MIDI data is stored as + MY_FLOAT to conform with SKINI. + + An optional argument to the constructor + can be used to specify a device or card. + When no argument is given, a default + device is opened or a list of available + devices is printed to allow selection + by the user. +*/ +/******************************************/ + +#include "RtMidi.h" + +#if defined(__STK_REALTIME_) + +#define MIDI_BUFFER_SIZE 1024 +int writeOffset; +int readOffset; + +#if defined(__OS_IRIX_) + +/*************************************/ +/* SGI MIDI INPUT */ +/*************************************/ + +#include +#include +#include +#include + +MDport inport; + +MDevent *midiBuffer; + +pthread_t midi_input_thread; + +void *midiInputThread(void *) +{ + MDevent newMessage; + int status; + + while (1) { + mdReceive(inport, &newMessage, 1); + status = (newMessage.msg[0] & MD_STATUSMASK); + + // Ignore all system messages + if (status != 0xf0) { + midiBuffer[writeOffset] = newMessage; + writeOffset++; + + if( writeOffset >= MIDI_BUFFER_SIZE ) + writeOffset = 0; + } + } +} + +RtMidi :: RtMidi(int device) +{ + int nports, card; + char msg[256]; + char *device_name = 0; + + nports = mdInit(); + if (nports < 1) { + sprintf(msg, "RtMidi: No SGI MIDI device available.\n"); + throw StkError(msg, StkError::MIDICARD_NOT_FOUND); + } + + if (device == -1) { + // open default MIDI interface + inport = mdOpenInPort(NULL); + if (inport == NULL) { + sprintf(msg, "RtMidi: Cannot open default SGI MIDI device.\n"); + throw StkError(msg, StkError::MIDICARD_CONTROL); + } + } + else { + card = device; + if ( (card < 0) || (card >= nports) ) { + printf("\n"); + for (card=0; card= MIDI_BUFFER_SIZE ) readOffset = 0; + + status = (lastEvent.msg[0] & MD_STATUSMASK); + byte1 = lastEvent.msg[1]; + byte2 = lastEvent.msg[2]; + channel = (lastEvent.msg[0] & MD_CHANNELMASK); + + if ((status == MD_PROGRAMCHANGE) || + (status == MD_CHANNELPRESSURE)) + { + messageType = status; + byteTwo = (float) byte1; + deltaTime = (MY_FLOAT) ((lastEvent.stamp - lastTimeStamp) * 0.000000001); + lastTimeStamp = lastEvent.stamp; + } + else if ((status == MD_NOTEON) || (status == MD_NOTEOFF) || + (status == MD_CONTROLCHANGE) || (status == MD_POLYKEYPRESSURE)) + { + messageType = status; + byteTwo = (float) byte1; + byteThree = (float) byte2; + deltaTime = (MY_FLOAT) ((lastEvent.stamp - lastTimeStamp) * 0.000000001); + lastTimeStamp = lastEvent.stamp; + } + else if (status == MD_PITCHBENDCHANGE) + { + messageType = status; + byteTwo = (float) byte1 * NORM_7; + byteTwo += (float) byte2; + deltaTime = (MY_FLOAT) ((lastEvent.stamp - lastTimeStamp) * 0.000000001); + lastTimeStamp = lastEvent.stamp; + } + else + { + messageType = -1; + } + + return messageType; +} + + +#elif ( defined(__OSS_API_) || defined(__ALSA_API_) ) + +/*************************************/ +/* OSS & ALSA MIDI INPUT */ +/*************************************/ + +#include +#include + +#if defined(__OSS_API_) + +#include +#include +#include +#include +#include +#include +int midi_in; + +#else // ALSA_API + +#include +snd_rawmidi_t *midi_in = 0; + +#endif + +typedef unsigned char byte; + +/* MIDI System Messages */ +#define MD_SYSTEM_MSG ((byte)0xF0) +#define MD_PGM_CHANGE ((byte)0xC0) +#define MD_CHN_PRESSURE ((byte)0xD0) +#define MD_PITCH_BEND ((byte)0xE0) +#define MessageType(MSG) (byte)((MSG) & ((byte)0xF0)) + +typedef struct { + byte data[3]; + float delta_time; +} MIDIMESSAGE; + +MIDIMESSAGE *midiBuffer; + +pthread_t midi_input_thread; + +void *midiInputThread(void *) +{ + int numArgs = 2, argsLeft = 0; + double lastTime = 0.0, newTime = 0.0; + byte newByte; + MIDIMESSAGE newMessage; + int n; + struct timeval tv; + + (void)gettimeofday(&tv, (struct timezone *)NULL); + lastTime = (double) (tv.tv_sec + (tv.tv_usec * 0.000001)); + + for (;;) { + +#if defined(__OSS_API_) + + // Normally, you should check the return value of this read() call. + // A return of -1 usually indicates an error. However, for OSS + // compatability in ALSA, we need to ignore such values. + + n = read(midi_in, &newByte, 1); + +#else // ALSA_API + + if ((n = snd_rawmidi_read(midi_in, &newByte, 1)) == -1) { + char msg[256]; + sprintf(msg, "RtMidi: Error reading ALSA raw MIDI device.\n"); + throw StkError(msg, StkError::MIDICARD_CAPS); + } + +#endif + + while (n > 0) { + if (newByte & 0x80) { // status byte + if (MessageType(newByte) == MD_SYSTEM_MSG) { + n--; + continue; + } + else if (MessageType(newByte) == MD_PGM_CHANGE || + MessageType(newByte) == MD_CHN_PRESSURE) { + numArgs = 1; + } + else { + numArgs = 2; + } + newMessage.data[0] = newByte; + newMessage.data[1] = 0; + newMessage.data[2] = 0; + argsLeft = numArgs; + } + else { // data byte + if ( argsLeft == numArgs ) + newMessage.data[1] = newByte; + else { + newMessage.data[2] = newByte; + } + argsLeft--; + + if ( !argsLeft ) { // MIDI message complete + // setup for running status mode (another event of the + // same type without status byte) + if (MessageType(newMessage.data[0]) == (int) MD_PGM_CHANGE || + MessageType(newMessage.data[0]) == (int) MD_CHN_PRESSURE) { + argsLeft = 1; + } + else { + argsLeft = 2; + } + + // determine the delta time since the last event + (void)gettimeofday(&tv, (struct timezone *)NULL); + newTime = (double) ((double)tv.tv_sec + (((double)tv.tv_usec) * 0.000001)); + newMessage.delta_time = (float) (newTime - lastTime); + lastTime = newTime; + + // Put newMessage in the circular buffer + midiBuffer[writeOffset] = newMessage; + writeOffset++; + + if( writeOffset >= MIDI_BUFFER_SIZE ) + writeOffset = 0; + } + } + n--; + } + } +} + +#if defined(__OSS_API_) + +#if defined(__MIDIATOR_) + +/* Hopefully, this special support for the MIDIator serial + port MIDI device is temporary and it will eventually be + incorporated into the OSS and ALSA APIs. + + This code is based almost entirely on David Topper's + driver code, which is available from: + + ftp://presto.music.virginia.edu/pub/midiator + + See the README-Linux STK document for details on how to + get the MIDIator setup correctly for use under linux. +*/ + +#include +#include + +#define BAUD_RATE B19200 +#define MAX_MIDI_DEVS 3 +#define MIDI_NAME "/dev/ttyS" + +void initializeMidiator(); + +RtMidi :: RtMidi(int device) +{ + int card = 0, err = 0, nChoices = 0; + char msg[256]; + char device_name[16]; + bool print_list = FALSE; + midi_in = 0; + + // /dev/midi should be a link to the default midi device under OSS + strcpy(device_name, MIDI_NAME); + + // The OSS API doesn't really give us a means for probing the + // capabilities of devices. Thus, we'll just pursue a brute + // force method of opening devices until we either find something + // that doesn't complain or we have to give up. We'll start with + // the default device, then try /dev/midi00, /dev/midi01, etc... + + if (device != -1) { + // check device specified as argument + sprintf(device_name, "%s%d", MIDI_NAME, device); + // try to open this device + if((midi_in = open(device_name, O_RDONLY, 0)) == -1) { + // Open device failed ... either busy or doesn't exist + print_list = TRUE; + printf("\n"); + card = 0; + } + else { + goto have_good_device; + } + } + + while (card < MAX_MIDI_DEVS) { + // if the default device doesn't work, try some others + sprintf(device_name, "%s%d", MIDI_NAME, card); + + if ((midi_in = open(device_name, O_RDONLY, 0)) == -1) { + // Open device failed ... either busy or doesn't exist + if (errno == EBUSY && print_list == FALSE) + fprintf(stderr,"RtMidi: Serial device (%s) is busy and cannot be opened.\n", + device_name); + card++; + continue; + } + + if (print_list) { + close(midi_in); + printf("Serial Port %d: %s\n", card, device_name); + nChoices++; + card++; + continue; + } + + // This device appears to be OK + goto have_good_device; + } + + if (print_list && nChoices) { + char choice[16]; + printf("\nType a serial port number from above: "); + fgets(choice, 16, stdin); + card = atoi(choice); + printf("\n"); + sprintf(device_name, "%s%d", MIDI_NAME, card); + if ((midi_in = open(device_name, O_RDONLY, 0)) == -1) { + sprintf(msg, "RtMidi: Unable to open serial port (%s) for MIDI input!\n", + device_name); + throw StkError(msg, StkError::MIDICARD_CONTROL); + } + goto have_good_device; + } + + // If we got here, no device was found to meet the requested functionality + sprintf(msg, "RtMidi: could not open any serial ports for MIDI input!\n"); + throw StkError(msg, StkError::MIDICARD_CAPS); + + have_good_device: // the current device is what we will use + + printf("\nInitializing MIDIator MS-124w ... "); + initializeMidiator(); + printf("ready on serial port %s.\n",device_name); + + // Set up the circular buffer for the MIDI input messages + midiBuffer = new MIDIMESSAGE[MIDI_BUFFER_SIZE]; + readOffset = 0; + writeOffset = 0; + + err = pthread_create(&midi_input_thread, NULL, midiInputThread, NULL); + if (err) { + sprintf(msg, "RtMidi: unable to create MIDI input thread.\n"); + throw StkError(msg, StkError::PROCESS_THREAD); + } +} + +#else // normal OSS stuff + +#define MAX_MIDI_DEVS 8 +#define MIDI_NAME "/dev/midi" + +RtMidi :: RtMidi(int device) +{ + int card = 0, err = 0, nChoices = 0; + midi_in = 0; + char msg[256]; + char device_name[16]; + bool print_list = FALSE; + + // /dev/midi should be a link to the default midi device under OSS + strcpy(device_name, MIDI_NAME); + + // The OSS API doesn't really give us a means for probing the + // capabilities of devices. Thus, we'll just pursue a brute + // force method of opening devices until we either find something + // that doesn't complain or we have to give up. We'll start with + // the default device, then try /dev/midi00, /dev/midi01, etc... + + if (device != -1) { + // check device specified as argument + sprintf(device_name, "%s%d%d", MIDI_NAME, 0, device); + // try to open this device + if((midi_in = open(device_name, O_RDONLY, 0)) == -1) { + // Open device failed ... either busy or doesn't exist + print_list = TRUE; + printf("\n"); + card = 1; + } + else { + goto have_good_device; + } + } + + while (card < MAX_MIDI_DEVS) { + // if the default device doesn't work, try some others + if (card > 0) sprintf(device_name, "%s%d%d", MIDI_NAME, 0, card-1); + + if ((midi_in = open(device_name, O_RDONLY, 0)) == -1) { + // Open device failed ... either busy or doesn't exist + if (errno == EBUSY && print_list == FALSE) + fprintf(stderr,"RtMidi: OSS MIDI device (%s) is busy and cannot be opened.\n", + device_name); + card++; + continue; + } + + if (print_list) { + close(midi_in); + printf("MIDI Card %d: %s\n", card-1, device_name); + nChoices++; + card++; + continue; + } + + // This device appears to be OK + goto have_good_device; + } + + if (print_list && nChoices) { + char choice[16]; + printf("\nType a MIDI card number from above: "); + fgets(choice, 16, stdin); + card = atoi(choice); + printf("\n"); + sprintf(device_name, "%s%d%d", MIDI_NAME, 0, card); + if ((midi_in = open(device_name, O_RDONLY, 0)) == -1) { + sprintf(msg, "RtMidi: Unable to open OSS device (%s) for MIDI input!\n", + device_name); + throw StkError(msg, StkError::MIDICARD_CONTROL); + } + goto have_good_device; + } + + // If we got here, no device was found to meet the requested functionality + sprintf(msg, "RtMidi: no OSS device found for MIDI input!\n"); + throw StkError(msg, StkError::MIDICARD_CAPS); + + have_good_device: // the current device is what we will use + + // Set up the circular buffer for the MIDI input messages + midiBuffer = new MIDIMESSAGE[MIDI_BUFFER_SIZE]; + readOffset = 0; + writeOffset = 0; + + err = pthread_create(&midi_input_thread, NULL, midiInputThread, NULL); + if (err) { + sprintf(msg, "RtMidi: unable to create MIDI input thread.\n"); + throw StkError(msg, StkError::PROCESS_THREAD); + } +} + +#endif // end of normal OSS section + +#else // ALSA_API + +RtMidi :: RtMidi(int device) +{ + int err = 0, nChoices = 0; + midi_in = 0; + char msg[256]; + int card, dev; + int default_card; + bool print_list = FALSE; + unsigned int mask; + snd_ctl_t *chandle; + struct snd_ctl_hw_info info; + snd_rawmidi_info_t midiinfo; + + mask = snd_cards_mask(); + if (!mask) { + sprintf(msg, "RtMidi: no ALSA sound/MIDI cards reported available.\n"); + throw StkError(msg, StkError::MIDICARD_NOT_FOUND); + } + + if (device == -1) { + default_card = snd_defaults_rawmidi_card(); + } + else { // check device specified as argument + if (!(mask & (1<= MIDI_BUFFER_SIZE ) readOffset = 0; + + messageType = (int) (lastEvent.data[0] & 0xf0); + channel = (int) (lastEvent.data[0] & 0x0f); + byteTwo = (float) lastEvent.data[1]; + if (messageType == (int) MD_PITCH_BEND) + byteTwo = (float) lastEvent.data[2] + (byteTwo * NORM_7); + else + byteThree = (float) lastEvent.data[2]; + deltaTime = (float) lastEvent.delta_time; + + return messageType; +} + +#if defined(__MIDIATOR_) + +void initializeMidiator() +{ + struct termios info; /* serial port configuration info */ + int status; /* Serial port status */ + struct timeval tv; /* to do a little time delay */ + char msg[256]; + + /* Get the current serial port attributes, so we can change + * the ones we care about. + */ + if (tcgetattr(midi_in, &info) < 0) { + sprintf(msg, "RtMidi: ioctl to get tty info failed (MIDIator support)!\n"); + throw StkError(msg, StkError::MIDICARD_CAPS); + } + + bzero(&info, sizeof(info)); + info.c_cflag = BAUD_RATE | CRTSCTS | CS8 | CLOCAL | CREAD; + info.c_iflag &= ~IGNCR; + info.c_oflag &= ~IGNCR; + + /* set input mode (non-canonical, no echo,...) */ + info.c_lflag = 0; + + info.c_cc[VTIME] = 1; /* inter-character timer unused */ + info.c_cc[VMIN] = 1; /* blocking read until 5 chars received */ + + tcflush(midi_in, TCIFLUSH); + + /* Set the attributes */ + tcsetattr(midi_in, TCSANOW, &info); + + /* Startup sequence, as per ron@MIDI_DEV's instructions */ + /* Many thanks to Ron for supporting Linux */ + + /* Step 1 */ + /* Power down */ + /* deassert DTR and RTS */ + ioctl(midi_in, TIOCMGET, &status); + status &= ~TIOCM_DTR; + status &= ~TIOCM_RTS; + ioctl(midi_in, TIOCMSET, status); + /* Wait 600 ms to make sure everything is stable */ + tv.tv_sec = 0; + tv.tv_usec = 600000; + select(0, NULL, NULL, NULL, &tv); + + /* Step 2 */ + /* Power up */ + /* assert break */ + ioctl(midi_in, TIOCMGET, &status); + status |= TCSBRK; + ioctl(midi_in, TIOCMSET, status); + /* Wait 300 ms to make sure everything is stable */ + tv.tv_sec = 0; + tv.tv_usec = 300000; + select(0, NULL, NULL, NULL, &tv); + + /* Step 3 */ + /* Set input mode */ + ioctl(midi_in, TIOCMGET, &status); + status &= ~TIOCM_DTR; + status |= TIOCM_RTS; + ioctl(midi_in, TIOCMSET, status); + /* Wait 40 us to make sure everything is stable */ + tv.tv_sec = 0; + tv.tv_usec = 40; + select(0, NULL, NULL, NULL, &tv); + + /* Step 4*/ + /* Set input mode */ + ioctl(midi_in, TIOCMGET, &status); + status |= TIOCM_DTR; + status &= TIOCM_RTS; + ioctl(midi_in, TIOCMSET, status); + /* Wait 40 us to make sure everything is stable */ + tv.tv_sec = 0; + tv.tv_usec = 40; + select(0, NULL, NULL, NULL, &tv); + + /* Step 5 */ + /* Set output mode */ + /* Bitval = RTS, clock = DTR */ + + /* 1 */ + ioctl(midi_in, TIOCMGET, &status); + status &= ~TIOCM_DTR; /* 0 */ + status |= TIOCM_RTS; /* 1 */ + ioctl(midi_in, TIOCMSET, status); + /* Wait 40 us to make sure everything is stable */ + tv.tv_sec = 0; + tv.tv_usec = 40; + select(0, NULL, NULL, NULL, &tv); + /****/ + ioctl(midi_in, TIOCMGET, &status); + status |= TIOCM_DTR; /* 1 rising edge clock */ + status |= TIOCM_RTS; /* 1 */ + ioctl(midi_in, TIOCMSET, status); + /* Wait 40 us to make sure everything is stable */ + tv.tv_sec = 0; + tv.tv_usec = 40; + select(0, NULL, NULL, NULL, &tv); + + /* 1 */ + ioctl(midi_in, TIOCMGET, &status); + status &= ~TIOCM_DTR; /* 0 */ + status |= TIOCM_RTS; /* 1 */ + ioctl(midi_in, TIOCMSET, status); + /* Wait 40 us to make sure everything is stable */ + tv.tv_sec = 0; + tv.tv_usec = 40; + select(0, NULL, NULL, NULL, &tv); + /****/ + ioctl(midi_in, TIOCMGET, &status); + status |= TIOCM_DTR; /* 1 rising edge clock */ + status |= TIOCM_RTS; /* 1 */ + ioctl(midi_in, TIOCMSET, status); + /* Wait 40 us to make sure everything is stable */ + tv.tv_sec = 0; + tv.tv_usec = 40; + select(0, NULL, NULL, NULL, &tv); + + /* 0 */ + ioctl(midi_in, TIOCMGET, &status); + status &= ~TIOCM_DTR; /* 0 */ + status &= ~TIOCM_RTS; /* 0 */ + ioctl(midi_in, TIOCMSET, status); + /* Wait 40 us to make sure everything is stable */ + tv.tv_sec = 0; + tv.tv_usec = 40; + select(0, NULL, NULL, NULL, &tv); + /****/ + ioctl(midi_in, TIOCMGET, &status); + status |= TIOCM_DTR; /* 1 rising edge clock */ + status &= ~TIOCM_RTS; /* 0 */ + ioctl(midi_in, TIOCMSET, status); + /* Wait 40 us to make sure everything is stable */ + tv.tv_sec = 0; + tv.tv_usec = 40; + select(0, NULL, NULL, NULL, &tv); + + /* Step 6 ... necessary ?*/ + /* Set RTS=0,DTR=1 ... but they already are from previous ^ */ + /****/ + ioctl(midi_in, TIOCMGET, &status); + status |= TIOCM_DTR; /* 1 rising edge clock */ + status &= ~TIOCM_RTS; /* 0 */ + ioctl(midi_in, TIOCMSET, status); + /* Wait 40 us to make sure everything is stable */ + tv.tv_sec = 0; + tv.tv_usec = 40; + select(0, NULL, NULL, NULL, &tv); + + /* Step 7 */ + /* Deassert break */ + ioctl(midi_in, TIOCMGET, &status); + status &= ~TCSBRK; + ioctl(midi_in, TIOCMSET, status); + /* Wait 100 ms to make sure everything is stable */ + tv.tv_sec = 0; + tv.tv_usec = 100000; + select(0, NULL, NULL, NULL, &tv); + /* End Midiator startup sequence -- midi_dev_type = MIDIATOR */ +} +#endif // MIDIator + +#elif defined(__OS_Win_) + +/*************************************/ +/* Windoze MIDI INPUT */ +/*************************************/ + +#define MIDI_NOTEON 0x90 +#define MIDI_NOTEOFF 0x80 +#define MIDI_POLYKEYPRESSURE 0xA0 +#define MIDI_CHANNELPRESSURE 0xD0 +#define MIDI_PROGRAMCHANGE 0xC0 +#define MIDI_CONTROLCHANGE 0xB0 +#define MIDI_PITCHBEND 0xE0 + +typedef struct { + DWORD data; + DWORD time; +} MIDIMESSAGE; + +MIDIMESSAGE *midiBuffer; + +static void CALLBACK midiInputCallback( HMIDIOUT hmin, UINT inputStatus, + DWORD instancePtr, DWORD midiMessage, DWORD timestamp) +{ + MIDIMESSAGE newMessage; + + switch (inputStatus) { + + case MIM_DATA: + + // Ignore Active Sensing messages + if ((midiMessage & 0xff) == 0xfe || (midiMessage & 0xff) == 0xf8) { + break; + } + newMessage.data = midiMessage; + newMessage.time = timestamp; + + // Put newMessage in the circular buffer + midiBuffer[writeOffset] = newMessage; + writeOffset++; + + if( writeOffset >= MIDI_BUFFER_SIZE ) + writeOffset = 0; + break; + + default: + break; + } +} + +HMIDIIN hMidiIn ; // Handle to Midi Output Device + +RtMidi :: RtMidi(int device) +{ + MMRESULT result; + UINT uDeviceID; + MIDIINCAPS deviceCaps; + UINT i; + char msg[256]; + + uDeviceID = midiInGetNumDevs(); + if (uDeviceID < 1) { + sprintf(msg, "RtMidi: No windoze MIDI device available.\n"); + throw StkError(msg, StkError::MIDICARD_NOT_FOUND); + } + + /* Our normal scheme is to use the default device if no argument + is supplied to RtMidi() or if the argument = -1. However, + there is no way to specify a default MIDI device under windoze. + So, I'm going to print the list if device = -1. + */ + if ( (device != -1) && (device < uDeviceID) ) { + // try to open device specified as argument + result = midiInOpen(&hMidiIn, device, + (DWORD)&midiInputCallback, + (DWORD)NULL, + CALLBACK_FUNCTION); + if (result == MMSYSERR_NOERROR) + goto have_good_device; + } + + printf("\nMIDI input interfaces available: %i\n",uDeviceID); + for (i=0; i 1) { + char choice[16]; + printf("\nType the MIDI interface to open: "); + fgets(choice, 16, stdin); + uDeviceID = (UINT) atoi(choice); + } + else uDeviceID -= 1; + + // Open the port and return any errors + result = midiInOpen(&hMidiIn, uDeviceID, + (DWORD)&midiInputCallback, + (DWORD)NULL, + CALLBACK_FUNCTION); + if (result != MMSYSERR_NOERROR) { + sprintf(msg, "RtMidi: Cannot open Windoze MIDI interface %d.\n", + uDeviceID); + throw StkError(msg, StkError::MIDICARD_CONTROL); + } + + have_good_device: // the current device is what we will use + + // Set up the circular buffer for the Midi Input Messages + midiBuffer = new MIDIMESSAGE[MIDI_BUFFER_SIZE]; + readOffset = 0; + writeOffset = 0; + + midiInStart( hMidiIn ); +} + +RtMidi :: ~RtMidi() +{ + midiInReset( hMidiIn ); + midiInStop( hMidiIn ); + midiInClose( hMidiIn ); + delete [] midiBuffer; +} + +int RtMidi :: nextMessage() +{ + int status; + int byte1; + int byte2; + MIDIMESSAGE lastEvent; + static DWORD lastTime = 0; + static DWORD newTime = 0; + + if ( readOffset == writeOffset ) return 0; + + lastEvent = midiBuffer[readOffset]; + + readOffset++; + if ( readOffset >= MIDI_BUFFER_SIZE ) readOffset = 0; + + status = (int) (lastEvent.data & 0xff); + byte1 = (int) (lastEvent.data & 0xff00) >> 8; + byte2 = (int) (lastEvent.data & 0xff0000) >> 16; + channel = (int) (status & 0x0f); + status &= 0xf0; // Clear lower byte of status + newTime = lastEvent.time; + deltaTime = (float) (newTime - lastTime) * 0.001; + lastTime = newTime; + + if ((status == MIDI_PROGRAMCHANGE) || + (status == MIDI_CHANNELPRESSURE)) + { + messageType = status; + byteTwo = (float) byte1; + } + else if ((status == MIDI_NOTEON) || (status == MIDI_NOTEOFF) || + (status == MIDI_CONTROLCHANGE) || (status == MIDI_POLYKEYPRESSURE)) + { + messageType = status; + byteTwo = (float) byte1; + byteThree = (float) byte2; + } + else if (status == MIDI_PITCHBEND) + { + messageType = status; + byteTwo = (float) (byte1 * NORM_7); + byteTwo += (float) byte2; + } + else + { + messageType = -1; + } + + return messageType; +} + +#endif + +void RtMidi :: printMessage() +{ + printf("type = %d, channel = %d, byte2 = %f, byte3 = %f\n", + this->getType(), this->getChannel(), this->getByteTwo(), + this->getByteThree()); +} + +int RtMidi :: getType() +{ + return messageType; +} + +int RtMidi :: getChannel() +{ + return channel; +} + +MY_FLOAT RtMidi :: getByteTwo() +{ + return byteTwo; +} + +MY_FLOAT RtMidi :: getByteThree() +{ + return byteThree; +} + +MY_FLOAT RtMidi :: getDeltaTime() +{ + return deltaTime; +} + + +#endif diff --git a/src/RtWvIn.cpp b/src/RtWvIn.cpp new file mode 100644 index 0000000..89ddfa1 --- /dev/null +++ b/src/RtWvIn.cpp @@ -0,0 +1,146 @@ +/*******************************************/ +/* RtWvIn Input Class, */ +/* by Gary P. Scavone, 1999-2000 */ +/* */ +/* This object inherits from WvIn and is */ +/* used to read in realtime 16-bit data */ +/* from a computer's audio port. */ +/* */ +/* NOTE: This object is NOT intended for */ +/* use in achieving simultaneous realtime */ +/* audio input/output (together with */ +/* RtWvOut). Under certain circumstances */ +/* such a scheme is possible, though you */ +/* should definitely know what you are */ +/* doing before trying. For safer "full- */ +/* duplex" operation, use the RtDuplex */ +/* class. */ +/*******************************************/ + +#include "RtWvIn.h" + +RtWvIn :: RtWvIn(int chans, MY_FLOAT srate, int device) +{ + chunking = 1; + looping = 0; + sound_dev = new RtAudio(chans, srate, "record", device); + channels = chans; + bufferSize = RT_BUFFER_SIZE; + data = 0; + rtdata = (INT16 *) new INT16[(bufferSize+1)*channels]; + + lastSamples = (INT16 *) new INT16[channels]; + for (int i=0;igetData(0); + + rate = (MY_FLOAT) srate / SRATE; + if (fmod(rate, 1.0) > 0.0) interpolate = 1; + else interpolate = 0; + phaseOffset = (MY_FLOAT) 0.0; + lastOutput = (MY_FLOAT *) new MY_FLOAT[channels]; + this->reset(); + + gain = 0.00003052; +#if (defined(__STK_REALTIME_) && defined(__OS_IRIX_)) + // This is necessary under IRIX because it scales the input by 0.5 + // when using single-channel input. + if (channels == 1) gain *= 2; +#endif +} + +RtWvIn :: ~RtWvIn() +{ + delete sound_dev; + if (rtdata) { + delete [ ] rtdata; + rtdata = 0; + } + if (lastSamples) { + delete [ ] lastSamples; + lastSamples = 0; + } +} + +void RtWvIn :: setRate(MY_FLOAT aRate) +{ + // Negative rates not allowed for realtime input + rate = fabs(aRate); + + if (fmod(rate, 1.0) != 0.0) interpolate = 1; + else interpolate = 0; +} + +void RtWvIn :: addTime(MY_FLOAT aTime) +{ + // Negative time shift no allowed for realtime input + time += fabs(aTime); +} + +void RtWvIn :: setLooping(int aLoopStatus) +{ + // No looping for realtime data. + looping = 0; +} + +long RtWvIn :: getSize() +{ + return bufferSize; +} + +void RtWvIn :: getData(long index) +{ + static long temp = RT_BUFFER_SIZE*channels; + sound_dev->recordBuffer(&rtdata[channels],temp); + + /* Fill in the extra sample frame for interpolation. + * We do this by pre-pending the last sample frame + * from the previous input buffer to the current one. + */ + for (int i=0;i= bufferSize) { + this->getData(0); + while (time >= bufferSize) + time -= bufferSize; + } + + // integer part of time address + index = (long) time; + + if (interpolate) { + // fractional part of time address + alpha = time - (MY_FLOAT) index; + index *= channels; + for (int i=0;iplayBuffer(data,counter); + counter = 0; + while (counterplayBuffer(data,counter); + sound_dev->playBuffer(data,counter); // Are these extra writes necessary? + sound_dev->playBuffer(data,counter); + delete sound_dev; +} + +void RtWvOut :: tick(MY_FLOAT sample) +{ + for (int i=0;i= data_length) { + sound_dev->playBuffer(data,data_length); + counter = 0; + } +} + +void RtWvOut :: mtick(MY_MULTI samples) +{ + for (int i=0;i= data_length) { + sound_dev->playBuffer(data,data_length); + counter = 0; + } +} + +//windows stop and start methods ... because windoze sucks +#if (defined(__OS_Win_) ) + +void RtWvOut :: stopPlay() { + sound_dev->stopPlay(); +} + +void RtWvOut :: startPlay() { + sound_dev->startPlay(); +} + +void RtWvOut :: stopRecord() { + sound_dev->stopRecord(); +} + +void RtWvOut :: startRecord() { + sound_dev->startRecord(); +} + +#endif // extra windoze crap + +#endif diff --git a/STK/SKINI11.cpp b/src/SKINI11.cpp similarity index 100% rename from STK/SKINI11.cpp rename to src/SKINI11.cpp diff --git a/STK/SKINI11.tbl b/src/SKINI11.tbl similarity index 100% rename from STK/SKINI11.tbl rename to src/SKINI11.tbl diff --git a/STK/SamplFlt.cpp b/src/SamplFlt.cpp similarity index 100% rename from STK/SamplFlt.cpp rename to src/SamplFlt.cpp diff --git a/STK/Sampler.cpp b/src/Sampler.cpp similarity index 100% rename from STK/Sampler.cpp rename to src/Sampler.cpp diff --git a/STK/Shakers.cpp b/src/Shakers.cpp similarity index 98% rename from STK/Shakers.cpp rename to src/Shakers.cpp index 16e39ac..63809ae 100644 --- a/STK/Shakers.cpp +++ b/src/Shakers.cpp @@ -546,7 +546,7 @@ int Shakers :: setupNum(int inst) void Shakers :: noteOn(MY_FLOAT freq, MY_FLOAT amp) { // Yep ... pretty kludgey, but it works! - int noteNum = (int) ((12*log(freq/220)/log(2)) + 57.01) % 32; + int noteNum = (int) ((12*log(freq/220)/log(2.0)) + 57.01) % 32; if (instType != noteNum) instType = this->setupNum(noteNum); //shakeEnergy = amp * MAX_SHAKE * 0.1; shakeEnergy += amp * MAX_SHAKE * 0.1; @@ -641,7 +641,7 @@ void Shakers :: controlChange(int number, MY_FLOAT value) #if defined(_debug_) printf("Shakers : ControlChange: Number=%i Value=%f\n",number,value); #endif - if (number == __SK_Breath_) { // control_change #2 + if (number == __SK_ShakerEnergy_) { // control_change #2 #if defined(_debug_) printf("shaking \n"); #endif @@ -653,7 +653,7 @@ void Shakers :: controlChange(int number, MY_FLOAT value) lastRatchetPos = (int) value; } } - else if (number == __SK_FootControl_) { // control_change #4 + else if (number == __SK_ShakerDamping_) { // control_change #11 #if defined(_debug_) printf("setting decay\n"); #endif @@ -676,7 +676,7 @@ void Shakers :: controlChange(int number, MY_FLOAT value) for (i=0;inormalize(); filter = new OnePole; noise = new Noise; bqpoles = new TwoPole; diff --git a/STK/SingWave.cpp b/src/SingWave.cpp similarity index 80% rename from STK/SingWave.cpp rename to src/SingWave.cpp index b8968be..1820663 100644 --- a/STK/SingWave.cpp +++ b/src/SingWave.cpp @@ -11,34 +11,51 @@ /*******************************************/ #include "SingWave.h" -#include "swapstuf.h" +#include +#include + +#ifdef __LITTLE_ENDIAN__ + #include "ByteSwap.h" +#endif SingWave :: SingWave(char *fileName) { - long i; - INT16 temp; FILE *fd; - // extern short SwapINT16(short); + char msg[256]; + + // Use the system call "stat" to determine the file length + struct stat filestat; + if (stat(fileName, &filestat) == -1) + { /* Opening file failed */ + sprintf(msg, "SingWave: Couldn't stat or find file (%s).\n", fileName); + throw StkError(msg, StkError::FILE_NOT_FOUND); + } + length = (long) filestat.st_size / 2; // length in 2-byte samples + + // Open the file and read samples into data[] + fd = fopen(fileName,"rb"); + if (!fd) { + sprintf(msg, "SingWave: Couldn't open or find file (%s).\n", fileName); + throw StkError(msg, StkError::FILE_NOT_FOUND); + } - fd = fopen(fileName,"rb"); - if (!fd) { - printf("Couldn't find soundfile %s !!!!!!!!\n",fileName); - } - i = 0; - while (fread(&temp,2,1,fd)) i++; - length = i; fseek(fd,0,0); - data = (MY_FLOAT *) malloc((length + 1) * sizeof(MY_FLOAT)); - i = 0; - while (fread(&temp,2,1,fd)) { + data = (MY_FLOAT *) new MY_FLOAT[(length+1)]; + + // Read samples into data[]. Use MY _FLOAT data structure to store INT16 samples + INT16 *buf = (INT16 *)data; + fseek(fd,0,SEEK_SET); // Only here to bypass bug in Linux glibc 2.1x (RedHat 6.0) + fread(buf,length,2,fd); + // Convert in place (unpack) to MY_FLOAT from the end of the array + for (int i=length-1; i>=0; i--) { #ifdef __LITTLE_ENDIAN__ - temp = SwapINT16(temp); + swap16((unsigned char *)(buf+i)); #endif - data[i] = temp; - i++; - } + data[i] = buf[i]; + } + fclose(fd); + data[length] = data[length-1]; - fclose(fd); mytime = (MY_FLOAT) 0.0; rate = (MY_FLOAT) 1.0; sweepRate = (MY_FLOAT) 0.001; diff --git a/src/SndWvIn.cpp b/src/SndWvIn.cpp new file mode 100644 index 0000000..b2402d0 --- /dev/null +++ b/src/SndWvIn.cpp @@ -0,0 +1,172 @@ +/*******************************************/ +/* SndWvIn Input Class, */ +/* by Gary P. Scavone, 2000 */ +/* */ +/* This object inherits from WvIn and is */ +/* used to open NeXT/Sun .snd 16-bit data */ +/* (signed integer) files for playback. */ +/* */ +/* .snd files are always big-endian. */ +/*******************************************/ + +#include "SndWvIn.h" + +#ifdef __LITTLE_ENDIAN__ + #include "ByteSwap.h" +#endif + +SndWvIn :: SndWvIn(char *fileName, const char *mode) +{ + char msg[256]; + + // check mode string + if ( strcmp(mode,"oneshot") && strcmp(mode,"looping") ) { + sprintf(msg, "SndWvIn: constructor parameter 'mode' must be oneshot or looping only.\n"); + throw StkError(msg, StkError::FUNCTION_SYNTAX); + } + + // Open the file and get header info + fd = fopen(fileName,"rb"); + if (!fd) { + sprintf(msg, "SndWvIn: Couldn't open or find file (%s).\n", fileName); + throw StkError(msg, StkError::FILE_NOT_FOUND); + } + + // Make sure this is a .snd format file + char magic[4]; + fseek(fd,0,SEEK_SET); // Locate magic number in header + fread(magic,4,1,fd); + if (strncmp(magic,".snd",4)) { + fclose(fd); + sprintf(msg, "SndWvIn: %s doesn't appear to be an SND file.\n", fileName); + throw StkError(msg, StkError::FILE_ERROR); + } + + // Check that the data is not compressed + INT32 format; + fseek(fd,12,SEEK_SET); // Locate format + fread(&format,4,1,fd); +#ifdef __LITTLE_ENDIAN__ + swap32((unsigned char *)&format); +#endif + if (format != 3) { // 16-bit linear PCM = 3 + fclose(fd); + sprintf(msg, "SndWvIn: STK does not currently support data formats other than 16 bit signed integer.\n"); + throw StkError(msg, StkError::FILE_ERROR); + } + + // Get file sample rate from the header and set the default rate + INT32 srate; + fread(&srate,4,1,fd); +#ifdef __LITTLE_ENDIAN__ + swap32((unsigned char *)&srate); +#endif + rate = (MY_FLOAT) (srate/SRATE); + + // Get number of channels from the header + INT32 chans; + fread(&chans,4,1,fd); +#ifdef __LITTLE_ENDIAN__ + swap32((unsigned char *)&chans); +#endif + channels = chans; + + fseek(fd,4,SEEK_SET); + fread(&dataOffset,4,1,fd); +#ifdef __LITTLE_ENDIAN__ + swap32((unsigned char *)&dataOffset); +#endif + + // Get length of data from the header + fread(&fileSize,4,1,fd); +#ifdef __LITTLE_ENDIAN__ + swap32((unsigned char *)&fileSize); +#endif + // fileSize is the number of sample frames + fileSize /= 2 * channels; + bufferSize = fileSize; + + if ((fileSize*channels) > MAX_FILE_LOAD_SIZE) { + printf("\nSndWvIn: The .SND file (%s) has more than %d samples and\n", + fileName, MAX_FILE_LOAD_SIZE); + printf("will be loaded incrementally from disk. Normalization will be disabled.\n"); + chunking = 1; + bufferSize = LOAD_BUFFER_SIZE; + } + + // Setup for looping or one-shot playback + if (!strcmp(mode,"looping")) + looping = 1; + else // default = oneshot + looping = 0; + + data = (MY_FLOAT *) new MY_FLOAT[(bufferSize+1)*channels]; + this->getData(0); // Read samples into data[] + + if (fmod(rate, 1.0) != 0.0) interpolate = 1; + else interpolate = 0; + phaseOffset = (MY_FLOAT) 0.0; + lastOutput = (MY_FLOAT *) new MY_FLOAT[channels]; + this->reset(); + + // finally, let's normalize the data by default + this->normalize(); +} + +SndWvIn :: ~SndWvIn() +{ +} + +void SndWvIn :: getData(long index) +{ + /* Compare index to current readPointer and modify as needed. + * The following while() loops will only execute on calls subsequent + * to class instantiation ... and thus, only when "chunking". + */ + while (index < readPointer) { + readPointer -= LOAD_BUFFER_SIZE; + bufferSize = LOAD_BUFFER_SIZE; + if (readPointer < 0) { + bufferSize += readPointer; + readPointer = 0; + } + } + while (index >= readPointer+bufferSize) { + readPointer += LOAD_BUFFER_SIZE; + bufferSize = LOAD_BUFFER_SIZE; + if (readPointer+LOAD_BUFFER_SIZE >= fileSize) { + bufferSize = fileSize - readPointer; + } + } + + fseek(fd, dataOffset+(long)(readPointer*channels*2), SEEK_SET); + long length = bufferSize; + int end_of_file = (readPointer+bufferSize == fileSize); + if (!end_of_file) length += 1; + + // Read samples into data[]. Use MY _FLOAT data structure to store INT16 samples + INT16 *buf = (INT16 *)data; + fread(buf, length*channels, 2, fd); + // Convert in place (unpack) to MY_FLOAT from the end of the array + for (int i=length*channels-1; i>=0; i--) { +#ifdef __LITTLE_ENDIAN__ + swap16((unsigned char *)(buf+i)); +#endif + data[i] = buf[i]; + if (chunking) data[i] *= 0.00003051; + } + + // fill in the extra sample frame for interpolation + if (end_of_file) { + for (int j=0; j +#include +#include +#include +#include +#include + +pthread_t strm_thread; +pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + +#define MUTEX_LOCK(A) pthread_mutex_lock(A) +#define MUTEX_UNLOCK(A) pthread_mutex_unlock(A) + +#elif defined(__OS_Win_) +#include +#include + +unsigned long strm_thread; +CRITICAL_SECTION mutex; + +#define MUTEX_LOCK(A) EnterCriticalSection(A) +#define MUTEX_UNLOCK(A) LeaveCriticalSection(A) + +#endif + +#if (defined(__OS_IRIX_) || defined(__OS_Linux_)) + +void *streamInThread(void * chan) + +#elif defined(__OS_Win_) + +void streamInThread(void * chan) + +#endif + +{ + extern char *stream_buffer; + + int remote_socket; + char msg[256]; + int fd, i = -1, writefrag = 0; + long fill_size = RT_BUFFER_SIZE * (int)chan * 2; // bytes + fd_set mask, rmask; + struct sockaddr_in mysocket; + static struct timeval timeout = {0, 10000}; // ten milliseconds + +#if defined(__OS_Win_) // Windoze-only stuff + WSADATA wsaData; + WORD wVersionRequested = MAKEWORD(1,1); + + WSAStartup(wVersionRequested, &wsaData); + if (wsaData.wVersion != wVersionRequested) { + sprintf(msg, "StrmWvIn: Wrong Windoze socket library version!\n"); + throw StkError(msg, StkError::PROCESS_SOCKET); + } +#endif + + // Create the server-side socket + local_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (local_socket < 0) { + sprintf(msg, "StrmWvIn: Couldn't create socket!\n"); + throw StkError(msg, StkError::PROCESS_SOCKET); + } + + mysocket.sin_family=AF_INET; + mysocket.sin_addr.s_addr=INADDR_ANY; + mysocket.sin_port=htons(STK_STREAM_PORT); + + /* Bind socket to the appropriate port and interface (INADDR_ANY) */ + if (bind(local_socket, (struct sockaddr *)&mysocket, sizeof(mysocket)) < 0) { + sprintf(msg, "StrmWvIn: Couldn't bind socket!\n"); + throw StkError(msg, StkError::PROCESS_SOCKET); + } + + /* Listen for one incoming connection */ + if (listen(local_socket, 1) < 0) { + sprintf(msg, "StrmWvIn: Couldn't set up listen on socket!\n"); + throw StkError(msg, StkError::PROCESS_SOCKET); + } + printf("\nStrmWvIn listening for a connection on port %d\n", STK_STREAM_PORT); + + remote_socket=accept(local_socket, NULL, NULL); + if (remote_socket < 0) { + sprintf(msg, "StrmWvIn: Couldn't accept connection request!\n"); + throw StkError(msg, StkError::PROCESS_SOCKET); + } + printf(" ... connection made!\n"); + + FD_ZERO(&mask); + fd = remote_socket; + FD_SET(fd, &mask); + + for (;;) { + rmask = mask; + // select will block until data is available for reading + select(fd+1, &rmask, (fd_set *)0, (fd_set *)0, NULL); + if (FD_ISSET(fd, &rmask)) { // data is available + MUTEX_LOCK(&mutex); + // don't fill if we're ahead + if (g_nfrags_filled < NUM_STREAM_IN_FRAGMENTS) { +#if defined(__OS_Win_) + // Yet again, we have to make an extra special effort to get things to work + // under windoze ... why do I waste my time supporting this shitty OS? + // The windoze recv() call doesn't allow the use of the MSG_WAITALL flag. + // The following scheme should work but could cause even worse performance if + // we're in an underrun situation. + int j; + i = recv(fd, &stream_buffer[fill_size*writefrag], fill_size, 0); + if (i == SOCKET_ERROR) i = 0; + while (i < fill_size && i > 0) { + j = recv(fd, &stream_buffer[fill_size*writefrag+i], fill_size-i, 0); + if (j == 0 || j == SOCKET_ERROR) { + i = 0; + break; + } + i += j; + } +#else + i = recv(fd, &stream_buffer[fill_size*writefrag], fill_size, MSG_WAITALL); +#endif + if (i==0) { + printf("The remote StrmWvIn socket connection has closed!\n"); +#if defined(__OS_Win_) + closesocket(fd); +#else + close(fd); +#endif + g_thread_done = 1; + MUTEX_UNLOCK(&mutex); + break; + } + g_nfrags_filled++; + if (++writefrag == NUM_STREAM_IN_FRAGMENTS) + writefrag = 0; + MUTEX_UNLOCK(&mutex); + } + else { // wait a little + MUTEX_UNLOCK(&mutex); +#if defined(__OS_Win_) + // the windoze select function doesn't work as a timer + Sleep((DWORD) 10); +#else + // reset the timeout values because of linux "select" implementation + timeout.tv_sec = 0; + timeout.tv_usec = 10000; // 0.01 seconds + select(0, NULL, NULL, NULL, &timeout); +#endif + } + } + } + + // We can only get here if the remote socket shuts down +#if defined(__OS_Win_) + closesocket(local_socket); + WSACleanup(); + _endthread(); +#else + close(local_socket); + return NULL; +#endif +} + +StrmWvIn :: StrmWvIn(int chans, MY_FLOAT srate) +{ + char msg[256]; + long buffer_size = RT_BUFFER_SIZE * NUM_STREAM_IN_FRAGMENTS * chans * 2; + chunking = 1; + looping = 0; + + stream_buffer = (char *) new char[buffer_size]; + memset(stream_buffer, 0, buffer_size); + + // start the input stream thread +#if (defined(__OS_IRIX_) || defined(__OS_Linux_)) + if (pthread_create(&strm_thread, NULL, streamInThread, (void *)chans)) { + sprintf(msg, "StrmWvIn: unable to create input stream thread!\n"); + throw StkError(msg, StkError::PROCESS_THREAD); + } +#elif defined(__OS_Win_) + InitializeCriticalSection(&mutex); + strm_thread = _beginthread(streamInThread, 0, (void *)chans); + if (strm_thread == 0) { + sprintf(msg, "StrmWvIn: unable to create input stream thread!\n"); + throw StkError(msg, StkError::PROCESS_THREAD); + } +#endif + + channels = chans; + bufferSize = RT_BUFFER_SIZE; + data = 0; + strmdata = (INT16 *) new INT16[(bufferSize+1)*channels]; + + lastSamples = (INT16 *) new INT16[channels]; + for (int i=0;igetData(0); + + rate = (MY_FLOAT) srate / SRATE; + if (fmod(rate, 1.0) > 0.0) interpolate = 1; + else interpolate = 0; + phaseOffset = (MY_FLOAT) 0.0; + lastOutput = (MY_FLOAT *) new MY_FLOAT[channels]; + this->reset(); +} + +StrmWvIn :: ~StrmWvIn() +{ +#if (defined(__OS_IRIX_) || defined(__OS_Linux_)) + shutdown(local_socket,0); + pthread_cancel(strm_thread); + pthread_join(strm_thread, NULL); + pthread_mutex_destroy(&mutex); +#elif defined(__OS_Win_) + closesocket(local_socket); + WSACleanup(); + TerminateThread((HANDLE)strm_thread,0); + DeleteCriticalSection(&mutex); +#endif + + if (strmdata) { + delete [ ] strmdata; + strmdata = 0; + } + if (stream_buffer) { + delete [] stream_buffer; + stream_buffer = 0; + } + if (lastSamples) { + delete [ ] lastSamples; + lastSamples = 0; + } +} + +void StrmWvIn :: setRate(MY_FLOAT aRate) +{ + // Negative rates not allowed for realtime input + rate = fabs(aRate); + + if (fmod(rate, 1.0) != 0.0) interpolate = 1; + else interpolate = 0; +} + +void StrmWvIn :: addTime(MY_FLOAT aTime) +{ + // Negative time shift no allowed for realtime input + time += fabs(aTime); +} + +void StrmWvIn :: setLooping(int aLoopStatus) +{ + // No looping for realtime data. + looping = 0; +} + +long StrmWvIn :: getSize() +{ + return bufferSize; +} + +void StrmWvIn :: getData(long index) +{ + /* We have two potential courses of action should this method + * be called and the stream_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). + */ + static int readfrag = 0, i; + static struct timeval timer = {0, 10000}; // ten milliseconds + long temp = RT_BUFFER_SIZE*channels; + + /* wait until data is ready */ + while (g_nfrags_filled == 0) { +#if defined(__OS_Win_) + // the windoze select function doesn't work as a timer + Sleep((DWORD) 10); +#else + timer.tv_sec = 0; + timer.tv_usec = 10000; // 0.01 seconds + select(0, NULL, NULL, NULL, &timer); +#endif + if (g_thread_done) { + finished = 1; + return; + } + } + + /* copy data from stream_buffer to strmdata */ + MUTEX_LOCK(&mutex); + memcpy(&strmdata[channels], &stream_buffer[readfrag*temp*2], temp*2); +#ifdef __LITTLE_ENDIAN__ + for (i=0; i= bufferSize) { + this->getData(0); + while (time >= bufferSize) + time -= bufferSize; + } + + // integer part of time address + index = (long) time; + + if (interpolate) { + // fractional part of time address + alpha = time - (MY_FLOAT) index; + index *= channels; + for (int i=0;i +#include +#include +#include + +#elif defined(__OS_Win_) +#include + +#endif + +StrmWvOut :: StrmWvOut(int port, const char *hostname, int chans) +{ + char msg[256]; + struct sockaddr_in server_address; + + if (chans < 1) { + sprintf(msg, "StrmWvOut: number of channels (%d) must be one or greater.\n", chans); + throw StkError(msg, StkError::FUNCTION_SYNTAX); + } + + channels = chans; + +#if defined(__OS_Win_) // Windoze-only stuff + WSADATA wsaData; + WORD wVersionRequested = MAKEWORD(1,1); + + WSAStartup(wVersionRequested, &wsaData); + if (wsaData.wVersion != wVersionRequested) { + sprintf(msg, "StrmWvOut: Wrong Windoze socket library version!\n"); + throw StkError(msg, StkError::PROCESS_SOCKET); + } +#endif + + // Create the client-side socket + local_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (local_socket < 0) { + sprintf(msg, "StrmWvOut: Couldn't create socket!\n"); + throw StkError(msg, StkError::PROCESS_SOCKET); + } + + struct hostent *hostp; + + if ((hostp = gethostbyname(hostname)) == 0) { + sprintf(msg, "StrmWvOut: unknown host (%s)!\n", hostname); + throw StkError(msg, StkError::PROCESS_SOCKET_IPADDR); + } + + // Fill in the address structure + 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(local_socket, (struct sockaddr *)&server_address, + sizeof(server_address) ) < 0) { +#if defined(__OS_Win_) + closesocket(local_socket); + WSACleanup(); +#else + close(local_socket); +#endif + sprintf(msg, "StrmWvOut: Couldn't connect to socket server!\n"); + throw StkError(msg, StkError::PROCESS_SOCKET); + } + + data_length = RT_BUFFER_SIZE*channels; // samples + // Add a few extra samples for good measure + data = (INT16 *) new INT16[data_length+10]; +} + +StrmWvOut :: ~StrmWvOut() +{ + while (counter= data_length) { + if (send(local_socket, (const char *)data, data_length*2, 0) < 0) { + char msg[256]; +#if defined(__OS_Win_) + closesocket(local_socket); + WSACleanup(); +#else + close(local_socket); +#endif + sprintf(msg, "StrmWvOut: connection to socket server failed!\n"); + throw StkError(msg, StkError::PROCESS_SOCKET); + } + counter = 0; + } +} + +void StrmWvOut :: mtick(MY_MULTI samples) +{ + for (int i=0;i= data_length) { + if (send(local_socket, (const char *)data, data_length*2, 0) < 0) { + char msg[256]; +#if defined(__OS_Win_) + closesocket(local_socket); + WSACleanup(); +#else + close(local_socket); +#endif + sprintf(msg, "StrmWvOut: connection to socket server failed!\n"); + throw StkError(msg, StkError::PROCESS_SOCKET); + } + counter = 0; + } +} + +#endif diff --git a/STK/SubNoise.cpp b/src/SubNoise.cpp similarity index 100% rename from STK/SubNoise.cpp rename to src/SubNoise.cpp diff --git a/STK/TablLook.cpp b/src/TablLook.cpp similarity index 79% rename from STK/TablLook.cpp rename to src/TablLook.cpp index 3019c4b..7f5b509 100644 --- a/STK/TablLook.cpp +++ b/src/TablLook.cpp @@ -14,28 +14,28 @@ #include #ifdef __LITTLE_ENDIAN__ - #include "swapstuf.h" + #include "ByteSwap.h" #endif TablLook :: TablLook(char *fileName) { - extern double SwapDouble(double); + char msg[256]; // Use the system call "stat" to determine the file length struct stat filestat; if (stat(fileName, &filestat) == -1) { /* Opening file failed */ - fprintf(stderr,"TablLook - Cannot access or find table lookup file: %s !!!\n",fileName); - exit(0); + sprintf(msg, "TablLook: Couldn't stat or find file (%s).\n", fileName); + throw StkError(msg, 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,"rb"); - if (!fd) { - printf("TablLook - Couldn't open or find table lookup file %s !!!\n",fileName); - exit(0); + if (!fd) { + sprintf(msg, "TablLook: Couldn't open or find file (%s).\n", fileName); + throw StkError(msg, StkError::FILE_NOT_FOUND); } data = (MY_FLOAT *) new MY_FLOAT[length]; @@ -45,7 +45,7 @@ TablLook :: TablLook(char *fileName) double temp; while (fread(&temp,8,1,fd)) { #ifdef __LITTLE_ENDIAN__ - temp = SwapDouble(temp); + swap64((unsigned char *)&temp); #endif data[i++] = (MY_FLOAT) temp; } @@ -70,11 +70,13 @@ MY_FLOAT TablLook :: tick(MY_FLOAT index) static long temp; if (index > length-1) { - fprintf(stderr,"TablLook: Index (%f) exceeds table length ... sticking at end!\n", index); + fprintf(stderr, "TablLook: Index (%f) exceeds table length ... sticking at end!.", + index); index = length-1; } if (index < 0.0) { - fprintf(stderr,"TablLook: Index (%f) is less than zero ... setting to zero\n", index); + fprintf(stderr,"TablLook: Index (%f) is less than zero ... setting to zero\n", + index); index = 0.0; } diff --git a/STK/TubeBell.cpp b/src/TubeBell.cpp similarity index 100% rename from STK/TubeBell.cpp rename to src/TubeBell.cpp diff --git a/STK/TwoPole.cpp b/src/TwoPole.cpp similarity index 100% rename from STK/TwoPole.cpp rename to src/TwoPole.cpp diff --git a/STK/TwoZero.cpp b/src/TwoZero.cpp similarity index 100% rename from STK/TwoZero.cpp rename to src/TwoZero.cpp diff --git a/STK/VoicForm.cpp b/src/VoicForm.cpp similarity index 100% rename from STK/VoicForm.cpp rename to src/VoicForm.cpp diff --git a/STK/VoicMang.cpp b/src/VoicMang.cpp similarity index 93% rename from STK/VoicMang.cpp rename to src/VoicMang.cpp index 3dddba9..aaa1ac6 100644 --- a/STK/VoicMang.cpp +++ b/src/VoicMang.cpp @@ -31,9 +31,6 @@ #include "VoicMang.h" #include "Mandolin.h" -#include "Marimba.h" -#include "Vibraphn.h" -#include "AgogoBel.h" #include "Plucked.h" #include "Clarinet.h" #include "Flute.h" @@ -60,21 +57,6 @@ VoicMang :: VoicMang(int maxVoices, char *instrType) instrument[i] = new Mandolin((MY_FLOAT) 50.0); mute_time = 1000; } - else if (!strcmp(instrType,"Marimba")) { - for (i=0;i MAX_FILE_LOAD_SIZE) { + printf("\nWavWvIn: The .WAV file (%s) has more than %d samples and\n", + fileName, MAX_FILE_LOAD_SIZE); + printf("will be loaded incrementally from disk. Normalization will be disabled.\n"); + chunking = 1; + bufferSize = LOAD_BUFFER_SIZE; + } + + // Setup for looping or one-shot playback + if (!strcmp(mode,"looping")) + looping = 1; + else // default = oneshot + looping = 0; + + data = (MY_FLOAT *) new MY_FLOAT[(bufferSize+1)*channels]; + dataOffset = ftell(fd); + this->getData(0); // Read samples into data[] + + if (fmod(rate, 1.0) != 0.0) interpolate = 1; + else interpolate = 0; + phaseOffset = (MY_FLOAT) 0.0; + lastOutput = (MY_FLOAT *) new MY_FLOAT[channels]; + this->reset(); + + // finally, let's normalize the data by default + this->normalize(); +} + +WavWvIn :: ~WavWvIn() +{ +} + +void WavWvIn :: getData(long index) +{ + /* Compare index to current readPointer and modify as needed. + * The following while() loops will only execute on calls subsequent + * to class instantiation ... and thus, only when "chunking". + */ + while (index < readPointer) { + readPointer -= LOAD_BUFFER_SIZE; + bufferSize = LOAD_BUFFER_SIZE; + if (readPointer < 0) { + bufferSize += readPointer; + readPointer = 0; + } + } + while (index >= readPointer+bufferSize) { + readPointer += LOAD_BUFFER_SIZE; + bufferSize = LOAD_BUFFER_SIZE; + if (readPointer+LOAD_BUFFER_SIZE >= fileSize) { + bufferSize = fileSize - readPointer; + } + } + + fseek(fd, dataOffset+(long)(readPointer*channels*2), SEEK_SET); + long length = bufferSize; + int end_of_file = (readPointer+bufferSize == fileSize); + if (!end_of_file) length += 1; + + // Read samples into data[]. Use MY _FLOAT data structure to store INT16 samples + INT16 *buf = (INT16 *)data; + fread(buf, 2, length*channels, fd); + // Convert in place (unpack) to MY_FLOAT from the end of the array + for (int i=length*channels-1; i>=0; i--) { +#ifndef __LITTLE_ENDIAN__ + swap16((unsigned char *)(buf+i)); +#endif + data[i] = buf[i]; + if (chunking) data[i] *= 0.00003051; + } + + // fill in the extra sample frame for interpolation + if (end_of_file) { + for (int j=0; j 2) { - fprintf(stderr,"WavWvOut: Unsupported # of channels: %d\n", chans); - exit(0); + char msg[256]; + if (chans < 1) { + sprintf(msg, "WavWvOut: number of channels = %d not supported!\n", chans); + throw StkError(msg, StkError::FUNCTION_SYNTAX); } channels = chans; fd = openWAVFile(chans,fileName); - counter = 0; - totalCount = 0; + data_length = FILE_BUFFER_SIZE*channels; + data = (INT16 *) new INT16[data_length]; } WavWvOut :: ~WavWvOut() @@ -95,47 +89,39 @@ WavWvOut :: ~WavWvOut() INT32 bytes; fwrite(data,2,counter,fd); - fseek(fd,40,SEEK_SET); time = (double) totalCount * ONE_OVER_SRATE; - printf("%f Seconds Computed\n",time); + printf("%f Seconds Computed\n\n", time); + bytes = totalCount*2*channels; #ifndef __LITTLE_ENDIAN__ - bytes = SwapINT32(bytes); + swap32((unsigned char *)&bytes); #endif + fseek(fd,40,SEEK_SET); // jump to data length fwrite(&bytes,4,1,fd); + bytes = totalCount*2*channels + 44; #ifndef __LITTLE_ENDIAN__ - bytes = SwapINT32(bytes); + swap32((unsigned char *)&bytes); #endif - fseek(fd,4,SEEK_SET); + fseek(fd,4,SEEK_SET); // jump to file size fwrite(&bytes,4,1,fd); fclose(fd); } -long WavWvOut :: getCounter() -{ - return totalCount; -} - -MY_FLOAT WavWvOut :: getTime() -{ - return (MY_FLOAT) totalCount * ONE_OVER_SRATE; -} - void WavWvOut :: tick(MY_FLOAT sample) { - INT16 isample; + static INT16 isample; isample = (INT16) (sample * 32000.0); #ifndef __LITTLE_ENDIAN__ - isample = SwapINT16 (isample); + swap16 ((unsigned char *)&isample); #endif for (int i=0;i + +WvIn :: WvIn() +{ + fd = 0; + chunking = 0; + readPointer = 0; + fileSize = 0; +} + +WvIn :: ~WvIn() +{ + if (fd) { + fclose(fd); + fd = 0; + } + if (data) { + delete [ ] data; + data = 0; + } + if (lastOutput) { + delete [ ] lastOutput; + lastOutput = 0; + } +} + +void WvIn :: reset() +{ + finished = 0; + time = (MY_FLOAT) 0.0; + for (int i=0;inormalize((MY_FLOAT) 1.0); +} + +// Normalize all channels equally by the greatest magnitude in all of data +void WvIn :: normalize(MY_FLOAT newPeak) +{ + /* Do nothing for streamed input ... cannot be normalized */ + if (chunking) return; + + long i; + MY_FLOAT max = (MY_FLOAT) 0.0; + + for (i=0;i max) + max = (MY_FLOAT) fabs((double) data[i]); + } + if (max > 0.0) { + max = (MY_FLOAT) 1.0 / max; + max *= newPeak; + for (i=0;i<=channels*bufferSize;i++) + data[i] *= max; + } +} + +void WvIn :: setRate(MY_FLOAT aRate) +{ + rate = aRate; + + // If negative rate and at beginning of sound, move pointer to end of sound. + if ( (rate < 0) && (time == 0.0) ) time += rate + fileSize; + + if (fmod(rate, 1.0) != 0.0) interpolate = 1; + else interpolate = 0; +} + +void WvIn :: setFreq(MY_FLOAT aFreq) +{ + // This is a looping frequency. + if (looping) { + rate = fileSize * (MY_FLOAT) ONE_OVER_SRATE * aFreq; + if (fmod(rate, 1.0) != 0.0) interpolate = 1; + else interpolate = 0; + } +} + +void WvIn :: addTime(MY_FLOAT aTime) +{ + // Add an absolute time in samples + time += aTime; + + while (time < 0.0) + time += fileSize; + while (time >= fileSize) + time -= fileSize; +} + +void WvIn :: addPhase(MY_FLOAT anAngle) +{ + // Add a time in cycles (one cycle = fileSize) ... for looping. + if (looping) { + time += fileSize * anAngle; + + while (time < 0.0) + time += fileSize; + while (time >= fileSize) + time -= fileSize; + } +} + +void WvIn :: addPhaseOffset(MY_FLOAT anAngle) +{ + // Add a phase offset in cycles, where 1.0 = fileSize (looping). + if (looping) + phaseOffset = fileSize * anAngle; +} + +void WvIn :: setInterpolate(int anInterpStatus) +{ + interpolate = anInterpStatus; +} + +void WvIn :: setLooping(int aLoopStatus) +{ + time = (MY_FLOAT) 0.0; + looping = aLoopStatus; + + if (looping && !chunking) { + for (int i=0;iinformTick(); + if (channels > 1) { + MY_FLOAT tempout = 0.0; + for (int i=0;iinformTick(); + return lastOutput; +} + +int WvIn :: informTick() +{ + static MY_FLOAT temp, alpha; + static long index; + + if (finished) return finished; + + if (looping) { + // Check limits of time address ... if necessary, recalculate modulo fileSize. + while (time < 0.0) + time += fileSize; + while (time >= fileSize) + time -= fileSize; + + if (phaseOffset) { + temp = time + phaseOffset; + while (temp < 0.0) + temp += fileSize; + while (temp >= fileSize) + temp -= fileSize; + } + else { + temp = time; + } + } + else { + // oneshot: if out of bounds, we're done + if ( (time < 0.0) || (time >= fileSize) ) { + finished = 1; + return finished; + } + temp = time; + } + + if (chunking) { + // check the time address vs. our current buffer limits + if ( (temp < readPointer) || (temp >= readPointer+bufferSize) ) + this->getData((long) temp); + // adjust index for current buffer + temp -= readPointer; + } + + // integer part of time address + index = (long) temp; + + if (interpolate) { + // fractional part of time address + alpha = temp - (MY_FLOAT) index; + index *= channels; + for (int i=0;i 1) { + MY_FLOAT tempout = 0.0; + for (int i=0;iEZhBT6#la&)>ao1OI z`2;?J7p~>4K7!u*3NFR}PIAH_B{5-P2=za#e`Ze3p0nrtX1M6??BUm6F8}u34->zu zx-zG{>hFVo)#v)&gSMz#h86A~97x-#rH!vx&JlsXFjfQe=7lamy^zfL6Oa$;hX$ZQ zNapzx>LKV!2una+hDM;Lpi$^)NbH_LJq|q!O+e2<&qG(B7oZm*u?wTV3cU=y0=)`d zgC?Qt&<*G{NNnFgeG{63-h|$QrXfEx1Kone?j6+cLhnKEL$lBa&~4~LXbuv)JE-qM z^H2Z^LLq1Y`WU(giJfQ(?PX{Mia@K-8uSUY4n-lc`xNyi6oWp4wxG|UFQ7Q|B_wwD zQGX33pd^%n(vXI>p$sH;|8-ec7Jf>~z?++>i)tU9TQ6f+G0qre?KCTQ_P$R}UHZ`@ z@8#IV;Jv7Jl&uP2k;3~MU|B-DRA%AWHL4BOQ(mvKc4Zum?A+h?$b~FclzDi!)E@k6 zwAwGj@b5)8`8{dX|3z_A^&i5lXYsB=;Ur~9^?2lWReVcncUtVx(>NP2WN`rw{vGiCM)RyO2m}V=}t2G&yVdjY84-MyE>G?HfZ*9=WlNUiMJ! z!R5=!W9w|1eR*7WU)bEX4#(pj>PS$3t8-RC7mc-|mEKL2s&CTpMx}S%E7s2guStLe zNPq-LfCNZ@1W14cNPq-Lpj!zr{@blH!*P*7X9#TlREeFA*Mf34jaWD`<2Tkr%b~l` z&_(A)<P^Z}DqheQG$Brt%#|6M6g^z;HQ`(lYw>cOqer*X>}qU;ORa>4zd%>Q;41#1!@0TLhq5+DH*AOR8}0TLjAt|GwrUsp{B2SWlK zC(u{+h|Pbs-II*}we|O3xc{%?YnBd4fCNZ@1W14cNPq-LfCNZ@1ll9O_+NXxXiWl- H8-afSLeJ&( diff --git a/syntmono/STKdemo b/syntmono/STKdemo deleted file mode 100755 index 250acad..0000000 --- a/syntmono/STKdemo +++ /dev/null @@ -1 +0,0 @@ -wish < tcl/TCLDemo.tcl | syntmono Clarinet -r -ip diff --git a/syntmono/md2skini.plg b/syntmono/md2skini.plg deleted file mode 100755 index 90cdb8b..0000000 --- a/syntmono/md2skini.plg +++ /dev/null @@ -1,32 +0,0 @@ ---------------------Configuration: MD2SKINI - Win32 Release-------------------- -Begining build with project "C:\home\gary\stk\syntmono\MD2SKINI.DSP", at root. -Active configuration is Win32 (x86) Console Application (based on Win32 (x86) Console Application) - -Project's tools are: - "32-bit C/C++ Compiler for 80x86" with flags "/nologo /MT /W3 /GX /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__OS_Win_" /Fp"Release/MD2SKINI.pch" /YX /Fo"Release/" /Fd"Release/" /FD /c " - "Win32 Resource Compiler" with flags "/l 0x409 /d "NDEBUG" " - "Browser Database Maker" with flags "/nologo /o"MD2SKINI.bsc" " - "COFF Linker for 80x86" with flags "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 dsound.lib Wsock32.lib /nologo /subsystem:console /incremental:no /pdb:"MD2SKINI.pdb" /machine:I386 /out:"MD2SKINI.exe" " - "Custom Build" with flags "" - "" with flags "" - -Creating temp file "C:\WINDOWS\TEMP\RSPE245.TMP" with contents -Creating command line "cl.exe @C:\WINDOWS\TEMP\RSPE245.TMP" -Creating temp file "C:\WINDOWS\TEMP\RSPE246.TMP" with contents -Creating command line "link.exe @C:\WINDOWS\TEMP\RSPE246.TMP" -Compiling... -MD2SKINI.cpp -MIDIIO.cpp -Object.cpp -Linking... - - - -MD2SKINI.exe - 0 error(s), 0 warning(s) diff --git a/syntmono/miditabl.h b/syntmono/miditabl.h deleted file mode 100644 index 8938646..0000000 --- a/syntmono/miditabl.h +++ /dev/null @@ -1,19 +0,0 @@ -#include "../STK/Object.h" - -double __MIDI_To_Pitch[128] = { -8.18,8.66,9.18,9.72,10.30,10.91,11.56,12.25, -12.98,13.75,14.57,15.43,16.35,17.32,18.35,19.45, -20.60,21.83,23.12,24.50,25.96,27.50,29.14,30.87, -32.70,34.65,36.71,38.89,41.20,43.65,46.25,49.00, -51.91,55.00,58.27,61.74,65.41,69.30,73.42,77.78, -82.41,87.31,92.50,98.00,103.83,110.00,116.54,123.47, -130.81,138.59,146.83,155.56,164.81,174.61,185.00,196.00, -207.65,220.00,233.08,246.94,261.63,277.18,293.66,311.13, -329.63,349.23,369.99,392.00,415.30,440.00,466.16,493.88, -523.25,554.37,587.33,622.25,659.26,698.46,739.99,783.99, -830.61,880.00,932.33,987.77,1046.50,1108.73,1174.66,1244.51, -1318.51,1396.91,1479.98,1567.98,1661.22,1760.00,1864.66,1975.53, -2093.00,2217.46,2349.32,2489.02,2637.02,2793.83,2959.96,3135.96, -3322.44,3520.00,3729.31,3951.07,4186.01,4434.92,4698.64,4978.03, -5274.04,5587.65,5919.91,6271.93,6644.88,7040.00,7458.62,7902.13, -8372.02,8869.84,9397.27,9956.06,10548.08,11175.30,11839.82,12543.85}; diff --git a/syntmono/syntmono.cpp b/syntmono/syntmono.cpp deleted file mode 100644 index f4e4e28..0000000 --- a/syntmono/syntmono.cpp +++ /dev/null @@ -1,181 +0,0 @@ -// syntmono.cpp -// -// An example STK program for monophonic voice playback and control. - -#include "../STK/WvOut.h" -#include "../STK/Instrmnt.h" -#include "../STK/Reverb.h" -#include "../STK/NRev.h" -#include "../STK/PRCRev.h" -#include "../STK/JCRev.h" -#include "../STK/SKINI11.h" -#include "../STK/SKINI11.msg" -#include "miditabl.h" - -int numStrings = 0; -int notDone = 1; -char **inputString; - -// Miscellaneous command-line parsing and instrument allocation -// functions are defined in utilites.cpp. -#include "utilities.h" - -// The input command pipe and socket threads are defined in threads.cpp. -#include "threads.h" - -Instrmnt *instrument; -WvOut **output; - -int main(int argc,char *argv[]) -{ - long i, j, synlength; - int type, rtInput = 0; - int numOuts = 0, outOne = 0; - int instNum; - char *fin; - MY_FLOAT reverbTime = 0.5; // in seconds - MY_FLOAT temp, byte3, outSample, lastPitch=220.0; - - // Check the command-line arguments for errors and to determine - // the number of WvOut objects to be instantiated. - numOuts = checkArgs(argc, argv); - output = (WvOut **) malloc(numOuts * sizeof(WvOut *)); - - // Instantiate the instrument from the command-line argument. - if ( (instNum=newInstByName(argv[1])) < 0 ) usage(argv[0]); - - // Parse the command-line flags and instantiate WvOut objects. - rtInput = parseArgs(argc, argv); - - SKINI11 *score = new SKINI11(); - Reverb *reverb = new PRCRev(reverbTime); - reverb->setEffectMix(0.2); - - - // If using realtime input, start the input thread. - if (rtInput) { -#if defined(__STK_REALTIME_) - if (rtInput == 2) startSocketThread(); - else startPipeThread(); - instrument->noteOn(200.0,0.1); -#endif - } - else { // Malloc inputString as 1 x STRING_LEN array - inputString = (char **) malloc(sizeof(char *)); - inputString[0] = (char *) malloc(STRING_LEN * sizeof(char)); - } - - // The runtime loop begins here: - notDone = 1; - synlength = RT_BUFFER_SIZE; - while(notDone || numStrings) { - if (rtInput) { - if (numStrings > 1) synlength = (long) RT_BUFFER_SIZE / numStrings; - else synlength = RT_BUFFER_SIZE; - for ( i=0; itick(instrument->tick()); - for ( j=0; jtick(outSample); - } - } - else { - fin = fgets(inputString[0],STRING_LEN,stdin); - if (fin == NULL) notDone = 0; - else { - numStrings++; - } - } - if (numStrings) { - score->parseThis(inputString[outOne]); - type = score->getType(); - if (type > 0) { - // All realtime control messages should have a delta time = 0. - // If we find a non-zero delta time, we're assuming control is - // coming from a score file. - if ((temp = score->getDelta())) { /* SKINI score file */ - synlength = (long) (temp * SRATE); - for ( i=0; itick(instrument->tick()); - for ( j=0; jtick(outSample); - } - synlength = 0; - } - - switch(type) { - - case __SK_NoteOn_: - // check to see if velocity is zero ... really a NoteOff - if (( byte3 = score->getByteThree() ) == 0) - instrument->noteOff(0.0); - else { // really a NoteOn - j = (int) score->getByteTwo(); - lastPitch = __MIDI_To_Pitch[j]; - instrument->noteOn(lastPitch,byte3*NORM_7); - } - break; - - case __SK_NoteOff_: - instrument->noteOff(NORM_7*score->getByteThree()); - break; - - case __SK_ControlChange_: - instrument->controlChange((int)score->getByteTwo(), - score->getByteThree()); - break; - - case __SK_AfterTouch_: - instrument->controlChange(128,score->getByteTwo()); - break; - - case __SK_PitchBend_: - temp = score->getByteTwo(); - j = (int) temp; - temp -= j; // floating-point remainder - lastPitch = __MIDI_To_Pitch[j] * pow(2.0,temp / 12.0) ; - instrument->setFreq(lastPitch); - break; - - case __SK_ProgramChange_: - j = (int) score->getByteTwo(); - if (j != instNum) { - instrument->noteOff(1.0); - // let the old instrument settle a little - for (i=0;i<4096;i++) { - outSample = reverb->tick(instrument->tick()); - for ( int k=0; ktick(outSample); - } - delete instrument; - if ( (instNum=newInstByNum(j)) < 0 ) { - // Default instrument = 0 - instNum = newInstByNum(0); - } - instrument->noteOn(lastPitch, 0.2); - } - break; - } - } - if (rtInput) { - outOne += 1; - if (outOne == MAX_IN_STRINGS) outOne = 0; - } - numStrings--; - } - } - - for (i=0;itick(instrument->tick()); - for ( j=0; jtick(outSample); - } - - for ( i=0; i" with flags "" - -Creating temp file "C:\WINDOWS\TEMP\RSPC092.TMP" with contents -Creating command line "cl.exe @C:\WINDOWS\TEMP\RSPC092.TMP" -Creating temp file "C:\WINDOWS\TEMP\RSPC093.TMP" with contents -Creating command line "link.exe @C:\WINDOWS\TEMP\RSPC093.TMP" -Compiling... -utilities.cpp -BowedBar.cpp -Linking... - - - -syntmono.exe - 0 error(s), 0 warning(s) diff --git a/syntmono/threads.cpp b/syntmono/threads.cpp deleted file mode 100644 index 4313af0..0000000 --- a/syntmono/threads.cpp +++ /dev/null @@ -1,279 +0,0 @@ -// Thread functions for use with syntmono. -// -// No mutexes are currently being used when accessing -// the global variables shared between these threads -// and the main() routine. In a single processor -// environment, no problems have resulted from such data -// sharing. However, if STK is to be run on a true parallel -// processing platform, it is likely that mutexes will be -// necessary. While the mutex calls are simple to code, I -// am trying to keep the code as generic as possible. A -// quick investigation of threads under Windoze indicates -// that mutex functionality is not available, at least with -// the standard libraries. -// -// Gary P. Scavone, 2000. - -#include "threads.h" - -#if defined(__STK_REALTIME_) - -// Default STK socket port ID number -#define SERVICE_PORT 2001 - -// Do OS dependent declarations and includes -#if (defined(__OS_IRIX_) || defined(__OS_Linux_)) -#include -#include -#include -#include -#include -#include - -pthread_t string_thread; - -#elif defined(__OS_Win_) -#include -#include - -unsigned long string_thread; - -#endif - - -// The thread function protocols are slightly different -// under Windoze ... but of course! - -#if (defined(__OS_IRIX_) || defined(__OS_Linux_)) - -void *newStringByPipe(void *) - -#elif defined(__OS_Win_) - -void newStringByPipe(void *) - -#endif - -{ - extern int numStrings, notDone; - extern char **inputString; - int i; - - // Malloc inputString. - inputString = (char **) malloc(MAX_IN_STRINGS * sizeof(char *)); - for ( i=0;i MAX_IN_STRINGS) { - fprintf(stderr,"Losing MIDI data ... try increasing MAX_IN_STRINGS.\n"); - numStrings--; - } - inOne++; - if (inOne == MAX_IN_STRINGS) inOne = 0; - } - } - - // Free inputString. - for ( i=0;i maxfd) maxfd = accept_id; - FD_CLR(soc_id, &rmask); - } - for (fd=0;fd<=maxfd;fd++) { // look for other sockets with data - if (FD_ISSET(fd, &rmask)) { // process the data - parsing = 1; - while (parsing) { - i = recv(fd, socBuf, STRING_LEN,0); - if (i==0) { - printf("Closing a socket connection.\n"); - FD_CLR(fd, &mask); -#if defined(__OS_Win_) - closesocket(fd); -#else - close(fd); -#endif - parsing = 0; - } - n = 0; - while (n < i) { - inputString[inOne][m++] = socBuf[n]; - if (socBuf[n++] == '\n') { - if (inputString[inOne][2] == 'i' && inputString[inOne][3] == 't' - && inputString[inOne][1] == 'x' && inputString[inOne][0] == 'E') { - notDone = 0; - n = i; - parsing = 0; - } - else { - m = 0; - if (n >= i) parsing = 0; - numStrings++; - if (numStrings > MAX_IN_STRINGS) { - fprintf(stderr,"Losing MIDI data ... try increasing MAX_IN_STRINGS.\n"); - numStrings--; - } - inOne++; - if (inOne == MAX_IN_STRINGS) inOne = 0; - memset(inputString[inOne], 0, STRING_LEN); - } - } - } - } - } - } - } -#if defined(__OS_Win_) // Stupid Windoze only stuff - closesocket(soc_id); - WSACleanup(); -#else - shutdown(soc_id,0); -#endif - - // Free inputString. - for ( i=0;i for .snd output file,\n"); - printf(" -w for .wav output file,\n"); - printf(" -m for .mat output file,\n"); -#if defined(__STK_REALTIME_) - printf(" -r for realtime output,\n"); - printf(" -ip for realtime input by pipe (versus scorefile),\n"); - printf(" (won't work under Win95/98),\n"); - printf(" -is for realtime input by socket (versus scorefile),\n"); -#endif - printf(" and Instr = one of these:\n"); - for (i=0;i are not specified,\n"); - printf("default names will be indicated. Each flag must\n"); - printf("include its own '-' sign.\n\n"); - exit(0); -} - -int checkArgs(int numArgs, char *args[]) -{ - int w, i = 2, j = 0; - int numOutputs = 0; - char flags[16] = ""; - - if (numArgs < 3 || numArgs > 10) usage(args[0]); - - while (i < numArgs) { - if (args[i][0] == '-') { - if ( (args[i][1] == 'r') || (args[i][1] == 's') || - (args[i][1] == 'w') || (args[i][1] == 'm') ) - numOutputs++; - else if (args[i][1] == 'i') { - if ( (args[i][2] != 's') && (args[i][2] != 'p') ) usage(args[0]); - } - else usage(args[0]); - flags[j] = args[i][1]; - j++; - } - i++; - } - - /* Check for multiple flags of the same type */ - for (i=0; i<=j; i++) { - w = i+1; - while (w <= j) { - if (flags[i] == flags[w]) { - printf("\nError: Multiple command line flags of the same type specified.\n\n"); - usage(args[0]); - } - w++; - } - } - - /* Make sure we have at least one output type */ - if (numOutputs < 1) usage(args[0]); - - return numOutputs; -} - -int parseArgs(int numArgs, char *args[]) -{ - int i = 2, j = 0; - int realtime = 0; - char fileName[256]; - extern WvOut **output; - - while (i < numArgs) { - if (args[i][0] == '-') { - switch(args[i][1]) { - - case 'i': -#if defined(__STK_REALTIME_) - if (args[i][2] == 's') realtime = 2; - else realtime = 1; - break; -#else - usage(args[0]); -#endif - - case 'r': -#if defined(__STK_REALTIME_) - output[j] = new RTWvOut(SRATE,1); - j++; - break; -#else - usage(args[0]); -#endif - - case 'w': - if ((i+1 < numArgs) && args[i+1][0] != '-') { - i++; - strcpy(fileName,args[i]); - } - else strcpy(fileName,"testwav"); - output[j] = new WavWvOut(1,fileName); - j++; - break; - - case 's': - if ((i+1 < numArgs) && args[i+1][0] != '-') { - i++; - strcpy(fileName,args[i]); - } - else strcpy(fileName,"testsnd"); - output[j] = new SndWvOut(1,fileName); - j++; - break; - - case 'm': - if ((i+1 < numArgs) && args[i+1][0] != '-') { - i++; - strcpy(fileName,args[i]); - } - else strcpy(fileName,"testmat"); - output[j] = new MatWvOut(1,fileName); - j++; - break; - - default: - usage(args[0]); - break; - } - } - i++; - } - return realtime; -}